[cfe-commits] r70155 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Parse/ lib/AST/ lib/Analysis/ lib/CodeGen/ lib/Parse/ lib/Sema/ test/Parser/ tools/clang-cc/

Sebastian Redl sebastian.redl at getdesigned.at
Sun Apr 26 13:35:06 PDT 2009


Author: cornedbee
Date: Sun Apr 26 15:35:05 2009
New Revision: 70155

URL: http://llvm.org/viewvc/llvm-project?rev=70155&view=rev
Log:
Implement function-try-blocks. However, there's a very subtle bug that I can't track down.

Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/lib/Analysis/BugReporter.cpp
    cfe/trunk/lib/Analysis/CFRefCount.cpp
    cfe/trunk/lib/Analysis/PathDiagnostic.cpp
    cfe/trunk/lib/CodeGen/CGObjC.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Parse/ParseStmt.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Parser/cxx-try.cpp
    cfe/trunk/tools/clang-cc/RewriteBlocks.cpp
    cfe/trunk/tools/clang-cc/RewriteObjC.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Sun Apr 26 15:35:05 2009
@@ -554,17 +554,16 @@
   /// function. The variant that accepts a FunctionDecl pointer will
   /// set that function declaration to the actual declaration
   /// containing the body (if there is one).
-  CompoundStmt *getBody(ASTContext &Context, 
-                        const FunctionDecl *&Definition) const;
+  Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const;
 
-  virtual CompoundStmt *getBody(ASTContext &Context) const { 
+  virtual Stmt *getBody(ASTContext &Context) const {
     const FunctionDecl* Definition;
     return getBody(Context, Definition);
   }
 
   /// \brief If the function has a body that is immediately available,
   /// return it.
-  CompoundStmt *getBodyIfAvailable() const;
+  Stmt *getBodyIfAvailable() const;
 
   /// isThisDeclarationADefinition - Returns whether this specific
   /// declaration of the function is also a definition. This does not
@@ -574,7 +573,7 @@
   /// CodeGenModule.cpp uses it, and I don't know if this would break it.
   bool isThisDeclarationADefinition() const { return Body; }
 
-  void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+  void setBody(Stmt *B) { Body = B; }
   void setLazyBody(uint64_t Offset) { Body = Offset; }
 
   /// Whether this function is virtual, either by explicit marking, or by
@@ -1148,7 +1147,7 @@
   SourceLocation getCaretLocation() const { return getLocation(); }
 
   CompoundStmt *getBody() const { return (CompoundStmt*) Body; }
-  CompoundStmt *getBody(ASTContext &C) const { return (CompoundStmt*) Body; }
+  Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; }
   void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
 
   // Iterator access to formal parameters.

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Sun Apr 26 15:35:05 2009
@@ -281,11 +281,18 @@
   // be defined inside or outside a function etc).
   bool isDefinedOutsideFunctionOrMethod() const;
 
-  // getBody - If this Decl represents a declaration for a body of code,
-  //  such as a function or method definition, this method returns the top-level
-  //  Stmt* of that body.  Otherwise this method returns null.  
-  virtual CompoundStmt* getBody(ASTContext &Context) const { return 0; }
-  
+  /// getBody - If this Decl represents a declaration for a body of code,
+  ///  such as a function or method definition, this method returns the
+  ///  top-level Stmt* of that body.  Otherwise this method returns null.
+  virtual Stmt* getBody(ASTContext &Context) const { return 0; }
+
+  /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt.
+  CompoundStmt* getCompoundBody(ASTContext &Context) const;
+
+  /// getBodyRBrace - Gets the right brace of the body, if a body exists.
+  /// This works whether the body is a CompoundStmt or a CXXTryStmt.
+  SourceLocation getBodyRBrace(ASTContext &Context) const;
+
   // global temp stats (until we have a per-module visitor)
   static void addDeclKind(Kind k);
   static bool CollectingStats(bool Enable = false);

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sun Apr 26 15:35:05 2009
@@ -242,11 +242,11 @@
     return ImplementationControl(DeclImplementation); 
   }
 
-  virtual CompoundStmt *getBody(ASTContext &C) const { 
-    return (CompoundStmt*) Body; 
+  virtual Stmt *getBody(ASTContext &C) const { 
+    return (Stmt*) Body; 
   }
   CompoundStmt *getBody() { return (CompoundStmt*)Body; }
-  void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+  void setBody(Stmt *B) { Body = B; }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return D->getKind() == ObjCMethod; }

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

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sun Apr 26 15:35:05 2009
@@ -205,6 +205,7 @@
 def ext_ellipsis_exception_spec : Extension<
   "exception specification of '...' is a Microsoft extension">;
 def err_expected_catch : Error<"expected catch">;
+def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
 
 // C++ derived classes
 def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sun Apr 26 15:35:05 2009
@@ -795,6 +795,7 @@
   // C++ 6: Statements and Blocks
 
   OwningStmtResult ParseCXXTryBlock();
+  OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc);
   OwningStmtResult ParseCXXCatchBlock();
 
   //===--------------------------------------------------------------------===//
@@ -815,7 +816,8 @@
                                         bool RequireSemi = true);
   DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D);
   DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl);
-  
+  DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl);
+
   bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS,
                         TemplateParameterLists *TemplateParams,
                         AccessSpecifier AS);

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Sun Apr 26 15:35:05 2009
@@ -321,22 +321,22 @@
 }
 
 
-CompoundStmt *FunctionDecl::getBody(ASTContext &Context,
-                                    const FunctionDecl *&Definition) const {
+Stmt *FunctionDecl::getBody(ASTContext &Context,
+                            const FunctionDecl *&Definition) const {
   for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
     if (FD->Body) {
       Definition = FD;
-      return cast<CompoundStmt>(FD->Body.get(Context.getExternalSource()));
+      return FD->Body.get(Context.getExternalSource());
     }
   }
 
   return 0;
 }
 
-CompoundStmt *FunctionDecl::getBodyIfAvailable() const {
+Stmt *FunctionDecl::getBodyIfAvailable() const {
   for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) {
     if (FD->Body && !FD->Body.isOffset()) {
-      return cast<CompoundStmt>(FD->Body.get(0));
+      return FD->Body.get(0);
     }
   }
 

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Sun Apr 26 15:35:05 2009
@@ -20,6 +20,8 @@
 #include "clang/AST/ExternalASTSource.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -341,6 +343,21 @@
   }
 }
 
+CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const {
+  return dyn_cast_or_null<CompoundStmt>(getBody(Context));
+}
+
+SourceLocation Decl::getBodyRBrace(ASTContext &Context) const {
+  Stmt *Body = getBody(Context);
+  if (!Body)
+    return SourceLocation();
+  if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
+    return CS->getRBracLoc();
+  assert(isa<CXXTryStmt>(Body) &&
+         "Body can only be CompoundStmt or CXXTryStmt");
+  return cast<CXXTryStmt>(Body)->getSourceRange().getEnd();
+}
+
 #ifndef NDEBUG
 void Decl::CheckAccessDeclContext() const {
   assert((Access != AS_none || isa<TranslationUnitDecl>(this) ||

Modified: cfe/trunk/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BugReporter.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Sun Apr 26 15:35:05 2009
@@ -189,7 +189,7 @@
   if (Stmt *S = GetNextStmt(N))
     return PathDiagnosticLocation(S, SMgr);
 
-  return FullSourceLoc(CodeDecl.getBody(getContext())->getRBracLoc(), SMgr);
+  return FullSourceLoc(CodeDecl.getBodyRBrace(getContext()), SMgr);
 }
   
 PathDiagnosticLocation
@@ -825,7 +825,9 @@
     
     // Finally, add an initial edge from the start location of the first
     // statement (if it doesn't already exist).
-    if (const CompoundStmt *CS = PDB.getCodeDecl().getBody(PDB.getContext()))
+    // FIXME: Should handle CXXTryStmt if analyser starts supporting C++.
+    if (const CompoundStmt *CS =
+          PDB.getCodeDecl().getCompoundBody(PDB.getContext()))
       if (!CS->body_empty()) {
         SourceLocation Loc = (*CS->body_begin())->getLocStart();
         rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager()));

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Sun Apr 26 15:35:05 2009
@@ -3047,11 +3047,11 @@
 
     LeakN = LeakN->succ_empty() ? 0 : *(LeakN->succ_begin());
   }
