forked from OSchip/llvm-project
Full AST support and better Sema support for C++ try-catch.
llvm-svn: 61346
This commit is contained in:
parent
014caa431c
commit
9b244a8797
|
@ -1238,6 +1238,46 @@ public:
|
|||
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
|
||||
|
|
|
@ -55,8 +55,9 @@ STMT(ObjCForCollectionStmt, Stmt)
|
|||
|
||||
// C++ statements
|
||||
STMT(CXXCatchStmt, Stmt)
|
||||
STMT(CXXTryStmt , Stmt)
|
||||
|
||||
LAST_STMT(CXXCatchStmt)
|
||||
LAST_STMT(CXXTryStmt)
|
||||
|
||||
// Expressions.
|
||||
STMT(Expr , Stmt)
|
||||
|
|
|
@ -1319,6 +1319,8 @@ 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_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")
|
||||
|
|
|
@ -350,6 +350,18 @@ QualType CXXCatchStmt::getCaughtType() {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace {
|
|||
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 @@ void StmtPrinter::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *Node) {
|
|||
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";
|
||||
}
|
||||
|
||||
|
|
|
@ -1540,3 +1540,19 @@ CXXCatchStmt::CreateImpl(llvm::Deserializer& D, ASTContext& C) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -640,9 +640,9 @@ public:
|
|||
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.
|
||||
|
|
|
@ -2058,6 +2058,10 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
|
|||
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
|
||||
|
|
|
@ -961,3 +961,31 @@ Sema::ActOnCXXCatchBlock(SourceLocation CatchLoc, DeclTy *ExDecl,
|
|||
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));
|
||||
}
|
||||
|
|
|
@ -16,4 +16,9 @@ void f()
|
|||
} catch(...) {
|
||||
int j = i; // expected-error {{use of undeclared identifier 'i'}}
|
||||
}
|
||||
|
||||
try {
|
||||
} catch(...) { // expected-error {{catch-all handler must come last}}
|
||||
} catch(int) {
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue