]> granicus.if.org Git - clang/commitdiff
Fix <rdar://problem/6640991> Exception handling executes wrong clause (Daniel, please...
authorSteve Naroff <snaroff@apple.com>
Tue, 3 Mar 2009 19:52:17 +0000 (19:52 +0000)
committerSteve Naroff <snaroff@apple.com>
Tue, 3 Mar 2009 19:52:17 +0000 (19:52 +0000)
Also necessary to fix:

<rdar://problem/6632061> [sema] non object types should not be allowed in @catch statements
<rdar://problem/6252237> [sema] qualified id should be disallowed in @catch statements

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65964 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/PrintParserCallbacks.cpp
Driver/RewriteObjC.cpp
include/clang/AST/Stmt.h
include/clang/Parse/Action.h
lib/AST/Stmt.cpp
lib/AST/StmtPrinter.cpp
lib/CodeGen/CGObjCMac.cpp
lib/Parse/ParseObjc.cpp
lib/Sema/Sema.h
lib/Sema/SemaStmt.cpp

index bc28db525b1c9257bb005b237e24dc252ce5016e..b14f2660b86d4dc528937e25e8c0da097fe4478e 100644 (file)
@@ -382,7 +382,7 @@ namespace {
     // Objective-c statements
     virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                                                   SourceLocation RParen,
-                                                  StmtArg Parm, StmtArg Body,
+                                                  DeclTy *Parm, StmtArg Body,
                                                   StmtArg CatchList) {
       llvm::cout << __FUNCTION__ << "\n";
       return StmtEmpty();
index 7293201166e127d6760eb6b1390250c8564d8da5..c4f67627ceccc7d8b6a7574ac22a199c4ec50540 100644 (file)
@@ -1567,7 +1567,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
   bool sawIdTypedCatch = false;
   Stmt *lastCatchBody = 0;
   while (catchList) {
-    Stmt *catchStmt = catchList->getCatchParamStmt();
+    ParmVarDecl *catchDecl = catchList->getCatchParamDecl();
 
     if (catchList == S->getCatchStmts()) 
       buf = "if ("; // we are generating code for the first catch clause
@@ -1592,8 +1592,8 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
       buf += "1) { id _tmp = _caught;";
       Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, 
                           buf.c_str(), buf.size());      
-    } else if (DeclStmt *declStmt = dyn_cast<DeclStmt>(catchStmt)) {
-      QualType t = dyn_cast<ValueDecl>(declStmt->getSolitaryDecl())->getType();
+    } else if (catchDecl) {
+      QualType t = catchDecl->getType();
       if (t == Context->getObjCIdType()) {
         buf += "1) { ";
         ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
@@ -1622,7 +1622,7 @@ Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
       // Here we replace ") {" with "= _caught;" (which initializes and 
       // declares the @catch parameter).
       ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size());
-    } else if (!isa<NullStmt>(catchStmt)) {
+    } else {
       assert(false && "@catch rewrite bug");
     }
     // make sure all the catch bodies get rewritten!
