[cfe-commits] r61337 - in /cfe/trunk: include/clang/AST/DeclCXX.h 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/Parse/ParseStmt.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 11:15:11 PST 2008


Author: cornedbee
Date: Mon Dec 22 13:15:10 2008
New Revision: 61337

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

Added:
    cfe/trunk/test/SemaCXX/try-catch.cpp
Modified:
    cfe/trunk/include/clang/AST/DeclCXX.h
    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/Parse/ParseStmt.cpp
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaStmt.cpp

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

==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Mon Dec 22 13:15:10 2008
@@ -945,8 +945,6 @@
   void ReadInRec(llvm::Deserializer& D, ASTContext& C);
 };
 
-  
-
 } // end namespace clang
 
 #endif

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

==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Mon Dec 22 13:15:10 2008
@@ -31,6 +31,7 @@
   class Expr;
   class Decl;
   class ScopedDecl;
+  class QualType;
   class IdentifierInfo;
   class SourceManager;
   class StringLiteral;
@@ -1202,6 +1203,41 @@
   static ObjCAtThrowStmt* CreateImpl(llvm::Deserializer& D, ASTContext& C);
 };
 
+/// CXXCatchStmt - This represents a C++ catch block.
+class CXXCatchStmt : public Stmt {
+  SourceLocation CatchLoc;
+  /// The exception-declaration of the type.
+  Decl *ExceptionDecl;
+  /// The handler block.
+  Stmt *HandlerBlock;
+
+public:
+  CXXCatchStmt(SourceLocation catchLoc, Decl *exDecl, Stmt *handlerBlock)
+  : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl),
+    HandlerBlock(handlerBlock) {}
+
+  virtual void Destroy(ASTContext& Ctx);
+
+  virtual SourceRange getSourceRange() const {
+    return SourceRange(CatchLoc, HandlerBlock->getLocEnd());
+  }
+
+  Decl *getExceptionDecl() { return ExceptionDecl; }
+  QualType getCaughtType();
+  Stmt *getHandlerBlock() { return HandlerBlock; }
+
+  static bool classof(const Stmt *T) {
+    return T->getStmtClass() == CXXCatchStmtClass;
+  }
+  static bool classof(const CXXCatchStmt *) { return true; }
+
+  virtual child_iterator child_begin();
+  virtual child_iterator child_end();
+
+  virtual void EmitImpl(llvm::Serializer& S) const;
+  static CXXCatchStmt* 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=61337&r1=61336&r2=61337&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/StmtNodes.def (original)
+++ cfe/trunk/include/clang/AST/StmtNodes.def Mon Dec 22 13:15:10 2008
@@ -53,7 +53,10 @@
 // Obj-C2 statements
 STMT(ObjCForCollectionStmt, Stmt)
 
-LAST_STMT(ObjCForCollectionStmt)
+// C++ statements
+STMT(CXXCatchStmt, Stmt)
+
+LAST_STMT(CXXCatchStmt)
 
 // 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=61337&r1=61336&r2=61337&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Dec 22 13:15:10 2008
@@ -1315,6 +1315,10 @@
      "cannot decrement expression of type bool")
 DIAG(warn_increment_bool, WARNING,
      "incrementing expression of type bool is deprecated")
+DIAG(err_catch_incomplete, ERROR,
+     "cannot catch%select{| pointer to| reference to}1 incomplete type %0")
+DIAG(err_qualified_catch_declarator, ERROR,
+     "exception declarator cannot be qualified")
 
 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=61337&r1=61336&r2=61337&view=diff

==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Mon Dec 22 13:15:10 2008
@@ -14,6 +14,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
 using namespace clang;
 
 static struct StmtClassNameTable {
@@ -333,3 +334,22 @@
   return &SubStmts[0]+END_EXPR;
 }
 
