]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6243503> [sema] @throw; accepted outside catch block.
authorSteve Naroff <snaroff@apple.com>
Wed, 11 Feb 2009 20:05:44 +0000 (20:05 +0000)
committerSteve Naroff <snaroff@apple.com>
Wed, 11 Feb 2009 20:05:44 +0000 (20:05 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64318 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/PrintParserCallbacks.cpp
include/clang/Basic/DiagnosticSemaKinds.def
include/clang/Parse/Action.h
include/clang/Parse/Scope.h
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.h
lib/Sema/SemaStmt.cpp
test/SemaObjC/try-catch.m

index b8957e520cf119658e1cd5f6783b20fbf5e30318..e3850bab56c78634e036b500fe4bda21ec9cc24f 100644 (file)
@@ -402,7 +402,8 @@ namespace {
     }
 
     virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
-                                                  ExprArg Throw) {
+                                                  ExprArg Throw,
+                                                  Scope *CurScope) {
       llvm::cout << __FUNCTION__ << "\n";
       return StmtEmpty();
     }
index 34fc2e8ef752f82313b2e89937d7e3f6ab30f5c4..b354bf87676d728f863e1f8962d1b0056bbf572c 100644 (file)
@@ -869,6 +869,8 @@ DIAG(error_bad_receiver_type, ERROR,
      "bad receiver type %0")
 DIAG(warn_objc_throw_expects_object, WARNING,
      "invalid %0 argument (expected an ObjC object type)")
+DIAG(error_rethrow_used_outside_catch, ERROR,
+     "‘@throw’ (rethrow) used outside of a @catch block")
 
 
 // C++ casts
index 3c2ecfb0ebd8af2b3b8b92cc2799083f850ec628..4b2bdd27146bfa1780ad77de8b493e9db1d4bf97 100644 (file)
@@ -514,7 +514,8 @@ public:
   }
 
   virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
-                                                ExprArg Throw) {
+                                                ExprArg Throw,
+                                                Scope *CurScope) {
     return StmtEmpty();
   }
 
index edbc52730d73f5a5726f74f2e83099c4aed0f1c8..2efb809bbcca4be3f0179ba5cdaae85edb52eb22 100644 (file)
@@ -64,7 +64,11 @@ public:
 
     /// FunctionPrototypeScope - This is a scope that corresponds to the
     /// parameters within a function prototype.
-    FunctionPrototypeScope = 0x100
+    FunctionPrototypeScope = 0x100,
+    
+    /// AtCatchScope - This is a scope that corresponds to the Objective-C
+    /// @catch statement.
+    AtCatchScope = 0x200
   };
 private:
   /// The parent scope for this scope.  This is null for the translation-unit
@@ -77,7 +81,7 @@ private:
   
   /// Flags - This contains a set of ScopeFlags, which indicates how the scope
   /// interrelates with other control flow statements.
-  unsigned Flags : 9;
+  unsigned Flags : 10;
   
   /// WithinElse - Whether this scope is part of the "else" branch in
   /// its parent ControlScope.
@@ -231,6 +235,11 @@ public:
     return getFlags() & Scope::FunctionPrototypeScope;
   }
 
+  /// isAtCatchScope - Return true if this scope is @catch.
+  bool isAtCatchScope() const {
+    return getFlags() & Scope::AtCatchScope;
+  }
+
   /// isWithinElse - Whether we are within the "else" of the
   /// ControlParent (if any).
   bool isWithinElse() const { return WithinElse; }
index f45562644f3134e6d94f56a75ac52a9aa80bed1e..338e770cd6954583d9c1aef6a22732ad6e022562 100644 (file)
@@ -1202,7 +1202,7 @@ Parser::OwningStmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
     }
   }
   ConsumeToken(); // consume ';'
-  return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res));
+  return Actions.ActOnObjCAtThrowStmt(atLoc, move(Res), CurScope);
 }
 
 /// objc-synchronized-statement:
@@ -1284,7 +1284,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
       ConsumeToken(); // consume catch
       if (Tok.is(tok::l_paren)) {
         ConsumeParen();
-        ParseScope CatchScope(this, Scope::DeclScope);
+        ParseScope CatchScope(this, Scope::DeclScope|Scope::AtCatchScope);
         if (Tok.isNot(tok::ellipsis)) {
           DeclSpec DS;
           ParseDeclarationSpecifiers(DS);
index c236b89a5ed3d82339342a9ba13d5003998dba5e..aafddc5a03835d761978c47935de54ed86518b94 100644 (file)
@@ -1033,7 +1033,8 @@ public:
                                               StmtArg Catch, StmtArg Finally);
 
   virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc,
-                                                ExprArg Throw);
+                                                ExprArg Throw, 
+                                                Scope *CurScope);
   virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc,
                                                        ExprArg SynchExpr,
                                                        StmtArg SynchBody);
index f4eb22df1f43fc049c367dc294765eb49b8e54e1..989de0cdbf7a7b44ada32b2fc401aee8eabf7b82 100644 (file)
@@ -981,10 +981,17 @@ Sema::ActOnObjCAtTryStmt(SourceLocation AtLoc,
 }
 
 Action::OwningStmtResult
-Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg expr) {
+Sema::ActOnObjCAtThrowStmt(SourceLocation AtLoc, ExprArg expr,
+                           Scope *CurScope) {
   Expr *ThrowExpr = static_cast<Expr*>(expr.release());
   if (!ThrowExpr) {
-    // FIXME: verify the 'rethrow' is within a @catch block
+    // @throw without an expression designates a rethrow (which much occur
+    // in the context of an @catch clause).
+    Scope *AtCatchParent = CurScope;
+    while (AtCatchParent && !AtCatchParent->isAtCatchScope())
+      AtCatchParent = AtCatchParent->getParent();
+    if (!AtCatchParent)
+      Diag(AtLoc, diag::error_rethrow_used_outside_catch);
   } else {
     QualType ThrowType = ThrowExpr->getType();
     // Make sure the expression type is an ObjC pointer or "void *".
index 00f1129d31bfeab2f6224d382e26afb4aba87408..bb8b8491d66fe02276a76404e97697ed47c1c099 100644 (file)
@@ -39,5 +39,5 @@ typedef struct _NSZone NSZone;
 
 int foo() {
   @throw 42; // expected-warning {{invalid 'int' argument (expected an ObjC object type)}}
-  @throw; // FIXME: error: ‘@throw’ (rethrow) used outside of a @catch block
+  @throw; // expected-error {{‘@throw’ (rethrow) used outside of a @catch block}}
 }