diff options
Diffstat (limited to 'clang/lib/Parse')
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 27 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Parse/ParseStmt.cpp | 48 | ||||
-rw-r--r-- | clang/lib/Parse/Parser.cpp | 13 |
4 files changed, 75 insertions, 17 deletions
diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 45eaa746817..a2f93b46cab 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -17,15 +17,15 @@ #include "clang/Parse/Scope.h" using namespace clang; -/// ParseInlineCXXMethodDef - We parsed and verified that the specified +/// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. Parser::DeclPtrTy Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && "This isn't a function declarator!"); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && - "Current token not a '{' or ':'!"); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) && + "Current token not a '{', ':' or 'try'!"); DeclPtrTy FnD = Actions.ActOnCXXMemberDeclarator(CurScope, AS, D, 0, 0); @@ -34,8 +34,9 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { getCurTopClassStack().MethodDefs.push_back(LexedMethod(FnD)); CachedTokens &Toks = getCurTopClassStack().MethodDefs.back().Toks; - // We may have a constructor initializer here. - if (Tok.is(tok::colon)) { + tok::TokenKind kind = Tok.getKind(); + // We may have a constructor initializer or function-try-block here. + if (kind == tok::colon || kind == tok::kw_try) { // Consume everything up to (and including) the left brace. if (!ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks, tok::semi)) { // We didn't find the left-brace we expected after the @@ -58,6 +59,14 @@ Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D) { // Consume everything up to (and including) the matching right brace. ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); + // If we're in a function-try-block, we need to store all the catch blocks. + if (kind == tok::kw_try) { + while (Tok.is(tok::kw_catch)) { + ConsumeAndStoreUntil(tok::l_brace, tok::unknown, Toks); + ConsumeAndStoreUntil(tok::r_brace, tok::unknown, Toks); + } + } + return FnD; } @@ -126,14 +135,18 @@ void Parser::ParseLexedMethodDefs() { // Consume the previously pushed token. ConsumeAnyToken(); - assert((Tok.is(tok::l_brace) || Tok.is(tok::colon)) && - "Inline method not starting with '{' or ':'"); + assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) + && "Inline method not starting with '{', ':' or 'try'"); // Parse the method body. Function body parsing code is similar enough // to be re-used for method bodies as well. ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); Actions.ActOnStartOfFunctionDef(CurScope, LM.D); + if (Tok.is(tok::kw_try)) { + ParseFunctionTryBlock(LM.D); + return; + } if (Tok.is(tok::colon)) ParseConstructorInitializer(LM.D); // FIXME: What if ParseConstructorInitializer doesn't leave us with a '{'?? diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index d4310e0cbf4..c6a373dc5c4 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -737,7 +737,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS) { // function-definition: if (Tok.is(tok::l_brace) - || (DeclaratorInfo.isFunctionDeclarator() && Tok.is(tok::colon))) { + || (DeclaratorInfo.isFunctionDeclarator() && + (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { if (!DeclaratorInfo.isFunctionDeclarator()) { Diag(Tok, diag::err_func_def_no_params); ConsumeBrace(); @@ -1044,6 +1045,7 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) { break; else { // Skip over garbage, until we get to '{'. Don't eat the '{'. + Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma); SkipUntil(tok::l_brace, true, true); break; } diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index fa712e0a9eb..ce887287360 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -1289,7 +1289,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) { assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - + PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions, PP.getSourceManager(), "parsing function body"); @@ -1307,18 +1307,58 @@ Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) { return Actions.ActOnFinishFunctionBody(Decl, move(FnBody)); } +/// ParseFunctionTryBlock - Parse a C++ function-try-block. +/// +/// function-try-block: +/// 'try' ctor-initializer[opt] compound-statement handler-seq +/// +Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) { + assert(Tok.is(tok::kw_try) && "Expected 'try'"); + SourceLocation TryLoc = ConsumeToken(); + + PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions, + PP.getSourceManager(), + "parsing function try block"); + + // Constructor initializer list? + if (Tok.is(tok::colon)) + ParseConstructorInitializer(Decl); + + OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc)); + // If we failed to parse the try-catch, we just give the function an empty + // compound statement as the body. + if (FnBody.isInvalid()) + FnBody = Actions.ActOnCompoundStmt(TryLoc, TryLoc, + MultiStmtArg(Actions), false); + + return Actions.ActOnFinishFunctionBody(Decl, move(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(); + return ParseCXXTryBlockCommon(TryLoc); +} + +/// ParseCXXTryBlockCommon - Parse the common part of try-block and +/// function-try-block. +/// +/// try-block: +/// 'try' compound-statement handler-seq +/// +/// function-try-block: +/// 'try' ctor-initializer[opt] compound-statement handler-seq +/// +/// handler-seq: +/// handler handler-seq[opt] +/// +Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Tok.isNot(tok::l_brace)) return StmtError(Diag(Tok, diag::err_expected_lbrace)); OwningStmtResult TryBlock(ParseCompoundStatement()); diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index a245ac2156b..94036dbd86e 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -536,7 +536,8 @@ Parser::ParseDeclarationOrFunctionDefinition( (!getLang().CPlusPlus && isDeclarationSpecifier()) || // int X(f) int f; {} (getLang().CPlusPlus && - Tok.is(tok::colon)))) { // X() : Base() {} (used for ctors) + (Tok.is(tok::colon) || // X() : Base() {} (used for ctors) + Tok.is(tok::kw_try))))) { // X() try { ... } if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(Tok, diag::err_function_declared_typedef); @@ -575,7 +576,7 @@ Parser::ParseDeclarationOrFunctionDefinition( /// decl-specifier-seq[opt] declarator ctor-initializer[opt] /// function-body /// [C++] function-definition: [C++ 8.4] -/// decl-specifier-seq[opt] declarator function-try-block [TODO] +/// decl-specifier-seq[opt] declarator function-try-block /// Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); @@ -602,8 +603,8 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { // We should have either an opening brace or, in a C++ constructor, // we may have a colon. - // FIXME: In C++, we might also find the 'try' keyword. - if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon)) { + if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) && + Tok.isNot(tok::kw_try)) { Diag(Tok, diag::err_expected_fn_body); // Skip over garbage, until we get to '{'. Don't eat the '{'. @@ -621,12 +622,14 @@ Parser::DeclPtrTy Parser::ParseFunctionDefinition(Declarator &D) { // specified Declarator for the function. DeclPtrTy Res = Actions.ActOnStartOfFunctionDef(CurScope, D); + if (Tok.is(tok::kw_try)) + return ParseFunctionTryBlock(Res); + // If we have a colon, then we're probably parsing a C++ // ctor-initializer. if (Tok.is(tok::colon)) ParseConstructorInitializer(Res); - SourceLocation BraceLoc = Tok.getLocation(); return ParseFunctionStatementBody(Res); } |