-  
+
   if (!L.isValid()) {
-    CompoundStmt *CS 
-      = BR.getStateManager().getCodeDecl().getBody(BR.getContext());
-    L = PathDiagnosticLocation(CS->getRBracLoc(), SMgr);
+    L = PathDiagnosticLocation(
+          BR.getStateManager().getCodeDecl().getBodyRBrace(BR.getContext()),
+          SMgr);
   }
 
   std::string sbuf;

Modified: cfe/trunk/lib/Analysis/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/PathDiagnostic.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/Analysis/PathDiagnostic.cpp Sun Apr 26 15:35:05 2009
@@ -15,6 +15,7 @@
 #include "clang/AST/Expr.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
+#include "clang/AST/StmtCXX.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Casting.h"
 #include <sstream>
@@ -197,8 +198,12 @@
         // FIXME: We would like to always get the function body, even
         // when it needs to be de-serialized, but getting the
         // ASTContext here requires significant changes.
-        if (CompoundStmt *Body = FD->getBodyIfAvailable())
-          return Body->getSourceRange();
+        if (Stmt *Body = FD->getBodyIfAvailable()) {
+          if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body))
+            return CS->getSourceRange();
+          else
+            return cast<CXXTryStmt>(Body)->getSourceRange();
+        }
       }
       else {
         SourceLocation L = D->getLocation();

Modified: cfe/trunk/lib/CodeGen/CGObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjC.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjC.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjC.cpp Sun Apr 26 15:35:05 2009
@@ -129,7 +129,7 @@
     DebugInfo = CGM.getDebugInfo();
   StartObjCMethod(OMD, OMD->getClassInterface());
   EmitStmt(OMD->getBody(getContext()));
-  FinishFunction(cast<CompoundStmt>(OMD->getBody(getContext()))->getRBracLoc());
+  FinishFunction(OMD->getBodyRBrace(getContext()));
 }
 
 // FIXME: I wasn't sure about the synthesis approach. If we end up

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Sun Apr 26 15:35:05 2009
@@ -225,12 +225,13 @@
                                     FProto->getArgType(i)));
   }
 
-  const CompoundStmt *S = FD->getBody(getContext());
+  // FIXME: Support CXXTryStmt here, too.
+  if (const CompoundStmt *S = FD->getCompoundBody(getContext())) {
+    StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc());
+    EmitStmt(S);
+    FinishFunction(S->getRBracLoc());
+  }
 
-  StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc());
-  EmitStmt(S);
-  FinishFunction(S->getRBracLoc());
-    
   // Destroy the 'this' declaration.
   if (CXXThisDecl)
     CXXThisDecl->Destroy(getContext());

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Sun Apr 26 15:35:05 2009
@@ -17,15 +17,15 @@
 #include "clang/Parse/Scope.h"
 using namespace clang;
 
-/// ParseInlineCXXMethodDef - We parsed and verified that the specified
+/// ParseCXXInlineMethodDef - We parsed and verified that the specified
 /// Declarator is a well formed C++ inline method definition. Now lex its body
 /// and store its tokens for parsing after the C++ class is complete.
 Parser::DeclPtrTy
 Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) {
   assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function &&
          "This isn't a function declarator!");
-  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && 
-         "Current token not a '{' or ':'!");
+  assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) &&
+         "Current token not a '{', ':' or 'try'!");
 
   DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0);
 
@@ -34,8 +34,9 @@
   getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD));
   CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks;
 
