From: Argyrios Kyrtzidis Date: Thu, 22 Jul 2010 16:03:56 +0000 (+0000) Subject: Support C++ try/catch statements for PCH. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7cb45e37b6f924d9ddbc53ac023bbaadb4ca3534;p=clang Support C++ try/catch statements for PCH. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109112 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 4e87c2701c..58d45e801e 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -37,6 +37,9 @@ public: : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), HandlerBlock(handlerBlock) {} + CXXCatchStmt(EmptyShell Empty) + : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} + virtual SourceRange getSourceRange() const { return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); } @@ -53,6 +56,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; }; /// CXXTryStmt - A C++ try block, including all handlers. @@ -64,38 +69,46 @@ class CXXTryStmt : public Stmt { CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + CXXTryStmt(EmptyShell Empty, unsigned numHandlers) + : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } + + Stmt const * const *getStmts() const { + return reinterpret_cast(this + 1); + } + Stmt **getStmts() { + return reinterpret_cast(this + 1); + } + public: static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers); + static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, + unsigned numHandlers); + virtual SourceRange getSourceRange() const { return SourceRange(getTryLoc(), getEndLoc()); } SourceLocation getTryLoc() const { return TryLoc; } SourceLocation getEndLoc() const { - Stmt const * const*Stmts = reinterpret_cast(this + 1); - return Stmts[NumHandlers]->getLocEnd(); + return getStmts()[NumHandlers]->getLocEnd(); } CompoundStmt *getTryBlock() { - Stmt **Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[0]); + return llvm::cast(getStmts()[0]); } const CompoundStmt *getTryBlock() const { - Stmt const * const*Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[0]); + return llvm::cast(getStmts()[0]); } unsigned getNumHandlers() const { return NumHandlers; } CXXCatchStmt *getHandler(unsigned i) { - Stmt **Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[i + 1]); + return llvm::cast(getStmts()[i + 1]); } const CXXCatchStmt *getHandler(unsigned i) const { - Stmt const * const*Stmts = reinterpret_cast(this + 1); - return llvm::cast(Stmts[i + 1]); + return llvm::cast(getStmts()[i + 1]); } static bool classof(const Stmt *T) { @@ -105,6 +118,8 @@ public: virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; }; diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 27a2b7d0b9..eab877aec9 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -755,6 +755,11 @@ namespace clang { STMT_OBJC_AT_THROW, // C++ + + /// \brief A CXXCatchStmt record. + STMT_CXX_CATCH, + /// \brief A CXXTryStmt record. + STMT_CXX_TRY, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 6dbe8f4d18..4222ce7edd 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -451,6 +451,15 @@ CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc, return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers); } +CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty, + unsigned numHandlers) { + std::size_t Size = sizeof(CXXTryStmt); + Size += ((numHandlers + 1) * sizeof(Stmt)); + + void *Mem = C.Allocate(Size, llvm::alignof()); + return new (Mem) CXXTryStmt(Empty, numHandlers); +} + CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, unsigned numHandlers) : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) { diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index 03df4d78d9..65502b8e26 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -116,6 +116,10 @@ namespace clang { void VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *); void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); + // C++ Statements + void VisitCXXCatchStmt(CXXCatchStmt *S); + void VisitCXXTryStmt(CXXTryStmt *S); + void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); void VisitCXXConstructExpr(CXXConstructExpr *E); void VisitCXXTemporaryObjectExpr(CXXTemporaryObjectExpr *E); @@ -923,6 +927,24 @@ void PCHStmtReader::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { //===----------------------------------------------------------------------===// // C++ Expressions and Statements +//===----------------------------------------------------------------------===// + +void PCHStmtReader::VisitCXXCatchStmt(CXXCatchStmt *S) { + VisitStmt(S); + S->CatchLoc = Reader.ReadSourceLocation(Record, Idx); + S->ExceptionDecl = cast_or_null(Reader.GetDecl(Record[Idx++])); + S->HandlerBlock = Reader.ReadSubStmt(); +} + +void PCHStmtReader::VisitCXXTryStmt(CXXTryStmt *S) { + VisitStmt(S); + assert(Record[Idx] == S->getNumHandlers() && "NumStmtFields is wrong ?"); + ++Idx; + S->TryLoc = Reader.ReadSourceLocation(Record, Idx); + S->getStmts()[0] = Reader.ReadSubStmt(); + for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) + S->getStmts()[i + 1] = Reader.ReadSubStmt(); +} void PCHStmtReader::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); @@ -1587,6 +1609,15 @@ Stmt *PCHReader::ReadStmtFromStream(llvm::BitstreamCursor &Cursor) { S = new (Context) ObjCAtThrowStmt(Empty); break; + case pch::STMT_CXX_CATCH: + S = new (Context) CXXCatchStmt(Empty); + break; + + case pch::STMT_CXX_TRY: + S = CXXTryStmt::Create(*Context, Empty, + /*NumHandlers=*/Record[PCHStmtReader::NumStmtFields]); + break; + case pch::EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(*Context, Empty); break; diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index 90e48c457f..e807ddff09 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -115,6 +115,9 @@ namespace clang { void VisitObjCAtThrowStmt(ObjCAtThrowStmt *); // C++ Statements + void VisitCXXCatchStmt(CXXCatchStmt *S); + void VisitCXXTryStmt(CXXTryStmt *S); + void VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E); void VisitCXXMemberCallExpr(CXXMemberCallExpr *E); void VisitCXXConstructExpr(CXXConstructExpr *E); @@ -929,6 +932,24 @@ void PCHStmtWriter::VisitObjCAtThrowStmt(ObjCAtThrowStmt *S) { // C++ Expressions and Statements. //===----------------------------------------------------------------------===// +void PCHStmtWriter::VisitCXXCatchStmt(CXXCatchStmt *S) { + VisitStmt(S); + Writer.AddSourceLocation(S->getCatchLoc(), Record); + Writer.AddDeclRef(S->getExceptionDecl(), Record); + Writer.AddStmt(S->getHandlerBlock()); + Code = pch::STMT_CXX_CATCH; +} + +void PCHStmtWriter::VisitCXXTryStmt(CXXTryStmt *S) { + VisitStmt(S); + Record.push_back(S->getNumHandlers()); + Writer.AddSourceLocation(S->getTryLoc(), Record); + Writer.AddStmt(S->getTryBlock()); + for (unsigned i = 0, e = S->getNumHandlers(); i != e; ++i) + Writer.AddStmt(S->getHandler(i)); + Code = pch::STMT_CXX_TRY; +} + void PCHStmtWriter::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *E) { VisitCallExpr(E); Record.push_back(E->getOperator()); diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index 42c47f0307..47fa11eb08 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -88,7 +88,8 @@ template bool isInt(int x); template<> bool isInt<8>(int x) { - return true; + try { ++x; } catch(...) { --x; } + return true; } template