[cfe-commits] r69477 - in /cfe/trunk: include/clang/AST/Stmt.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDecl.cpp test/SemaObjC/scope-check.m

Chris Lattner sabre at nondot.org
Sat Apr 18 14:28:53 PDT 2009


Author: lattner
Date: Sat Apr 18 16:28:52 2009
New Revision: 69477

URL: http://llvm.org/viewvc/llvm-project?rev=69477&view=rev
Log:
reject invalid jumps among pieces of @try blocks.  This seems to work
reasonably well except for the problem that @catches are nested within
each other in the AST, giving the ugly diagnostics in L8.


Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/SemaObjC/scope-check.m

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=69477&r1=69476&r2=69477&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Sat Apr 18 16:28:52 2009
@@ -1290,6 +1290,7 @@
     return ExceptionDecl; 
   }
   
+  SourceLocation getAtCatchLoc() const { return AtCatchLoc; }
   SourceLocation getRParenLoc() const { return RParenLoc; }
   
   virtual SourceRange getSourceRange() const { 
@@ -1319,13 +1320,15 @@
   : Stmt(ObjCAtFinallyStmtClass), 
     AtFinallyStmt(atFinallyStmt), AtFinallyLoc(atFinallyLoc) {}
   
-  const Stmt *getFinallyBody () const { return AtFinallyStmt; }
-  Stmt *getFinallyBody () { return AtFinallyStmt; }
+  const Stmt *getFinallyBody() const { return AtFinallyStmt; }
+  Stmt *getFinallyBody() { return AtFinallyStmt; }
 
   virtual SourceRange getSourceRange() const { 
     return SourceRange(AtFinallyLoc, AtFinallyStmt->getLocEnd()); 
   }
   
+  SourceLocation getAtFinallyLoc() const { return AtFinallyLoc; }
+  
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == ObjCAtFinallyStmtClass;
   }

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=69477&r1=69476&r2=69477&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Apr 18 16:28:52 2009
@@ -842,6 +842,10 @@
   "jump bypasses initialization of declaration with __attribute__((cleanup))">;
 def note_protected_by_objc_try : Note<
   "jump bypasses initialization of @try block">;
+def note_protected_by_objc_catch : Note<
+  "jump bypasses initialization of @catch block">;
+def note_protected_by_objc_finally : Note<
+  "jump bypasses initialization of @finally block">;
 
 def err_func_returning_array_function : Error<
   "function cannot return array or function type %0">;

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=69477&r1=69476&r2=69477&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Apr 18 16:28:52 2009
@@ -3022,6 +3022,13 @@
     // it.  This makes the second scan not have to walk the AST again.
     LabelAndGotoScopes[S] = ParentScope;
     Jumps.push_back(S);
+  } else if (ObjCAtCatchStmt *AC = dyn_cast<ObjCAtCatchStmt>(S)) {
+    // @catch always starts a new scope.
+    // FIXME: We have to do this because @catches are nested inside each other,
+    // which seems weird and causes us to emit wierd diagnostics.
+    Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_catch,
+                               AC->getAtCatchLoc()));
+    ParentScope = Scopes.size()-1;
   }
 
   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end(); CI != E;
@@ -3050,10 +3057,24 @@
     // Disallow jumps into any part of an @try statement by pushing a scope and
     // walking all sub-stmts in that scope.
     if (ObjCAtTryStmt *AT = dyn_cast<ObjCAtTryStmt>(SubStmt)) {
-      Scopes.push_back(GotoScope(ParentScope, diag::note_protected_by_objc_try,
+      // Recursively walk the AST for the @try part.
+      Scopes.push_back(GotoScope(ParentScope,diag::note_protected_by_objc_try,
                                  AT->getAtTryLoc()));
-      // Recursively walk the AST.
-      BuildScopeInformation(SubStmt, Scopes.size()-1);
+      if (Stmt *TryPart = AT->getTryBody())
+        BuildScopeInformation(TryPart, Scopes.size()-1);
+
+      // Jump from the catch or finally to the try is not valid.
+      if (ObjCAtCatchStmt *AC = AT->getCatchStmts())
+        // @catches are nested and it isn't 
+        BuildScopeInformation(AC, ParentScope);
+      
+      if (ObjCAtFinallyStmt *AF = AT->getFinallyStmt()) {
+        Scopes.push_back(GotoScope(ParentScope,
+                                   diag::note_protected_by_objc_finally,
+                                   AF->getAtFinallyLoc()));
+        BuildScopeInformation(AF, Scopes.size()-1);
+      }
+      
       continue;
     }
     // FIXME: what about jumps into C++ catch blocks, what are the rules?

Modified: cfe/trunk/test/SemaObjC/scope-check.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/scope-check.m?rev=69477&r1=69476&r2=69477&view=diff

==============================================================================
--- cfe/trunk/test/SemaObjC/scope-check.m (original)
+++ cfe/trunk/test/SemaObjC/scope-check.m Sat Apr 18 16:28:52 2009
@@ -6,15 +6,46 @@
   goto L; // expected-error{{illegal goto into protected scope}}
   goto L2; // expected-error{{illegal goto into protected scope}}
   goto L3; // expected-error{{illegal goto into protected scope}}
-  @try {   // expected-note 3 {{jump bypasses initialization of @try block}}
+  @try {   // expected-note {{jump bypasses initialization of @try block}}
 L: ;
-  } @catch (A *x) {
+  } @catch (A *x) { // expected-note {{jump bypasses initialization of @catch block}}
 L2: ;
   } @catch (B *x) {
   } @catch (C *c) {
-  } @finally {
+  } @finally {// expected-note {{jump bypasses initialization of @finally block}}
 L3: ;
   }
+  
+  @try {
+    goto L4; // expected-error{{illegal goto into protected scope}}
+    goto L5; // expected-error{{illegal goto into protected scope}}
+  } @catch (C *c) { // expected-note {{jump bypasses initialization of @catch block}}
+  L5: ;
+    goto L6; // expected-error{{illegal goto into protected scope}}
+  } @catch (B *c) { // expected-note {{jump bypasses initialization of @catch block}}
+  L6: ;
+  } @finally { // expected-note {{jump bypasses initialization of @finally block}}
+  L4: ;
+  }
+ 
+  
+  @try { // expected-note 2 {{jump bypasses initialization of @try block}}
+  L7: ;
+  } @catch (C *c) {
+    goto L7; // expected-error{{illegal goto into protected scope}}
+  } @finally {
+    goto L7; // expected-error{{illegal goto into protected scope}}
+  }
+  
+  goto L8;  // expected-error{{illegal goto into protected scope}}
+  @try { 
+  } @catch (A *c) { // expected-note {{jump bypasses initialization of @catch block}}
+  } @catch (B *c) { // expected-note {{jump bypasses initialization of @catch block}}
+  } @catch (C *c) { // expected-note {{jump bypasses initialization of @catch block}}
+  L8: ;
+  }
+  
+  
 }
 
 void test2(int a) {





More information about the cfe-commits mailing list