diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 252 |
1 files changed, 163 insertions, 89 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index a2b7cdd..fdb9788 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -76,14 +76,15 @@ using namespace clang; /// [OBC] '@' 'throw' ';' /// StmtResult -Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { +Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, + SourceLocation *TrailingElseLoc) { const char *SemiError = 0; StmtResult Res; ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX0XAttributes(attrs, 0, /*MightBeObjCMessageSend*/ true); // Cases in this switch statement should fall through if the parser expects // the token to end in a semicolon (in which case SemiError should be set), @@ -115,7 +116,7 @@ Retry: IdentifierInfo *Name = Tok.getIdentifierInfo(); SourceLocation NameLoc = Tok.getLocation(); - if (getLang().CPlusPlus) + if (getLangOpts().CPlusPlus) CheckForTemplateAndDigraph(Next, ParsedType(), /*EnteringContext=*/false, *Name, SS); @@ -170,7 +171,7 @@ Retry: if (AnnotateTemplateIdToken( TemplateTy::make(Classification.getTemplateName()), Classification.getTemplateNameKind(), - SS, Id, SourceLocation(), + SS, SourceLocation(), Id, /*AllowTypeAnnotation=*/false)) { // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. @@ -206,7 +207,7 @@ Retry: } default: { - if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { + if ((getLangOpts().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy Decl = ParseDeclaration(Stmts, Declarator::BlockContext, DeclEnd, attrs); @@ -234,18 +235,18 @@ Retry: } case tok::kw_if: // C99 6.8.4.1: if-statement - return ParseIfStatement(attrs); + return ParseIfStatement(attrs, TrailingElseLoc); case tok::kw_switch: // C99 6.8.4.2: switch-statement - return ParseSwitchStatement(attrs); + return ParseSwitchStatement(attrs, TrailingElseLoc); case tok::kw_while: // C99 6.8.5.1: while-statement - return ParseWhileStatement(attrs); + return ParseWhileStatement(attrs, TrailingElseLoc); case tok::kw_do: // C99 6.8.5.2: do-statement Res = ParseDoStatement(attrs); SemiError = "do/while"; break; case tok::kw_for: // C99 6.8.5.3: for-statement - return ParseForStatement(attrs); + return ParseForStatement(attrs, TrailingElseLoc); case tok::kw_goto: // C99 6.8.6.1: goto-statement Res = ParseGotoStatement(attrs); @@ -279,6 +280,14 @@ Retry: case tok::kw___try: return ParseSEHTryBlock(attrs); + + case tok::annot_pragma_vis: + HandlePragmaVisibility(); + return StmtEmpty(); + + case tok::annot_pragma_pack: + HandlePragmaPack(); + return StmtEmpty(); } // If we reached this code, the statement must end in a semicolon. @@ -355,7 +364,8 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { return move(TryBlock); StmtResult Handler; - if(Tok.is(tok::kw___except)) { + if (Tok.is(tok::identifier) && + Tok.getIdentifierInfo() == getSEHExceptKeyword()) { SourceLocation Loc = ConsumeToken(); Handler = ParseSEHExceptBlock(Loc); } else if (Tok.is(tok::kw___finally)) { @@ -389,14 +399,14 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); - if (getLang().Borland) { + if (getLangOpts().Borland) { Ident__exception_info->setIsPoisoned(false); Ident___exception_info->setIsPoisoned(false); Ident_GetExceptionInfo->setIsPoisoned(false); } ExprResult FilterExpr(ParseExpression()); - if (getLang().Borland) { + if (getLangOpts().Borland) { Ident__exception_info->setIsPoisoned(true); Ident___exception_info->setIsPoisoned(true); Ident_GetExceptionInfo->setIsPoisoned(true); @@ -594,7 +604,8 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, // Nicely diagnose the common error "switch (X) { case 4: }", which is // not valid. SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); - Diag(AfterColonLoc, diag::err_label_end_of_compound_statement); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); SubStmt = true; } @@ -636,16 +647,22 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) { ColonLoc = ExpectedLoc; } - // Diagnose the common error "switch (X) {... default: }", which is not valid. - if (Tok.is(tok::r_brace)) { + StmtResult SubStmt; + + if (Tok.isNot(tok::r_brace)) { + SubStmt = ParseStatement(); + } else { + // Diagnose the common error "switch (X) {... default: }", which is + // not valid. SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); - Diag(AfterColonLoc, diag::err_label_end_of_compound_statement); - return StmtError(); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); + SubStmt = true; } - StmtResult SubStmt(ParseStatement()); + // Broken sub-stmt shouldn't prevent forming the case statement properly. if (SubStmt.isInvalid()) - return StmtError(); + SubStmt = Actions.ActOnNullStmt(ColonLoc); return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc, SubStmt.get(), getCurScope()); @@ -698,7 +715,6 @@ StmtResult Parser::ParseCompoundStatement(ParsedAttributes &attrs, return ParseCompoundStatementBody(isStmtExpr); } - /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the /// ActOnCompoundStmt action. This expects the '{' to be the current token, and /// consume the '}' at the end of the block. It does not manipulate the scope @@ -712,6 +728,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (T.consumeOpen()) return StmtError(); + Sema::CompoundScopeRAII CompoundScope(Actions); + StmtVector Stmts(Actions); // "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are @@ -752,7 +770,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { continue; } - if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) || + if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsStatement(Stmts); continue; @@ -771,7 +789,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ConsumeToken(); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX0XAttributes(attrs); + MaybeParseCXX0XAttributes(attrs, 0, /*MightBeObjCMessageSend*/ true); // If this is the start of a declaration, parse it as such. if (isDeclarationStatement()) { @@ -805,17 +823,20 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Stmts.push_back(R.release()); } + SourceLocation CloseLoc = Tok.getLocation(); + // We broke out of the while loop because we found a '}' or EOF. if (Tok.isNot(tok::r_brace)) { Diag(Tok, diag::err_expected_rbrace); Diag(T.getOpenLocation(), diag::note_matching) << "{"; - return StmtError(); + // Recover by creating a compound statement with what we parsed so far, + // instead of dropping everything and returning StmtError(); + } else { + if (!T.consumeClose()) + CloseLoc = T.getCloseLocation(); } - if (T.consumeClose()) - return StmtError(); - - return Actions.ActOnCompoundStmt(T.getOpenLocation(), T.getCloseLocation(), + return Actions.ActOnCompoundStmt(T.getOpenLocation(), CloseLoc, move_arg(Stmts), isStmtExpr); } @@ -837,7 +858,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - if (getLang().CPlusPlus) + if (getLangOpts().CPlusPlus) ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { ExprResult = ParseExpression(); @@ -873,7 +894,8 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, /// [C++] 'if' '(' condition ')' statement /// [C++] 'if' '(' condition ')' statement 'else' statement /// -StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { +StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs, + SourceLocation *TrailingElseLoc) { // FIXME: Use attributes? assert(Tok.is(tok::kw_if) && "Not an if stmt!"); @@ -885,7 +907,7 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { return StmtError(); } - bool C99orCXX = getLang().C99 || getLang().CPlusPlus; + bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; // C99 6.8.4p3 - In C99, the if statement is a block. This is not // the case for C90. @@ -932,7 +954,9 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { // Read the 'then' stmt. SourceLocation ThenStmtLoc = Tok.getLocation(); - StmtResult ThenStmt(ParseStatement()); + + SourceLocation InnerStatementTrailingElseLoc; + StmtResult ThenStmt(ParseStatement(&InnerStatementTrailingElseLoc)); // Pop the 'if' scope if needed. InnerScope.Exit(); @@ -943,6 +967,9 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { StmtResult ElseStmt; if (Tok.is(tok::kw_else)) { + if (TrailingElseLoc) + *TrailingElseLoc = Tok.getLocation(); + ElseLoc = ConsumeToken(); ElseStmtLoc = Tok.getLocation(); @@ -966,6 +993,8 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { Actions.CodeCompleteAfterIf(getCurScope()); cutOffParsing(); return StmtError(); + } else if (InnerStatementTrailingElseLoc.isValid()) { + Diag(InnerStatementTrailingElseLoc, diag::warn_dangling_else); } IfScope.Exit(); @@ -999,7 +1028,8 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { /// switch-statement: /// 'switch' '(' expression ')' statement /// [C++] 'switch' '(' condition ')' statement -StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { +StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs, + SourceLocation *TrailingElseLoc) { // FIXME: Use attributes? assert(Tok.is(tok::kw_switch) && "Not a switch stmt!"); @@ -1011,7 +1041,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { return StmtError(); } - bool C99orCXX = getLang().C99 || getLang().CPlusPlus; + bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; // C99 6.8.4p3 - In C99, the switch statement is a block. This is // not the case for C90. Start the switch scope. @@ -1067,15 +1097,20 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { C99orCXX && Tok.isNot(tok::l_brace)); // Read the body statement. - StmtResult Body(ParseStatement()); + StmtResult Body(ParseStatement(TrailingElseLoc)); // Pop the scopes. InnerScope.Exit(); SwitchScope.Exit(); - if (Body.isInvalid()) + if (Body.isInvalid()) { // FIXME: Remove the case statement list from the Switch statement. - Body = Actions.ActOnNullStmt(Tok.getLocation()); + + // Put the synthesized null statement on the same line as the end of switch + // condition. + SourceLocation SynthesizedNullStmtLocation = Cond.get()->getLocEnd(); + Body = Actions.ActOnNullStmt(SynthesizedNullStmtLocation); + } return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } @@ -1084,7 +1119,8 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { /// while-statement: [C99 6.8.5.1] /// 'while' '(' expression ')' statement /// [C++] 'while' '(' condition ')' statement -StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) { +StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs, + SourceLocation *TrailingElseLoc) { // FIXME: Use attributes? assert(Tok.is(tok::kw_while) && "Not a while stmt!"); @@ -1097,7 +1133,7 @@ StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) { return StmtError(); } - bool C99orCXX = getLang().C99 || getLang().CPlusPlus; + bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; // C99 6.8.5p5 - In C99, the while statement is a block. This is not // the case for C90. Start the loop scope. @@ -1142,7 +1178,7 @@ StmtResult Parser::ParseWhileStatement(ParsedAttributes &attrs) { C99orCXX && Tok.isNot(tok::l_brace)); // Read the body statement. - StmtResult Body(ParseStatement()); + StmtResult Body(ParseStatement(TrailingElseLoc)); // Pop the body scope if needed. InnerScope.Exit(); @@ -1167,7 +1203,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { // C99 6.8.5p5 - In C99, the do statement is a block. This is not // the case for C90. Start the loop scope. unsigned ScopeFlags; - if (getLang().C99) + if (getLangOpts().C99) ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope; else ScopeFlags = Scope::BreakScope | Scope::ContinueScope; @@ -1183,7 +1219,7 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { // which is entered and exited each time through the loop. // ParseScope InnerScope(this, Scope::DeclScope, - (getLang().C99 || getLang().CPlusPlus) && + (getLangOpts().C99 || getLangOpts().CPlusPlus) && Tok.isNot(tok::l_brace)); // Read the body statement. @@ -1241,7 +1277,8 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { /// [C++0x] for-range-initializer: /// [C++0x] expression /// [C++0x] braced-init-list [TODO] -StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { +StmtResult Parser::ParseForStatement(ParsedAttributes &attrs, + SourceLocation *TrailingElseLoc) { // FIXME: Use attributes? assert(Tok.is(tok::kw_for) && "Not a for stmt!"); @@ -1253,7 +1290,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { return StmtError(); } - bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1; + bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus || getLangOpts().ObjC1; // C99 6.8.5p5 - In C99, the for statement is a block. This is not // the case for C90. Start the loop scope. @@ -1305,7 +1342,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { if (Tok.is(tok::semi)) { // for (; // no first part, eat the ';'. ConsumeToken(); - } else if (isSimpleDeclaration()) { // for (int X = 4; + } else if (isForInitDeclaration()) { // for (int X = 4; // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); @@ -1314,7 +1351,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { MaybeParseCXX0XAttributes(attrs); // In C++0x, "for (T NS:a" might not be a typo for :: - bool MightBeForRangeStmt = getLang().CPlusPlus; + bool MightBeForRangeStmt = getLangOpts().CPlusPlus; ColonProtectionRAIIObject ColonProtection(*this, MightBeForRangeStmt); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; @@ -1326,8 +1363,8 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { - if (!getLang().CPlusPlus0x) - Diag(ForRangeInit.ColonLoc, diag::ext_for_range); + Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_for_range : diag::ext_for_range); ForRange = true; } else if (Tok.is(tok::semi)) { // for (int x = 4; @@ -1370,6 +1407,13 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { return StmtError(); } Collection = ParseExpression(); + } else if (getLangOpts().CPlusPlus0x && Tok.is(tok::colon) && FirstPart.get()) { + // User tried to write the reasonable, but ill-formed, for-range-statement + // for (expr : expr) { ... } + Diag(Tok, diag::err_for_range_expected_decl) + << FirstPart.get()->getSourceRange(); + SkipUntil(tok::r_paren, false, true); + SecondPartIsInvalid = true; } else { if (!Value.isInvalid()) { Diag(Tok, diag::err_expected_semi_for); @@ -1390,7 +1434,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { // missing both semicolons. } else { ExprResult Second; - if (getLang().CPlusPlus) + if (getLangOpts().CPlusPlus) ParseCXXCondition(Second, SecondVar, ForLoc, true); else { Second = ParseExpression(); @@ -1458,7 +1502,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { C99orCXXorObjC && Tok.isNot(tok::l_brace)); // Read the body statement. - StmtResult Body(ParseStatement()); + StmtResult Body(ParseStatement(TrailingElseLoc)); // Pop the body scope if needed. InnerScope.Exit(); @@ -1564,13 +1608,12 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { return StmtError(); } - // FIXME: This is a hack to allow something like C++0x's generalized - // initializer lists, but only enough of this feature to allow Clang to - // parse libstdc++ 4.5's headers. - if (Tok.is(tok::l_brace) && getLang().CPlusPlus) { + if (Tok.is(tok::l_brace) && getLangOpts().CPlusPlus) { R = ParseInitializer(); - if (R.isUsable() && !getLang().CPlusPlus0x) - Diag(R.get()->getLocStart(), diag::ext_generalized_initializer_lists) + if (R.isUsable()) + Diag(R.get()->getLocStart(), getLangOpts().CPlusPlus0x ? + diag::warn_cxx98_compat_generalized_initializer_lists : + diag::ext_generalized_initializer_lists) << R.get()->getSourceRange(); } else R = ParseExpression(); @@ -1731,7 +1774,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLang().MicrosoftExt && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { + if (getLangOpts().MicrosoftExt && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); } @@ -1756,8 +1799,11 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { T.consumeOpen(); ExprResult AsmString(ParseAsmStringLiteral()); - if (AsmString.isInvalid()) + if (AsmString.isInvalid()) { + // Consume up to and including the closing paren. + T.skipToEnd(); return StmtError(); + } SmallVector<IdentifierInfo *, 4> Names; ExprVector Constraints(Actions); @@ -1906,19 +1952,15 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, if (Tok.isNot(tok::comma)) return false; ConsumeToken(); } - - return true; } Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - if (PP.isCodeCompletionEnabled()) { - if (trySkippingFunctionBodyForCodeCompletion()) { - BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, 0); - } + if (SkipFunctionBodies && trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnFinishFunctionBody(Decl, 0); } PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, @@ -1930,9 +1972,11 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { StmtResult FnBody(ParseCompoundStatementBody()); // If the function body could not be parsed, make a bogus compoundstmt. - if (FnBody.isInvalid()) + if (FnBody.isInvalid()) { + Sema::CompoundScopeRAII CompoundScope(Actions); FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, MultiStmtArg(Actions), false); + } BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); @@ -1956,36 +2000,36 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { else Actions.ActOnDefaultCtorInitializers(Decl); - if (PP.isCodeCompletionEnabled()) { - if (trySkippingFunctionBodyForCodeCompletion()) { - BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, 0); - } + if (SkipFunctionBodies && trySkippingFunctionBody()) { + BodyScope.Exit(); + return Actions.ActOnFinishFunctionBody(Decl, 0); } SourceLocation LBraceLoc = Tok.getLocation(); StmtResult 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()) + if (FnBody.isInvalid()) { + Sema::CompoundScopeRAII CompoundScope(Actions); FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, MultiStmtArg(Actions), false); + } BodyScope.Exit(); return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); } -bool Parser::trySkippingFunctionBodyForCodeCompletion() { +bool Parser::trySkippingFunctionBody() { assert(Tok.is(tok::l_brace)); - assert(PP.isCodeCompletionEnabled() && - "Should only be called when in code-completion mode"); + assert(SkipFunctionBodies && + "Should only be called when SkipFunctionBodies is enabled"); // We're in code-completion mode. Skip parsing for all function bodies unless // the body contains the code-completion point. TentativeParsingAction PA(*this); ConsumeBrace(); if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false, - /*StopAtCodeCompletion=*/true)) { + /*StopAtCodeCompletion=*/PP.isCodeCompletionEnabled())) { PA.Commit(); return true; } @@ -2035,10 +2079,13 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { return move(TryBlock); // Borland allows SEH-handlers with 'try' - if(Tok.is(tok::kw___except) || Tok.is(tok::kw___finally)) { + + if((Tok.is(tok::identifier) && + Tok.getIdentifierInfo() == getSEHExceptKeyword()) || + Tok.is(tok::kw___finally)) { // TODO: Factor into common return ParseSEHHandlerCommon(...) StmtResult Handler; - if(Tok.is(tok::kw___except)) { + if(Tok.getIdentifierInfo() == getSEHExceptKeyword()) { SourceLocation Loc = ConsumeToken(); Handler = ParseSEHExceptBlock(Loc); } @@ -2130,19 +2177,51 @@ StmtResult Parser::ParseCXXCatchBlock() { } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { - bool Result; + IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - if (Tok.isNot(tok::l_brace)) { + // Handle dependent statements by parsing the braces as a compound statement. + // This is not the same behavior as Visual C++, which don't treat this as a + // compound statement, but for Clang's type checking we can't have anything + // inside these braces escaping to the surrounding code. + if (Result.Behavior == IEB_Dependent) { + if (!Tok.is(tok::l_brace)) { + Diag(Tok, diag::err_expected_lbrace); + return; + } + + ParsedAttributes Attrs(AttrFactory); + StmtResult Compound = ParseCompoundStatement(Attrs); + if (Compound.isInvalid()) + return; + + StmtResult DepResult = Actions.ActOnMSDependentExistsStmt(Result.KeywordLoc, + Result.IsIfExists, + Result.SS, + Result.Name, + Compound.get()); + if (DepResult.isUsable()) + Stmts.push_back(DepResult.get()); + return; + } + + BalancedDelimiterTracker Braces(*this, tok::l_brace); + if (Braces.consumeOpen()) { Diag(Tok, diag::err_expected_lbrace); return; } - ConsumeBrace(); - // Condition is false skip all inside the {}. - if (!Result) { - SkipUntil(tok::r_brace, false); + switch (Result.Behavior) { + case IEB_Parse: + // Parse the statements below. + break; + + case IEB_Dependent: + llvm_unreachable("Dependent case handled above"); + + case IEB_Skip: + Braces.skipToEnd(); return; } @@ -2152,10 +2231,5 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { if (R.isUsable()) Stmts.push_back(R.release()); } - - if (Tok.isNot(tok::r_brace)) { - Diag(Tok, diag::err_expected_rbrace); - return; - } - ConsumeBrace(); + Braces.consumeClose(); } |