Support C++ try/catch statements for PCH.

llvm-svn: 109112
This commit is contained in:
Argyrios Kyrtzidis 2010-07-22 16:03:56 +00:00
parent fd23a97d9c
commit 47cd7a91f4
6 changed files with 93 additions and 11 deletions

View File

@ -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<Stmt const * const*>(this + 1);
}
Stmt **getStmts() {
return reinterpret_cast<Stmt **>(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<Stmt const * const*>(this + 1);
return Stmts[NumHandlers]->getLocEnd();
return getStmts()[NumHandlers]->getLocEnd();
}
CompoundStmt *getTryBlock() {
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
return llvm::cast<CompoundStmt>(Stmts[0]);
return llvm::cast<CompoundStmt>(getStmts()[0]);
}
const CompoundStmt *getTryBlock() const {
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
return llvm::cast<CompoundStmt>(Stmts[0]);
return llvm::cast<CompoundStmt>(getStmts()[0]);
}
unsigned getNumHandlers() const { return NumHandlers; }
CXXCatchStmt *getHandler(unsigned i) {
Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]);
}
const CXXCatchStmt *getHandler(unsigned i) const {
Stmt const * const*Stmts = reinterpret_cast<Stmt const * const*>(this + 1);
return llvm::cast<CXXCatchStmt>(Stmts[i + 1]);
return llvm::cast<CXXCatchStmt>(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;
};

View File

@ -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,

View File

@ -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<CXXTryStmt>());
return new (Mem) CXXTryStmt(Empty, numHandlers);
}
CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
Stmt **handlers, unsigned numHandlers)
: Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) {

View File

@ -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<VarDecl>(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;

View File

@ -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());

View File

@ -88,7 +88,8 @@ template<unsigned N>
bool isInt(int x);
template<> bool isInt<8>(int x) {
return true;
try { ++x; } catch(...) { --x; }
return true;
}
template<typename _CharT>