[cfe-commits] r61346 - in /cfe/trunk: include/clang/AST/Stmt.h include/clang/AST/StmtNodes.def include/clang/Basic/DiagnosticKinds.def lib/AST/Stmt.cpp lib/AST/StmtPrinter.cpp lib/AST/StmtSerialization.cpp lib/Sema/Sema.h lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaStmt.cpp test/SemaCXX/try-catch.cpp

Sebastian Redl sebastian.redl at getdesigned.at
Mon Dec 22 13:35:03 PST 2008


Author: cornedbee
Date: Mon Dec 22 15:35:02 2008
New Revision: 61346

URL: http://llvm.org/viewvc/llvm-project?rev=61346&view=rev
Log:
Full AST support and better Sema support for C++ try-catch.

Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/include/clang/AST/StmtNodes.def
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtSerialization.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp
    cfe/trunk/test/SemaCXX/try-catch.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Dec 22 15:35:02 2008
@@ -1238,6 +1238,46 @@
   static CXXCatchStmt* CreateImpl(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// CXXTryStmt - A C++ try block, including all handlers.
+class CXXTryStmt : public Stmt {
+  SourceLocation TryLoc;
+  // First place is the guarded CompoundStatement. Subsequent are the handlers.
+  // More than three handlers should be rare.
+  llvm::SmallVector<Stmt*, 4> Stmts;
+
+public:
+  CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
+             Stmt **handlers, unsigned numHandlers);
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(TryLoc, Stmts.back()->getLocEnd());
+  }
+
+  CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); }
+  const CompoundStmt *getTryBlock() const {
+    return llvm::cast<CompoundStmt>(Stmts[0]);
+  }
+
+  unsigned getNumHandlers() const { return Stmts.size() - 1; }
+  CXXCatchStmt *getHandler(unsigned i) {
+    return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+  }
+  const CXXCatchStmt *getHandler(unsigned i) const {
+    return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
+  }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXTryStmtClass;
+  }
+  static bool classof(const CXXTryStmt *) { return true; }
+
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static CXXTryStmt* CreateImpl(llvm::Deserializer& D, ASTContext& C);
+};
+
 }  // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/AST/StmtNodes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtNodes.def?rev=61346&r1=61345&r2=61346&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Dec 22 15:35:02 2008
@@ -55,8 +55,9 @@
 
 // C++ statements
 STMT(CXXCatchStmt, Stmt)
+STMT(CXXTryStmt  , Stmt)
 
-LAST_STMT(CXXCatchStmt)
+LAST_STMT(CXXTryStmt)
 
 // Expressions.
 STMT(Expr                  , Stmt)

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=61346&r1=61345&r2=61346&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 22 15:35:02 2008
@@ -1319,6 +1319,8 @@
      "cannot catch%select{| pointer to| reference to}1 incomplete type %0")
 DIAG(err_qualified_catch_declarator, ERROR,
      "exception declarator cannot be qualified")
+DIAG(err_early_catch_all, ERROR,
+     "catch-all handler must come last")
 
 DIAG(err_invalid_use_of_function_type, ERROR,
      "a function type is not allowed here")

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

==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Mon Dec 22 15:35:02 2008
@@ -350,6 +350,18 @@
 }
 
 void CXXCatchStmt::Destroy(ASTContext& C) {
-  ExceptionDecl->Destroy(C);
+  if (ExceptionDecl)
+    ExceptionDecl->Destroy(C);
   Stmt::Destroy(C);
 }
+
+// CXXTryStmt
+Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
+Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
+
+CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
+                       Stmt **handlers, unsigned numHandlers)
+  : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
+  Stmts.push_back(tryBlock);
+  Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);
+}

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

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Dec 22 15:35:02 2008
@@ -52,6 +52,7 @@
     void PrintRawDecl(Decl *D);
     void PrintRawDeclStmt(DeclStmt *S);
     void PrintRawIfStmt(IfStmt *If);
+    void PrintRawCXXCatchStmt(CXXCatchStmt *Catch);
     
     void PrintExpr(Expr *E) {
       if (E)
@@ -474,14 +475,29 @@
   OS << "\n";
 }
 
-void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
-  Indent() << "catch (";
+void StmtPrinter::PrintRawCXXCatchStmt(CXXCatchStmt *Node) {
+  OS << "catch (";
   if (Decl *ExDecl = Node->getExceptionDecl())
     PrintRawDecl(ExDecl);
   else
     OS << "...";
   OS << ") ";
   PrintRawCompoundStmt(cast<CompoundStmt>(Node->getHandlerBlock()));
+}
+
+void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
+  Indent();
+  PrintRawCXXCatchStmt(Node);
+  OS << "\n";
+}
+
+void StmtPrinter::VisitCXXTryStmt(CXXTryStmt *Node) {
+  Indent() << "try ";
+  PrintRawCompoundStmt(Node->getTryBlock());
+  for(unsigned i = 0, e = Node->getNumHandlers(); i < e; ++i) {
+    OS << " ";
+    PrintRawCXXCatchStmt(Node->getHandler(i));
+  }
   OS << "\n";
 }
 

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

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Mon Dec 22 15:35:02 2008
@@ -1540,3 +1540,19 @@
   Stmt *HandlerBlock = D.ReadOwnedPtr<Stmt>(C);
   return new CXXCatchStmt(CatchLoc, ExDecl, HandlerBlock);
 }
