diff options
author | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-21 16:41:36 +0000 |
---|---|---|
committer | Sebastian Redl <sebastian.redl@getdesigned.at> | 2008-12-21 16:41:36 +0000 |
commit | a0fd8652f3302d0f39ed9849b521ee5b76597b0a (patch) | |
tree | b2fd4be9481d12209c0590794585a0fc1469c427 | |
parent | c994bb2b800d4aef4c42b5a58f33cb7816dbf7f0 (diff) |
Parser support for C++ try-catch.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@61312 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | Driver/PrintParserCallbacks.cpp | 22 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 2 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 19 | ||||
-rw-r--r-- | include/clang/Parse/DeclSpec.h | 5 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 16 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 93 | ||||
-rw-r--r-- | lib/Sema/IdentifierResolver.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 10 | ||||
-rw-r--r-- | test/Parser/cxx-try.cpp | 25 |
9 files changed, 187 insertions, 9 deletions
diff --git a/Driver/PrintParserCallbacks.cpp b/Driver/PrintParserCallbacks.cpp index 02b33fcc0f..3f6562893c 100644 --- a/Driver/PrintParserCallbacks.cpp +++ b/Driver/PrintParserCallbacks.cpp @@ -404,7 +404,27 @@ namespace { llvm::cout << __FUNCTION__ << "\n"; 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. //===--------------------------------------------------------------------===// diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index df21d8d30e..510f3ff916 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -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, diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 3031206dd6..249f1224c7 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -478,7 +478,24 @@ public: StmtTy *SynchBody) { 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. //===--------------------------------------------------------------------===// diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 4a97fd60ed..8b2033bfbe 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -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 diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index df6eca6432..fb1ebcf36e 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -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); //===--------------------------------------------------------------------===// diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index c605bf2352..81a9765555 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -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)); +} diff --git a/lib/Sema/IdentifierResolver.cpp b/lib/Sema/IdentifierResolver.cpp index 4441503528..027beede49 100644 --- a/lib/Sema/IdentifierResolver.cpp +++ b/lib/Sema/IdentifierResolver.cpp @@ -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 diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index e5146a23bb..b620b70be0 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -631,7 +631,15 @@ public: virtual StmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, 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. diff --git a/test/Parser/cxx-try.cpp b/test/Parser/cxx-try.cpp new file mode 100644 index 0000000000..642c8f6fe8 --- /dev/null +++ b/test/Parser/cxx-try.cpp @@ -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 '('}} +} |