+// CXXCatchStmt
+Stmt::child_iterator CXXCatchStmt::child_begin() {
+  return &HandlerBlock;
+}
+
+Stmt::child_iterator CXXCatchStmt::child_end() {
+  return &HandlerBlock + 1;
+}
+
+QualType CXXCatchStmt::getCaughtType() {
+  if (ExceptionDecl)
+    return llvm::cast<VarDecl>(ExceptionDecl)->getType();
+  return QualType();
+}
+
+void CXXCatchStmt::Destroy(ASTContext& C) {
+  ExceptionDecl->Destroy(C);
+  Stmt::Destroy(C);
+}

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

==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Mon Dec 22 13:15:10 2008
@@ -474,6 +474,17 @@
   OS << "\n";
 }
 
+void StmtPrinter::VisitCXXCatchStmt(CXXCatchStmt *Node) {
+  Indent() << "catch (";
+  if (Decl *ExDecl = Node->getExceptionDecl())
+    PrintRawDecl(ExDecl);
+  else
+    OS << "...";
+  OS << ") ";
+  PrintRawCompoundStmt(cast<CompoundStmt>(Node->getHandlerBlock()));
+  OS << "\n";
+}
+
 //===----------------------------------------------------------------------===//
 //  Expr printing methods.
 //===----------------------------------------------------------------------===//

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

==============================================================================
--- cfe/trunk/lib/AST/StmtSerialization.cpp (original)
+++ cfe/trunk/lib/AST/StmtSerialization.cpp Mon Dec 22 13:15:10 2008
@@ -242,6 +242,9 @@
 
     case CXXDependentNameExprClass:
       return CXXDependentNameExpr::CreateImpl(D, C);
+
+    case CXXCatchStmtClass:
+      return CXXCatchStmt::CreateImpl(D, C);
   }
 }
 
@@ -1523,3 +1526,17 @@
   SourceLocation L = SourceLocation::ReadVal(D);
   return new CXXDependentNameExpr(N, Ty, L);
 }
+
+void CXXCatchStmt::EmitImpl(llvm::Serializer& S) const {
+  S.Emit(CatchLoc);
+  S.EmitOwnedPtr(ExceptionDecl);
+  S.EmitOwnedPtr(HandlerBlock);
+}
+
+CXXCatchStmt *
+CXXCatchStmt::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
+  SourceLocation CatchLoc = SourceLocation::ReadVal(D);
+  Decl *ExDecl = D.ReadOwnedPtr<Decl>(C);
+  Stmt *HandlerBlock = D.ReadOwnedPtr<Stmt>(C);
+  return new CXXCatchStmt(CatchLoc, ExDecl, HandlerBlock);
+}

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

==============================================================================
--- cfe/trunk/lib/Parse/ParseStmt.cpp (original)
+++ cfe/trunk/lib/Parse/ParseStmt.cpp Mon Dec 22 13:15:10 2008
@@ -1314,7 +1314,8 @@
   DeclTy *ExceptionDecl = 0;
   if (Tok.isNot(tok::ellipsis)) {
     DeclSpec DS;
-    ParseDeclarationSpecifiers(DS);
+    if (ParseCXXTypeSpecifierSeq(DS))
+      return StmtError();
     Declarator ExDecl(DS, Declarator::CXXCatchContext);
     ParseDeclarator(ExDecl);
     ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Dec 22 13:15:10 2008
@@ -636,10 +636,10 @@
                                                  ExprTy *SynchExpr, 
                                                  StmtTy *SynchBody);
 
-  //virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D);
-  //virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
-  //                                            DeclTy *ExceptionDecl,
-  //                                            StmtArg HandlerBlock);
+  virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D);
+  virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
+                                              DeclTy *ExDecl,
+                                              StmtArg HandlerBlock);
   //virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
   //                                          StmtArg TryBlock,
   //                                          MultiStmtArg Handlers);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Dec 22 13:15:10 2008
@@ -2026,3 +2026,66 @@
   return LinkageSpecDecl::Create(Context, Loc, Language, dcl);
 }
 
