diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 42 | ||||
-rw-r--r-- | clang/test/Sema/scope-check.c | 9 |
3 files changed, 41 insertions, 13 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9b9b2a1d394..8ee940310b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -836,6 +836,9 @@ def err_switch_into_protected_scope : Error< "illegal switch case into protected scope">; def err_indirect_goto_in_protected_scope : Error< "illegal indirect goto in protected scope, unknown effect on scopes">; +def err_addr_of_label_in_protected_scope : Error< + "address taken of label in protected scope, jump to it would have " + "unknown effect on scope">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla : Note< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2aaa1bc940c..3a1217a8393 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2988,7 +2988,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { if (isa<LabelStmt>(S) || isa<DefaultStmt>(S) || isa<CaseStmt>(S)) { LabelAndGotoScopes[S] = ParentScope; } else if (isa<GotoStmt>(S) || isa<SwitchStmt>(S) || - isa<IndirectGotoStmt>(S)) { + isa<IndirectGotoStmt>(S) || isa<AddrLabelExpr>(S)) { // Remember both what scope a goto is in as well as the fact that we have // it. This makes the second scan not have to walk the AST again. LabelAndGotoScopes[S] = ParentScope; @@ -3082,19 +3082,41 @@ void JumpScopeChecker::VerifyJumps() { } + unsigned DiagnosticScope; + // We don't know where an indirect goto goes, require that it be at the // top level of scoping. - assert(isa<IndirectGotoStmt>(Jump)); - assert(LabelAndGotoScopes.count(Jump) &&"Jump didn't get added to scopes?"); - unsigned GotoScope = LabelAndGotoScopes[Jump]; - if (GotoScope == 0) continue; - S.Diag(Jump->getLocStart(), diag::err_indirect_goto_in_protected_scope); + if (IndirectGotoStmt *IG = dyn_cast<IndirectGotoStmt>(Jump)) { + assert(LabelAndGotoScopes.count(Jump) && + "Jump didn't get added to scopes?"); + unsigned GotoScope = LabelAndGotoScopes[IG]; + if (GotoScope == 0) continue; // indirect jump is ok. + S.Diag(IG->getGotoLoc(), diag::err_indirect_goto_in_protected_scope); + DiagnosticScope = GotoScope; + } else { + // We model &&Label as a jump for purposes of scope tracking. We actually + // don't care *where* the address of label is, but we require the *label + // itself* to be in scope 0. If it is nested inside of a VLA scope, then + // it is possible for an indirect goto to illegally enter the VLA scope by + // indirectly jumping to the label. + assert(isa<AddrLabelExpr>(Jump) && "Unknown jump type"); + LabelStmt *TheLabel = cast<AddrLabelExpr>(Jump)->getLabel(); + + assert(LabelAndGotoScopes.count(TheLabel) && + "Referenced label didn't get added to scopes?"); + unsigned LabelScope = LabelAndGotoScopes[TheLabel]; + if (LabelScope == 0) continue; // Addr of label is ok. - while (GotoScope != 0) { - S.Diag(Scopes[GotoScope].Loc, Scopes[GotoScope].Diag); - GotoScope = Scopes[GotoScope].ParentScope; + S.Diag(Jump->getLocStart(), diag::err_addr_of_label_in_protected_scope); + DiagnosticScope = LabelScope; + } + + // Report all the things that would be skipped over by this &&label or + // indirect goto. + while (DiagnosticScope != 0) { + S.Diag(Scopes[DiagnosticScope].Loc, Scopes[DiagnosticScope].Diag); + DiagnosticScope = Scopes[DiagnosticScope].ParentScope; } - continue; } } diff --git a/clang/test/Sema/scope-check.c b/clang/test/Sema/scope-check.c index 4605e02b880..83b84777a93 100644 --- a/clang/test/Sema/scope-check.c +++ b/clang/test/Sema/scope-check.c @@ -136,14 +136,17 @@ void test9(int n, void *P) { goto *P; // ok. L2: ; - int a[n]; // expected-note {{jump bypasses initialization of variable length array}} + int a[n]; // expected-note 2 {{jump bypasses initialization of variable length array}} L3: +L4: goto *P; // expected-error {{illegal indirect goto in protected scope, unknown effect on scopes}} + goto L3; // ok + goto L4; // ok void *Ptrs[] = { - &&L2, - &&L3 // FIXME: Not Ok. + &&L2, // Ok. + &&L3 // expected-error {{address taken of label in protected scope, jump to it would have unknown effect on scope}} }; } |