Parser support for C++ try-catch.

llvm-svn: 61312
This commit is contained in:
Sebastian Redl 2008-12-21 16:41:36 +00:00
parent 7b9c57083b
commit b219c90d7b
9 changed files with 187 additions and 9 deletions

View File

@ -405,6 +405,26 @@ namespace {
return 0;
}
// C++ Statements
virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D) {
llvm::cout << __FUNCTION__ << "\n";
return 0;
}
virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
DeclTy *ExceptionDecl,
StmtArg HandlerBlock) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
StmtArg TryBlock,
MultiStmtArg Handlers) {
llvm::cout << __FUNCTION__ << "\n";
return StmtEmpty();
}
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//

View File

@ -605,6 +605,8 @@ DIAG(err_expected_member_or_base_name, ERROR,
"expected class member or base class name")
DIAG(ext_ellipsis_exception_spec, EXTENSION,
"exception specification of '...' is a Microsoft extension")
DIAG(err_expected_catch, ERROR,
"expected catch")
/// C++ Templates
DIAG(err_expected_template, ERROR,

View File

@ -479,6 +479,23 @@ public:
return 0;
}
// C++ Statements
virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D) {
return 0;
}
virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
DeclTy *ExceptionDecl,
StmtArg HandlerBlock) {
return StmtEmpty();
}
virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
StmtArg TryBlock,
MultiStmtArg Handlers) {
return StmtEmpty();
}
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//

View File

@ -646,7 +646,8 @@ public:
BlockContext, // Declaration within a block in a function.
ForContext, // Declaration within first part of a for loop.
ConditionContext, // Condition declaration in a C++ if/switch/while/for.
TemplateParamContext // Within a template parameter list.
TemplateParamContext,// Within a template parameter list.
CXXCatchContext // C++ catch exception-declaration
};
/// DeclaratorKind - The kind of declarator this represents.
@ -762,7 +763,7 @@ public:
/// parameter lists.
bool mayOmitIdentifier() const {
return Context == TypeNameContext || Context == PrototypeContext ||
Context == TemplateParamContext;
Context == TemplateParamContext || Context == CXXCatchContext;
}
/// mayHaveIdentifier - Return true if the identifier is either optional or

View File

@ -724,13 +724,23 @@ private:
OwningStmtResult ParseReturnStatement();
OwningStmtResult ParseAsmStatement(bool &msAsm);
OwningStmtResult FuzzyParseMicrosoftAsmStatement();
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
llvm::SmallVectorImpl<ExprTy*> &Constraints,
llvm::SmallVectorImpl<ExprTy*> &Exprs);
//===--------------------------------------------------------------------===//
// C++ 6: Statements and Blocks
OwningStmtResult ParseCXXTryBlock();
OwningStmtResult ParseCXXCatchBlock();
//===--------------------------------------------------------------------===//
// Objective-C Statements
OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc);
OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc);
OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc);
OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc);
bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,
llvm::SmallVectorImpl<ExprTy*> &Constraints,
llvm::SmallVectorImpl<ExprTy*> &Exprs);
//===--------------------------------------------------------------------===//

View File

@ -38,6 +38,7 @@ using namespace clang;
/// iteration-statement
/// jump-statement
/// [C++] declaration-statement
/// [C++] try-block
/// [OBC] objc-throw-statement
/// [OBC] objc-try-catch-statement
/// [OBC] objc-synchronized-statement
@ -161,7 +162,7 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
SemiError = "return statement";
break;
case tok::kw_asm:
case tok::kw_asm: {
bool msAsm = false;
Res = ParseAsmStatement(msAsm);
if (msAsm) return move(Res);
@ -169,6 +170,10 @@ Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
break;
}
case tok::kw_try: // C++ 15: try-block
return ParseCXXTryBlock();
}
// If we reached this code, the statement must end in a semicolon.
if (Tok.is(tok::semi)) {
ConsumeToken();
@ -1243,3 +1248,89 @@ Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl,
return Actions.ActOnFinishFunctionBody(Decl, move_convert(FnBody));
}
/// ParseCXXTryBlock - Parse a C++ try-block.
///
/// try-block:
/// 'try' compound-statement handler-seq
///
/// handler-seq:
/// handler handler-seq[opt]
///
Parser::OwningStmtResult Parser::ParseCXXTryBlock() {
assert(Tok.is(tok::kw_try) && "Expected 'try'");
SourceLocation TryLoc = ConsumeToken();
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
OwningStmtResult TryBlock(ParseCompoundStatement());
if (TryBlock.isInvalid())
return move(TryBlock);
StmtVector Handlers(Actions);
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
while (Tok.is(tok::kw_catch)) {
OwningStmtResult Handler(ParseCXXCatchBlock());
if (!Handler.isInvalid())
Handlers.push_back(Handler.release());
}
// Don't bother creating the full statement if we don't have any usable
// handlers.
if (Handlers.empty())
return StmtError();
return Actions.ActOnCXXTryBlock(TryLoc, move_convert(TryBlock),
move_convert(Handlers));
}
/// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
///
/// handler:
/// 'catch' '(' exception-declaration ')' compound-statement
///
/// exception-declaration:
/// type-specifier-seq declarator
/// type-specifier-seq abstract-declarator
/// type-specifier-seq
/// '...'
///
Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
SourceLocation CatchLoc = ConsumeToken();
SourceLocation LParenLoc = Tok.getLocation();
if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
return StmtError();
// C++ 3.3.2p3:
// The name in a catch exception-declaration is local to the handler and
// shall not be redeclared in the outermost block of the handler.
ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
// exception-declaration is equivalent to '...' or a parameter-declaration
// without default arguments.
DeclTy *ExceptionDecl = 0;
if (Tok.isNot(tok::ellipsis)) {
DeclSpec DS;
ParseDeclarationSpecifiers(DS);
Declarator ExDecl(DS, Declarator::CXXCatchContext);
ParseDeclarator(ExDecl);
ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
} else
ConsumeToken();
if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
return StmtError();
if (Tok.isNot(tok::l_brace))
return StmtError(Diag(Tok, diag::err_expected_lbrace));
OwningStmtResult Block(ParseCompoundStatement());
if (Block.isInvalid())
return move(Block);
return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl,
move_convert(Block));
}

View File

@ -151,6 +151,10 @@ bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
if (S->isDeclScope(D))
return true;
if (LangOpt.CPlusPlus) {
// C++ 3.3.2p3:
// The name declared in a catch exception-declaration is local to the
// handler and shall not be redeclared in the outermost block of the
// handler.
// C++ 3.3.2p4:
// Names declared in the for-init-statement, and in the condition of if,
// while, for, and switch statements are local to the if, while, for, or

View File

@ -632,6 +632,14 @@ public:
ExprTy *SynchExpr,
StmtTy *SynchBody);
//virtual DeclTy *ActOnExceptionDeclarator(Scope *S, Declarator &D);
//virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc,
// DeclTy *ExceptionDecl,
// StmtArg HandlerBlock);
//virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc,
// StmtArg TryBlock,
// MultiStmtArg Handlers);
//===--------------------------------------------------------------------===//
// Expression Parsing Callbacks: SemaExpr.cpp.

View File

@ -0,0 +1,25 @@
// RUN: clang -fsyntax-only -verify %s
void f()
{
try {
;
} catch(int i) {
;
} catch(...) {
}
}
void g()
{
try; // expected-error {{expected '{'}}
try {}
catch; // expected-error {{expected '('}}
try {}
catch (...); // expected-error {{expected '{'}}
try {}
catch {} // expected-error {{expected '('}}
}