-  // We may have a constructor initializer here.
-  if (Tok.is(tok::colon)) {
+  tok::TokenKind kind = Tok.getKind();
+  // We may have a constructor initializer or function-try-block here.
+  if (kind == tok::colon || kind == tok::kw_try) {
     // Consume everything up to (and including) the left brace.
     if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) {
       // We didn't find the left-brace we expected after the
@@ -58,6 +59,14 @@
   // Consume everything up to (and including) the matching right brace.
   ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
 
+  // If we're in a function-try-block, we need to store all the catch blocks.
+  if (kind == tok::kw_try) {
+    while (Tok.is(tok::kw_catch)) {
+      ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks);
+      ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks);
+    }
+  }
+
   return FnD;
 }
 
@@ -126,14 +135,18 @@
 
     // Consume the previously pushed token.
     ConsumeAnyToken();
-    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && 
-           "Inline method not starting with '{' or ':'");
+    assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
+           && "Inline method not starting with '{', ':' or 'try'");
 
     // Parse the method body. Function body parsing code is similar enough
     // to be re-used for method bodies as well.
     ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
     Actions.ActOnStartOfFunctionDef(CurScope, LM.D);
 
+    if (Tok.is(tok::kw_try)) {
+      ParseFunctionTryBlock(LM.D);
+      return;
+    }
     if (Tok.is(tok::colon))
       ParseConstructorInitializer(LM.D);
     // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'??

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sun Apr 26 15:35:05 2009
@@ -737,7 +737,8 @@
 
     // function-definition:
     if (Tok.is(tok::l_brace)
-        || (DeclaratorInfo.isFunctionDeclarator() && Tok.is(tok::colon))) {
+        || (DeclaratorInfo.isFunctionDeclarator() &&
+            (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
       if (!DeclaratorInfo.isFunctionDeclarator()) {
         Diag(Tok, diag::err_func_def_no_params);
         ConsumeBrace();
@@ -1044,6 +1045,7 @@
       break;
     else {
       // Skip over garbage, until we get to '{'.  Don't eat the '{'.
+      Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
       SkipUntil(tok::l_brace, true, true);
       break;
     }

Modified: cfe/trunk/lib/Parse/ParseStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseStmt.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Sun Apr 26 15:35:05 2009
@@ -1289,7 +1289,7 @@
 Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
   assert(Tok.is(tok::l_brace));
   SourceLocation LBraceLoc = Tok.getLocation();
-         
+
   PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
                                         PP.getSourceManager(),
                                         "parsing function body");
@@ -1307,18 +1307,58 @@
   return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
 }
 
+/// ParseFunctionTryBlock - Parse a C++ function-try-block.
+///
+///       function-try-block:
+///         'try' ctor-initializer[opt] compound-statement handler-seq
+///
+Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
+  assert(Tok.is(tok::kw_try) && "Expected 'try'");
+  SourceLocation TryLoc = ConsumeToken();
+
+  PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
+                                        PP.getSourceManager(),
+                                        "parsing function try block");
+
+  // Constructor initializer list?
+  if (Tok.is(tok::colon))
+    ParseConstructorInitializer(Decl);
+
+  OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
+  // If we failed to parse the try-catch, we just give the function an empty
+  // compound statement as the body.
+  if (FnBody.isInvalid())
+    FnBody = Actions.ActOnCompoundStmt(TryLoc, TryLoc,
+                                       MultiStmtArg(Actions), false);
+
+  return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
+}
+
 /// ParseCXXTryBlock - Parse a C++ try-block.
 ///
 ///       try-block:
 ///         'try' compound-statement handler-seq
 ///
-///       handler-seq:
-///         handler handler-seq[opt]
-///
 Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
   assert(Tok.is(tok::kw_try) && "Expected 'try'");
 
   SourceLocation TryLoc = ConsumeToken();
