case _Panic:
// panic(x)
+ // record panic call if inside a function with result parameters
+ // (for use in Checker.isTerminating)
+ if check.sig.results.Len() > 0 {
+ // function has result parameters
+ p := check.isPanic
+ if p == nil {
+ // allocate lazily
+ p = make(map[*ast.CallExpr]bool)
+ check.isPanic = p
+ }
+ p[call] = true
+ }
+
check.assignment(x, &emptyInterface, "argument to panic")
if x.mode == invalid {
return
// A context represents the context within which an object is type-checked.
type context struct {
- decl *declInfo // package-level declaration whose init expression/function body is checked
- scope *Scope // top-most scope for lookups
- pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
- iota constant.Value // value of iota in a constant declaration; nil otherwise
- sig *Signature // function signature if inside a function; nil otherwise
- hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions
- hasCallOrRecv bool // set if an expression contains a function call or channel receive operation
+ decl *declInfo // package-level declaration whose init expression/function body is checked
+ scope *Scope // top-most scope for lookups
+ pos token.Pos // if valid, identifiers are looked up as if at position pos (used by Eval)
+ iota constant.Value // value of iota in a constant declaration; nil otherwise
+ sig *Signature // function signature if inside a function; nil otherwise
+ isPanic map[*ast.CallExpr]bool // set of panic call expressions (used for termination check)
+ hasLabel bool // set if a function makes use of labels (only ~1% of functions); unused outside functions
+ hasCallOrRecv bool // set if an expression contains a function call or channel receive operation
}
// lookup looks up name in the current context and returns the matching object, or nil.
return check.isTerminating(s.Stmt, s.Label.Name)
case *ast.ExprStmt:
- // the predeclared (possibly parenthesized) panic() function is terminating
- if call, _ := unparen(s.X).(*ast.CallExpr); call != nil {
- if id, _ := call.Fun.(*ast.Ident); id != nil {
- if _, obj := check.scope.LookupParent(id.Name, token.NoPos); obj != nil {
- if b, _ := obj.(*Builtin); b != nil && b.id == _Panic {
- return true
- }
- }
- }
+ // calling the predeclared (possibly parenthesized) panic() function is terminating
+ if call, ok := unparen(s.X).(*ast.CallExpr); ok && check.isPanic[call] {
+ return true
}
case *ast.ReturnStmt:
}
; ; ;
} /* ERROR "missing return" */
+
+func parenPanic() int {
+ ((((((panic)))(0))))
+}
+
+func issue23218a() int {
+ {
+ panic := func(interface{}){}
+ panic(0)
+ }
+} /* ERROR "missing return" */
+
+func issue23218b() int {
+ {
+ panic := func(interface{}){}
+ ((((panic))))(0)
+ }
+} /* ERROR "missing return" */