index c4c2291f2c081d2d9d801750e4796866786b8d35..0e2daed91c8292dae1097e7290ea458577127653 100644 (file)
@@ -31,6 +31,7 @@ namespace clang {
   class ASTContext;
   class Expr;
   class Decl;
+  class ParmVarDecl;
   class QualType;
   class IdentifierInfo;
   class SourceManager;
@@ -1056,7 +1057,8 @@ public:
 /// ObjCAtCatchStmt - This represents objective-c's @catch statement.
 class ObjCAtCatchStmt : public Stmt {
 private:
-  enum { SELECTOR, BODY, NEXT_CATCH, END_EXPR };
+  enum { BODY, NEXT_CATCH, END_EXPR };
+  ParmVarDecl *ExceptionDecl;
   Stmt *SubExprs[END_EXPR];
   SourceLocation AtCatchLoc, RParenLoc;
 
@@ -1066,7 +1068,7 @@ private:
 
 public:
   ObjCAtCatchStmt(SourceLocation atCatchLoc, SourceLocation rparenloc,
-                  DeclStmt *catchVarStmtDecl, 
+                  ParmVarDecl *catchVarDecl, 
                   Stmt *atCatchStmt, Stmt *atCatchList);
   
   const Stmt *getCatchBody() const { return SubExprs[BODY]; }
@@ -1079,10 +1081,11 @@ public:
     return static_cast<ObjCAtCatchStmt*>(SubExprs[NEXT_CATCH]);
   }
 
-  const DeclStmt *getCatchParamStmt() const { 
-    return static_cast<const DeclStmt*>(SubExprs[SELECTOR]); }
-  DeclStmt *getCatchParamStmt() { 
-    return static_cast<DeclStmt*>(SubExprs[SELECTOR]); 
+  const ParmVarDecl *getCatchParamDecl() const { 
+    return ExceptionDecl; 
+  }
+  ParmVarDecl *getCatchParamDecl() { 
+    return ExceptionDecl; 
   }
   
   SourceLocation getRParenLoc() const { return RParenLoc; }
@@ -1091,7 +1094,7 @@ public:
     return SourceRange(AtCatchLoc, SubExprs[BODY]->getLocEnd()); 
   }
 
-  bool hasEllipsis() const { return getCatchParamStmt() == 0; }
+  bool hasEllipsis() const { return getCatchParamDecl() == 0; }
   
   static bool classof(const Stmt *T) {
     return T->getStmtClass() == ObjCAtCatchStmtClass;
index 9b4e9802dcb3c5ed97518c9d8924657357b3cced..e1ed5cd10943caa1485f90b3cab9aaf7f55083f3 100644 (file)
@@ -500,7 +500,7 @@ public:
   // Objective-c statements
   virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                                                 SourceLocation RParen,
-                                                StmtArg Parm, StmtArg Body,
+                                                DeclTy *Parm, StmtArg Body,
                                                 StmtArg CatchList) {
     return StmtEmpty();
   }
index e987d84c23182c54b581dbcd4f84662648857cf6..63d3e7f7b4b5cab1b135dab0037607b8ca696276 100644 (file)
@@ -180,10 +180,10 @@ ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
 
 ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
                                  SourceLocation rparenloc,
-                                 DeclStmt *catchVarStmtDecl, Stmt *atCatchStmt,
+                                 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
                                  Stmt *atCatchList)
 : Stmt(ObjCAtCatchStmtClass) {
-  SubExprs[SELECTOR] = catchVarStmtDecl;
+  ExceptionDecl = catchVarDecl;
   SubExprs[BODY] = atCatchStmt;
   SubExprs[NEXT_CATCH] = NULL;
   // FIXME: O(N^2) in number of catch blocks.
index 7e25b465b127b7b1fc7ab4ef4ff7298128e0f9b5..e6ac310b8351ed029bc1d1151e6cda09ce5809fd 100644 (file)
@@ -448,9 +448,9 @@ void StmtPrinter::VisitObjCAtTryStmt(ObjCAtTryStmt *Node) {
        catchStmt = 
          static_cast<ObjCAtCatchStmt *>(catchStmt->getNextCatchStmt())) {
     Indent() << "@catch(";
-    if (catchStmt->getCatchParamStmt()) {
-      if (DeclStmt *DS = dyn_cast<DeclStmt>(catchStmt->getCatchParamStmt()))
-        PrintRawDeclStmt(DS);
+    if (catchStmt->getCatchParamDecl()) {
+      if (Decl *DS = catchStmt->getCatchParamDecl())
+        PrintRawDecl(DS);
     }
     OS << ")";
     if (CompoundStmt *CS = dyn_cast<CompoundStmt>(catchStmt->getCatchBody())) 
index 0f38eb94bc8a945ee3c012ed5e3a3862f1dfff45..bbbed3fe2b1baaf25106b8db0fa945768d9b5512 100644 (file)
@@ -2014,30 +2014,28 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
     for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
       llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch");
 
-      const DeclStmt *CatchParam = CatchStmt->getCatchParamStmt();
-      const VarDecl *VD = 0;
+      const ParmVarDecl *CatchParam = CatchStmt->getCatchParamDecl();
       const PointerType *PT = 0;
 
       // catch(...) always matches.
       if (!CatchParam) {
         AllMatched = true;
       } else {
-        VD = cast<VarDecl>(CatchParam->getSolitaryDecl());
-        PT = VD->getType()->getAsPointerType();
+        PT = CatchParam->getType()->getAsPointerType();
         
         // catch(id e) always matches. 
         // FIXME: For the time being we also match id<X>; this should
         // be rejected by Sema instead.
         if ((PT && CGF.getContext().isObjCIdStructType(PT->getPointeeType())) ||
-            VD->getType()->isObjCQualifiedIdType())
+            CatchParam->getType()->isObjCQualifiedIdType())
           AllMatched = true;
       }
       
       if (AllMatched) {   
         if (CatchParam) {
-          CGF.EmitStmt(CatchParam);
+          CGF.EmitLocalBlockVarDecl(*CatchParam);
           assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
-          CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(VD));
+          CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
         }
         
         CGF.EmitStmt(CatchStmt->getCatchBody());
@@ -2063,13 +2061,13 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
       
       // Emit the @catch block.
       CGF.EmitBlock(MatchedBlock);
-      CGF.EmitStmt(CatchParam);
+      CGF.EmitLocalBlockVarDecl(*CatchParam);
       assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
 
       llvm::Value *Tmp = 
-        CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(VD->getType()), 
+        CGF.Builder.CreateBitCast(Caught, CGF.ConvertType(CatchParam->getType()), 
                                   "tmp");
-      CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(VD));
+      CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
       
       CGF.EmitStmt(CatchStmt->getCatchBody());
       CGF.EmitBranchThroughCleanup(FinallyEnd);
@@ -4778,17 +4776,17 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
   SelectorArgs.push_back(ObjCTypes.EHPersonalityPtr);
 
   // Construct the lists of (type, catch body) to handle.
-  llvm::SmallVector<std::pair<const DeclStmt*, const Stmt*>, 8> Handlers;
+  llvm::SmallVector<std::pair<const Decl*, const Stmt*>, 8> Handlers;
   bool HasCatchAll = false;
   if (isTry) {
     if (const ObjCAtCatchStmt* CatchStmt =
         cast<ObjCAtTryStmt>(S).getCatchStmts())  {
       for (; CatchStmt; CatchStmt = CatchStmt->getNextCatchStmt()) {
-        const DeclStmt *DS = CatchStmt->getCatchParamStmt();
-        Handlers.push_back(std::make_pair(DS, CatchStmt->getCatchBody()));
+        const Decl *CatchDecl = CatchStmt->getCatchParamDecl();
+        Handlers.push_back(std::make_pair(CatchDecl, CatchStmt->getCatchBody()));
 
         // catch(...) always matches.
-        if (!DS) {
+        if (!CatchDecl) {
           // Use i8* null here to signal this is a catch all, not a cleanup.
           llvm::Value *Null = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
           SelectorArgs.push_back(Null);
@@ -4796,7 +4794,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
           break;
         }
 
-        const VarDecl *VD = cast<VarDecl>(DS->getSolitaryDecl());
+        const VarDecl *VD = cast<VarDecl>(CatchDecl);
         if (CGF.getContext().isObjCIdType(VD->getType()) ||
             VD->getType()->isObjCQualifiedIdType()) {
           llvm::Value *IDEHType = 
@@ -4826,7 +4824,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
   // We use a cleanup unless there was already a catch all.
   if (!HasCatchAll) {
     SelectorArgs.push_back(llvm::ConstantInt::get(llvm::Type::Int32Ty, 0));
-    Handlers.push_back(std::make_pair((const DeclStmt*) 0, (const Stmt*) 0));
+    Handlers.push_back(std::make_pair((const Decl*) 0, (const Stmt*) 0));
   }
     
   llvm::Value *Selector = 
@@ -4834,7 +4832,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
                            SelectorArgs.begin(), SelectorArgs.end(),
                            "selector");
   for (unsigned i = 0, e = Handlers.size(); i != e; ++i) {
-    const DeclStmt *CatchParam = Handlers[i].first;
+    const Decl *CatchParam = Handlers[i].first;
     const Stmt *CatchBody = Handlers[i].second;
 
     llvm::BasicBlock *Next = 0;
@@ -4871,10 +4869,10 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
 
       // Bind the catch parameter if it exists.
       if (CatchParam) {
-        const VarDecl *VD = cast<VarDecl>(CatchParam->getSolitaryDecl());
+        const VarDecl *VD = dyn_cast<VarDecl>(CatchParam);
         ExcObject = CGF.Builder.CreateBitCast(ExcObject, 
                                               CGF.ConvertType(VD->getType()));
-        CGF.EmitStmt(CatchParam);
+        CGF.EmitLocalBlockVarDecl(*VD);
         CGF.Builder.CreateStore(ExcObject, CGF.GetAddrOfLocalVar(VD));
       }
 
index 193a73f664db720069dad1811fda02860cfa531c..3637d144d63c6d28e2c0c29acf5a2d3345a8f033 100644 (file)
@@ -1285,7 +1285,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
 
     SourceLocation AtCatchFinallyLoc = ConsumeToken();
     if (Tok.isObjCAtKeyword(tok::objc_catch)) {
-      OwningStmtResult FirstPart(Actions);
+      DeclTy *FirstPart = 0;
       ConsumeToken(); // consume catch
       if (Tok.is(tok::l_paren)) {
         ConsumeParen();
@@ -1294,17 +1294,14 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
           DeclSpec DS;
           ParseDeclarationSpecifiers(DS);
           // For some odd reason, the name of the exception variable is
-          // optional. As a result, we need to use PrototypeContext.
-          Declarator DeclaratorInfo(DS, Declarator::PrototypeContext);
-          ParseDeclarator(DeclaratorInfo);
-          if (DeclaratorInfo.getIdentifier()) {
-            DeclTy *aBlockVarDecl = Actions.ActOnDeclarator(CurScope,
-                                                          DeclaratorInfo, 0);
-            FirstPart =
-              Actions.ActOnDeclStmt(aBlockVarDecl,
-                                    DS.getSourceRange().getBegin(),
-                                    DeclaratorInfo.getSourceRange().getEnd());
-          }
+          // optional. As a result, we need to use "PrototypeContext", because 
+          // we must accept either 'declarator' or 'abstract-declarator' here.
+          Declarator ParmDecl(DS, Declarator::PrototypeContext);
+          ParseDeclarator(ParmDecl);
+
+          // Inform the actions module about the parameter declarator, so it
+          // gets added to the current scope.
+          FirstPart = Actions.ActOnParamDeclarator(CurScope, ParmDecl);
         } else
           ConsumeToken(); // consume '...'
         SourceLocation RParenLoc = ConsumeParen();
@@ -1317,7 +1314,7 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
         if (CatchBody.isInvalid())
           CatchBody = Actions.ActOnNullStmt(Tok.getLocation());
         CatchStmts = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
-                        RParenLoc, move(FirstPart), move(CatchBody),
+                        RParenLoc, FirstPart, move(CatchBody),
                         move(CatchStmts));
       } else {
         Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
index 77f2a3d8b6982ed62afedf8da31b47722d99a7a7..deff50486484aa450fe6b2fd3523d3bda14d526e 100644 (file)
@@ -1054,7 +1054,7 @@ public:
 
   virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc,
                                                 SourceLocation RParen,
-                                                StmtArg Parm, StmtArg Body,
+                                                DeclTy *Parm, StmtArg Body,
                                                 StmtArg CatchList);
 
   virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc,
index e7dff6d5b32efce878988b3cb8f8a39c09f1283c..49bd85a9e7e2bb2696e87e140123eb20a13d0e80 100644 (file)
@@ -962,11 +962,11 @@ Sema::OwningStmtResult Sema::ActOnAsmStmt(SourceLocation AsmLoc,
 
 Action::OwningStmtResult
 Sema::ActOnObjCAtCatchStmt(SourceLocation AtLoc,
-                           SourceLocation RParen, StmtArg Parm,
+                           SourceLocation RParen, DeclTy *Parm,
                            StmtArg Body, StmtArg catchList) {
   Stmt *CatchList = static_cast<Stmt*>(catchList.release());
   ObjCAtCatchStmt *CS = new (Context) ObjCAtCatchStmt(AtLoc, RParen,
-    static_cast<DeclStmt*>(Parm.release()), static_cast<Stmt*>(Body.release()),
+    static_cast<ParmVarDecl*>(Parm), static_cast<Stmt*>(Body.release()),
     CatchList);
   return Owned(CatchList ? CatchList : CS);
 }