+  return ParseCXXTryBlockCommon(TryLoc);
+}
+
+/// ParseCXXTryBlockCommon - Parse the common part of try-block and
+/// function-try-block.
+///
+///       try-block:
+///         'try' compound-statement handler-seq
+///
+///       function-try-block:
+///         'try' ctor-initializer[opt] compound-statement handler-seq
+///
+///       handler-seq:
+///         handler handler-seq[opt]
+///
+Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
   if (Tok.isNot(tok::l_brace))
     return StmtError(Diag(Tok, diag::err_expected_lbrace));
   OwningStmtResult TryBlock(ParseCompoundStatement());

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Sun Apr 26 15:35:05 2009
@@ -536,7 +536,8 @@
               (!getLang().CPlusPlus &&
                isDeclarationSpecifier()) ||   // int X(f) int f; {}
               (getLang().CPlusPlus &&
-               Tok.is(tok::colon)))) { // X() : Base() {} (used for ctors)
+               (Tok.is(tok::colon) ||     // X() : Base() {} (used for ctors)
+                Tok.is(tok::kw_try))))) { // X() try { ... }
     if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
       Diag(Tok, diag::err_function_declared_typedef);
 
@@ -575,7 +576,7 @@
 ///         decl-specifier-seq[opt] declarator ctor-initializer[opt]
 ///         function-body
 /// [C++] function-definition: [C++ 8.4]
-///         decl-specifier-seq[opt] declarator function-try-block [TODO]
+///         decl-specifier-seq[opt] declarator function-try-block
 ///
 Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) {
   const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0);
@@ -602,8 +603,8 @@
 
   // We should have either an opening brace or, in a C++ constructor,
   // we may have a colon.
-  // FIXME: In C++, we might also find the 'try' keyword.
-  if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon)) {
+  if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) &&
+      Tok.isNot(tok::kw_try)) {
     Diag(Tok, diag::err_expected_fn_body);
 
     // Skip over garbage, until we get to '{'.  Don't eat the '{'.
@@ -621,12 +622,14 @@
   // specified Declarator for the function.
   DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D);
 
+  if (Tok.is(tok::kw_try))
+    return ParseFunctionTryBlock(Res);
+
   // If we have a colon, then we're probably parsing a C++
   // ctor-initializer.
   if (Tok.is(tok::colon))
     ParseConstructorInitializer(Res);
 
-  SourceLocation BraceLoc = Tok.getLocation();
   return ParseFunctionStatementBody(Res);
 }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sun Apr 26 15:35:05 2009
@@ -18,6 +18,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtCXX.h"
 #include "clang/Parse/DeclSpec.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/SourceManager.h"
@@ -2986,7 +2987,7 @@
 
 Sema::DeclPtrTy Sema::ActOnFinishFunctionBody(DeclPtrTy D, StmtArg BodyArg) {
   Decl *dcl = D.getAs<Decl>();
-  CompoundStmt *Body =cast<CompoundStmt>(static_cast<Stmt*>(BodyArg.release()));
+  Stmt *Body = BodyArg.takeAs<Stmt>();
   if (FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(dcl)) {
     FD->setBody(Body);
     assert(FD == getCurFunctionDecl() && "Function parsing confused");
@@ -3029,13 +3030,16 @@
     // function somewhere so that it is properly owned and so that the goto
     // has a valid target.  Do this by creating a new compound stmt with the
     // label in it.
-    
+
     // Give the label a sub-statement.
     L->setSubStmt(new (Context) NullStmt(L->getIdentLoc()));
-      
-    std::vector<Stmt*> Elements(Body->body_begin(), Body->body_end());
+
+    CompoundStmt *Compound = isa<CXXTryStmt>(Body) ?
+                               cast<CXXTryStmt>(Body)->getTryBlock() :
+                               cast<CompoundStmt>(Body);
+    std::vector<Stmt*> Elements(Compound->body_begin(), Compound->body_end());
     Elements.push_back(L);
-    Body->setStmts(Context, &Elements[0], Elements.size());
+    Compound->setStmts(Context, &Elements[0], Elements.size());
   }
   FunctionLabelMap.clear();
 

Modified: cfe/trunk/test/Parser/cxx-try.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-try.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/test/Parser/cxx-try.cpp (original)
+++ cfe/trunk/test/Parser/cxx-try.cpp Sun Apr 26 15:35:05 2009
@@ -23,3 +23,22 @@
   try {}
   catch {} // expected-error {{expected '('}}
 }
