From: Chris Lattner Date: Sat, 18 Apr 2009 19:50:02 +0000 (+0000) Subject: Improve switch diagnostic to emit the "jump" message on the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a9768b72bb5ea061c9f10d6aa51b3be3241f3ec2;p=clang Improve switch diagnostic to emit the "jump" message on the specific bad case instead of on the switch. Putting it on the switch means you don't know what case is the problem. For example: scope-check.c:54:3: error: illegal switch case into protected scope case 2: ^ scope-check.c:53:9: note: jump bypasses initialization of variable length array int a[x]; ^ git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69462 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9560614058..f0a7e848db 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -833,7 +833,7 @@ def err_undeclared_label_use : Error<"use of undeclared label '%0'">; def err_goto_into_protected_scope : Error<"illegal goto into protected scope">; def err_switch_into_protected_scope : Error< - "illegal switch into protected scope">; + "illegal switch case into protected scope">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; def note_protected_by_vla : Note< diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 48351407d9..814b730575 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2953,7 +2953,8 @@ private: bool StatementCreatesScope(DeclStmt *S, unsigned ParentScope); void BuildScopeInformation(Stmt *S, unsigned ParentScope); void VerifyJumps(); - void CheckJump(Stmt *S, unsigned JumpTargetScope, unsigned JumpDiag); + void CheckJump(Stmt *From, Stmt *To, + SourceLocation DiagLoc, unsigned JumpDiag); }; } // end anonymous namespace @@ -3067,14 +3068,13 @@ void JumpScopeChecker::VerifyJumps() { Stmt *Jump = Jumps.pop_back_val(); if (GotoStmt *GS = dyn_cast(Jump)) { - assert(LabelAndGotoScopes.count(GS->getLabel()) && "Label not visited?"); - CheckJump(GS, LabelAndGotoScopes[GS->getLabel()], + CheckJump(GS, GS->getLabel(), GS->getGotoLoc(), diag::err_goto_into_protected_scope); } else if (SwitchStmt *SS = dyn_cast(Jump)) { for (SwitchCase *SC = SS->getSwitchCaseList(); SC; SC = SC->getNextSwitchCase()) { assert(LabelAndGotoScopes.count(SC) && "Case not visited?"); - CheckJump(SS, LabelAndGotoScopes[SC], + CheckJump(SS, SC, SC->getLocStart(), diag::err_switch_into_protected_scope); } continue; @@ -3088,22 +3088,25 @@ void JumpScopeChecker::VerifyJumps() { /// CheckJump - Validate that the specified jump statement is valid: that it is /// jumping within or out of its current scope, not into a deeper one. -void JumpScopeChecker::CheckJump(Stmt *Jump, unsigned JumpTargetScope, - unsigned JumpDiag) { - assert(LabelAndGotoScopes.count(Jump) && "Jump didn't get added to scopes?"); - unsigned JumpScope = LabelAndGotoScopes[Jump]; +void JumpScopeChecker::CheckJump(Stmt *From, Stmt *To, + SourceLocation DiagLoc, unsigned JumpDiag) { + assert(LabelAndGotoScopes.count(From) && "Jump didn't get added to scopes?"); + unsigned FromScope = LabelAndGotoScopes[From]; + assert(LabelAndGotoScopes.count(To) && "Jump didn't get added to scopes?"); + unsigned ToScope = LabelAndGotoScopes[To]; + // Common case: exactly the same scope, which is fine. - if (JumpScope == JumpTargetScope) return; + if (FromScope == ToScope) return; // The only valid mismatch jump case happens when the jump is more deeply // nested inside the jump target. Do a quick scan to see if the jump is valid // because valid code is more common than invalid code. - unsigned TestScope = Scopes[JumpScope].ParentScope; + unsigned TestScope = Scopes[FromScope].ParentScope; while (TestScope != ~0U) { // If we found the jump target, then we're jumping out of our current scope, // which is perfectly fine. - if (TestScope == JumpTargetScope) return; + if (TestScope == ToScope) return; // Otherwise, scan up the hierarchy. TestScope = Scopes[TestScope].ParentScope; @@ -3111,23 +3114,23 @@ void JumpScopeChecker::CheckJump(Stmt *Jump, unsigned JumpTargetScope, // If we get here, then we know we have invalid code. Diagnose the bad jump, // and then emit a note at each VLA being jumped out of. - S.Diag(Jump->getLocStart(), JumpDiag); + S.Diag(DiagLoc, JumpDiag); // FIXME: This is N^2 and silly. while (1) { // Diagnose that the jump jumps over this declaration. - const GotoScope &TargetScope = Scopes[JumpTargetScope]; + const GotoScope &TargetScope = Scopes[ToScope]; S.Diag(TargetScope.Loc, TargetScope.Diag); // Walk out one level. - JumpTargetScope = Scopes[JumpTargetScope].ParentScope; - assert(JumpTargetScope != ~0U && "Didn't find top-level function scope?"); + ToScope = Scopes[ToScope].ParentScope; + assert(ToScope != ~0U && "Didn't find top-level function scope?"); // Check to see if the jump is valid now. - unsigned TestScope = JumpScope; + unsigned TestScope = FromScope; while (TestScope != ~0U) { // If we found the jump target, the the jump became valid. - if (TestScope == JumpTargetScope) return; + if (TestScope == ToScope) return; // Otherwise, scan up the hierarchy. TestScope = Scopes[TestScope].ParentScope; diff --git a/test/Sema/scope-check.c b/test/Sema/scope-check.c index 59d4d134a8..93120cdf94 100644 --- a/test/Sema/scope-check.c +++ b/test/Sema/scope-check.c @@ -47,11 +47,11 @@ int test6() { } void test7(int x) { -foo: - switch (x) { // expected-error {{illegal switch into protected scope}} +foo: // FIXME: remove + switch (x) { case 1: ; int a[x]; // expected-note {{jump bypasses initialization of variable length array}} - case 2: + case 2: // expected-error {{illegal switch case into protected scope}} a[1] = 2; break; }