]> granicus.if.org Git - clang/commitdiff
Improve switch diagnostic to emit the "jump" message on the
authorChris Lattner <sabre@nondot.org>
Sat, 18 Apr 2009 19:50:02 +0000 (19:50 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 18 Apr 2009 19:50:02 +0000 (19:50 +0000)
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

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/Sema/scope-check.c

index 9560614058f4dd716ce0a60c4ce10c9c98b7bc21..f0a7e848dbbc2d67287fc7c9c955785a96e85916 100644 (file)
@@ -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<
index 48351407d9893f85fe1bb2b60d4e50f3a1f7b65c..814b730575f00bc307dfcd12371a8d99ff17cf86 100644 (file)
@@ -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<GotoStmt>(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<SwitchStmt>(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;
index 59d4d134a81792af3d652f4359575cd24d66aef1..93120cdf9491c40953906eceb8d2f0a679d023ca 100644 (file)
@@ -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;
   }