+
+void h() try {
+} catch(...) {
+}
+
+struct A {
+  int i;
+  A(float) : i(0) try {} // expected-error {{expected '{' or ','}}
+  A(int);
+  A(char);
+  // FIXME: There's something very strange going on here. After the first
+  // inline function-try-block, subsequent inline bodies aren't parsed anymore.
+  // Valgrind is silent, though, and I can't even debug this properly.
+  A() try : i(0) {} catch(...) {}
+  void f() try {} catch(...) {}
+};
+
+A::A(char) : i(0) try {} // expected-error {{expected '{' or ','}}
+A::A(int j) try : i(j) {} catch(...) {}

Modified: cfe/trunk/tools/clang-cc/RewriteBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/RewriteBlocks.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/RewriteBlocks.cpp (original)
+++ cfe/trunk/tools/clang-cc/RewriteBlocks.cpp Sun Apr 26 15:35:05 2009
@@ -1091,8 +1091,9 @@
     // prototype. This enables us to rewrite function declarations and
     // definitions using the same code.
     RewriteFunctionProtoType(FD->getType(), FD);
-    
-    if (CompoundStmt *Body = FD->getBody(*Context)) {
+
+    // FIXME: Handle CXXTryStmt
+    if (CompoundStmt *Body = FD->getCompoundBody(*Context)) {
       CurFunctionDef = FD;
       FD->setBody(cast_or_null<CompoundStmt>(RewriteFunctionBody(Body)));
       // This synthesizes and inserts the block "impl" struct, invoke function,

Modified: cfe/trunk/tools/clang-cc/RewriteObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/RewriteObjC.cpp?rev=70155&r1=70154&r2=70155&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/RewriteObjC.cpp (original)
+++ cfe/trunk/tools/clang-cc/RewriteObjC.cpp Sun Apr 26 15:35:05 2009
@@ -980,8 +980,8 @@
     ObjCMethodDecl *OMD = *I;
     RewriteObjCMethodDecl(OMD, ResultStr);
     SourceLocation LocStart = OMD->getLocStart();
-    SourceLocation LocEnd = OMD->getBody(*Context)->getLocStart();
-    
+    SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart();
+
     const char *startBuf = SM->getCharacterData(LocStart);
     const char *endBuf = SM->getCharacterData(LocEnd);
     ReplaceText(LocStart, endBuf-startBuf,
@@ -996,7 +996,7 @@
     ObjCMethodDecl *OMD = *I;
     RewriteObjCMethodDecl(OMD, ResultStr);
     SourceLocation LocStart = OMD->getLocStart();
-    SourceLocation LocEnd = OMD->getBody(*Context)->getLocStart();
+    SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart();
     
     const char *startBuf = SM->getCharacterData(LocStart);
     const char *endBuf = SM->getCharacterData(LocEnd);
@@ -1426,6 +1426,7 @@
   buf += "}\n";
   
   // Insert all these *after* the statement body.
+  // FIXME: If this should support Obj-C++, support CXXTryStmt
   if (isa<CompoundStmt>(S->getBody())) {
     SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
     InsertText(endBodyLoc, buf.c_str(), buf.size());
@@ -4489,7 +4490,8 @@
     // definitions using the same code.
     RewriteBlocksInFunctionProtoType(FD->getType(), FD);
 
-    if (CompoundStmt *Body = FD->getBody(*Context)) {
+    // FIXME: If this should support Obj-C++, support CXXTryStmt
+    if (CompoundStmt *Body = FD->getCompoundBody(*Context)) {
       CurFunctionDef = FD;
       CollectPropertySetters(Body);
       CurrentBody = Body;





More information about the cfe-commits mailing list