+/// ActOnExceptionDeclarator - Parsed the exception-declarator in a C++ catch
+/// handler.
+Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
+{
+  QualType ExDeclType = GetTypeForDeclarator(D, S);
+  SourceLocation Begin = D.getDeclSpec().getSourceRange().getBegin();
+
+  bool Invalid = false;
+
+  // Arrays and functions decay.
+  if (ExDeclType->isArrayType())
+    ExDeclType = Context.getArrayDecayedType(ExDeclType);
+  else if (ExDeclType->isFunctionType())
+    ExDeclType = Context.getPointerType(ExDeclType);
+
+  // C++ 15.3p1: The exception-declaration shall not denote an incomplete type.
+  // The exception-declaration shall not denote a pointer or reference to an
+  // incomplete type, other than [cv] void*.
+  QualType BaseType = ExDeclType;
+  int Mode = 0; // 0 for direct type, 1 for pointer, 2 for reference
+  if (const PointerType *Ptr = BaseType->getAsPointerType()) {
+    BaseType = Ptr->getPointeeType();
+    Mode = 1;
+  } else if(const ReferenceType *Ref = BaseType->getAsReferenceType()) {
+    BaseType = Ref->getPointeeType();
+    Mode = 2;
+  }
+  if ((Mode == 0 || !BaseType->isVoidType()) && BaseType->isIncompleteType()) {
+    Invalid = true;
+    Diag(Begin, diag::err_catch_incomplete) << BaseType << Mode;
+  }
+
+  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
+    // it contains any previous declaration.
+    assert(!S->isDeclScope(PrevDecl));
+    if (PrevDecl->isTemplateParameter()) {
+      // Maybe we will complain about the shadowed template parameter.
+      DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
+
+    }
+  }
+
+  VarDecl *ExDecl = VarDecl::Create(Context, CurContext, D.getIdentifierLoc(),
+                                    II, ExDeclType, VarDecl::None, 0, Begin);
+  if (D.getInvalidType() || Invalid)
+    ExDecl->setInvalidDecl();
+
+  if (D.getCXXScopeSpec().isSet()) {
+    Diag(D.getIdentifierLoc(), diag::err_qualified_catch_declarator)
+      << D.getCXXScopeSpec().getRange();
+    ExDecl->setInvalidDecl();
+  }
+
+  // Add the exception declaration into this scope.
+  S->AddDecl(ExDecl);
+  if (II)
+    IdResolver.AddDecl(ExDecl);
+
+  ProcessDeclAttributes(ExDecl, D);
+  return ExDecl;
+}

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Dec 22 13:15:10 2008
@@ -951,3 +951,13 @@
     static_cast<Stmt*>(SynchExpr), static_cast<Stmt*>(SynchBody));
   return SS;
 }
+
+/// ActOnCXXCatchBlock - Takes an exception declaration and a handler block
+/// and creates a proper catch handler from them.
+Action::OwningStmtResult
+Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, DeclTy *ExDecl,
+                         StmtArg HandlerBlock) {
+  // There's nothing to test that ActOnExceptionDecl didn't already test.
+  return Owned(new CXXCatchStmt(CatchLoc, static_cast<VarDecl*>(ExDecl),
+                                static_cast<Stmt*>(HandlerBlock.release())));
+}

Added: cfe/trunk/test/SemaCXX/try-catch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/try-catch.cpp?rev=61337&view=auto

==============================================================================
--- cfe/trunk/test/SemaCXX/try-catch.cpp (added)
+++ cfe/trunk/test/SemaCXX/try-catch.cpp Mon Dec 22 13:15:10 2008
@@ -0,0 +1,19 @@
+// RUN: clang -fsyntax-only -verify %s
+
+struct A;
+
+void f()
+{
+  try {
+  } catch(int i) { // expected-note {{previous definition}}
+    int j = i;
+    int i; // expected-error {{redefinition of 'i'}}
+  } catch(float i) {
+  } catch(void v) { // expected-error {{cannot catch incomplete type 'void'}}
+  } catch(A a) { // expected-error {{cannot catch incomplete type 'struct A'}}
+  } catch(A *a) { // expected-error {{cannot catch pointer to incomplete type 'struct A'}}
+  } catch(A &a) { // expected-error {{cannot catch reference to incomplete type 'struct A'}}
+  } catch(...) {
+    int j = i; // expected-error {{use of undeclared identifier 'i'}}
+  }
+}





More information about the cfe-commits mailing list