+
+void CXXTryStmt::EmitImpl(llvm::Serializer& S) const {
+  S.Emit(TryLoc);
+  S.EmitInt(Stmts.size());
+  S.BatchEmitOwnedPtrs(Stmts.size(), &Stmts[0]);
+}
+
+CXXTryStmt *
+CXXTryStmt::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
+  SourceLocation TryLoc = SourceLocation::ReadVal(D);
+  unsigned size = D.ReadInt();
+  llvm::SmallVector<Stmt*, 4> Stmts(size);
+  D.BatchReadOwnedPtrs<Stmt>(size, &Stmts[0], C);
+
+  return new CXXTryStmt(TryLoc, Stmts[0], &Stmts[1], size - 1);
+}

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=61346&r1=61345&r2=61346&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Dec 22 15:35:02 2008
@@ -640,9 +640,9 @@
   virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
                                               DeclTy *ExDecl,
                                               StmtArg HandlerBlock);
-  //virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
-  //                                          StmtArg TryBlock,
-  //                                          MultiStmtArg Handlers);
+  virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
+                                            StmtArg TryBlock,
+                                            MultiStmtArg Handlers);
 
   //===--------------------------------------------------------------------===//
   // Expression Parsing Callbacks: SemaExpr.cpp.

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 22 15:35:02 2008
@@ -2058,6 +2058,10 @@
     Diag(Begin, diag::err_catch_incomplete) << BaseType << Mode;
   }
 
+  // FIXME: Need to test for ability to copy-construct and destroy the
+  // exception variable.
+  // FIXME: Need to check for abstract classes.
+
   IdentifierInfo *II = D.getIdentifier();
   if (Decl *PrevDecl = LookupDecl(II, Decl::IDNS_Ordinary, S)) {
     // The scope should be freshly made just for us. There is just no way

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Dec 22 15:35:02 2008
@@ -961,3 +961,31 @@
   return Owned(new CXXCatchStmt(CatchLoc, static_cast<VarDecl*>(ExDecl),
                                 static_cast<Stmt*>(HandlerBlock.release())));
 }
+
+/// ActOnCXXTryBlock - Takes a try compound-statement and a number of
+/// handlers and creates a try statement from them.
+Action::OwningStmtResult
+Sema::ActOnCXXTryBlock(SourceLocation TryLoc, StmtArg TryBlock,
+                       MultiStmtArg RawHandlers) {
+  unsigned NumHandlers = RawHandlers.size();
+  assert(NumHandlers > 0 &&
+         "The parser shouldn't call this if there are no handlers.");
+  Stmt **Handlers = reinterpret_cast<Stmt**>(RawHandlers.get());
+
+  for(unsigned i = 0; i < NumHandlers - 1; ++i) {
+    CXXCatchStmt *Handler = llvm::cast<CXXCatchStmt>(Handlers[i]);
+    if (!Handler->getExceptionDecl())
+      return StmtError(Diag(Handler->getLocStart(), diag::err_early_catch_all));
+  }
+  // FIXME: We should detect handlers for the same type as an earlier one.
+  // This one is rather easy.
+  // FIXME: We should detect handlers that cannot catch anything because an
+  // earlier handler catches a superclass. Need to find a method that is not
+  // quadratic for this.
+  // Neither of these are explicitly forbidden, but every compiler detects them
+  // and warns.
+
+  RawHandlers.release();
+  return Owned(new CXXTryStmt(TryLoc, static_cast<Stmt*>(TryBlock.release()),
+                              Handlers, NumHandlers));
+}

Modified: cfe/trunk/test/SemaCXX/try-catch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/try-catch.cpp?rev=61346&r1=61345&r2=61346&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/try-catch.cpp (original)
+++ cfe/trunk/test/SemaCXX/try-catch.cpp Mon Dec 22 15:35:02 2008
@@ -16,4 +16,9 @@
   } catch(...) {
     int j = i; // expected-error {{use of undeclared identifier 'i'}}
   }
+
+  try {
+  } catch(...) { // expected-error {{catch-all handler must come last}}
+  } catch(int) {
+  }
 }





More information about the cfe-commits mailing list