diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 395 |
1 files changed, 255 insertions, 140 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index b91bca5..a2b7cdd 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -79,7 +79,7 @@ StmtResult Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement) { const char *SemiError = 0; StmtResult Res; - + ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange attrs(AttrFactory); @@ -100,20 +100,25 @@ Retry: case tok::code_completion: Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Statement); - ConsumeCodeCompletionToken(); - return ParseStatementOrDeclaration(Stmts, OnlyStatement); - + cutOffParsing(); + return StmtError(); + case tok::identifier: { Token Next = NextToken(); if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement // identifier ':' statement return ParseLabeledStatement(attrs); } - + if (Next.isNot(tok::coloncolon)) { CXXScopeSpec SS; IdentifierInfo *Name = Tok.getIdentifierInfo(); SourceLocation NameLoc = Tok.getLocation(); + + if (getLang().CPlusPlus) + CheckForTemplateAndDigraph(Next, ParsedType(), + /*EnteringContext=*/false, *Name, SS); + Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next); switch (Classification.getKind()) { @@ -125,11 +130,11 @@ Retry: Tok.setKind(Name->getTokenID()); goto Retry; } - + // Fall through via the normal error path. // FIXME: This seems like it could only happen for context-sensitive // keywords. - + case Sema::NC_Error: // Handle errors here by skipping up to the next semicolon or '}', and // eat the semicolon if that's what stopped us. @@ -137,33 +142,33 @@ Retry: if (Tok.is(tok::semi)) ConsumeToken(); return StmtError(); - + case Sema::NC_Unknown: // Either we don't know anything about this identifier, or we know that - // we're in a syntactic context we haven't handled yet. - break; - + // we're in a syntactic context we haven't handled yet. + break; + case Sema::NC_Type: Tok.setKind(tok::annot_typename); setTypeAnnotation(Tok, Classification.getType()); Tok.setAnnotationEndLoc(NameLoc); PP.AnnotateCachedTokens(Tok); break; - + case Sema::NC_Expression: Tok.setKind(tok::annot_primary_expr); setExprAnnotation(Tok, Classification.getExpression()); Tok.setAnnotationEndLoc(NameLoc); PP.AnnotateCachedTokens(Tok); break; - + case Sema::NC_TypeTemplate: case Sema::NC_FunctionTemplate: { ConsumeToken(); // the identifier UnqualifiedId Id; Id.setIdentifier(Name, NameLoc); if (AnnotateTemplateIdToken( - TemplateTy::make(Classification.getTemplateName()), + TemplateTy::make(Classification.getTemplateName()), Classification.getTemplateNameKind(), SS, Id, SourceLocation(), /*AllowTypeAnnotation=*/false)) { @@ -172,10 +177,10 @@ Retry: SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); - return StmtError(); + return StmtError(); } - - // If the next token is '::', jump right into parsing a + + // If the next token is '::', jump right into parsing a // nested-name-specifier. We don't want to leave the template-id // hanging. if (NextToken().is(tok::coloncolon) && TryAnnotateCXXScopeToken(false)){ @@ -184,22 +189,22 @@ Retry: SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true); if (Tok.is(tok::semi)) ConsumeToken(); - return StmtError(); + return StmtError(); } - + // We've annotated a template-id, so try again now. goto Retry; } - + case Sema::NC_NestedNameSpecifier: // FIXME: Implement this! break; } } - + // Fall through } - + default: { if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; @@ -224,10 +229,8 @@ Retry: case tok::l_brace: // C99 6.8.2: compound-statement return ParseCompoundStatement(attrs); case tok::semi: { // C99 6.8.3p3: expression[opt] ';' - SourceLocation LeadingEmptyMacroLoc; - if (Tok.hasLeadingEmptyMacro()) - LeadingEmptyMacroLoc = PP.getLastEmptyMacroExpansionLoc(); - return Actions.ActOnNullStmt(ConsumeToken(), LeadingEmptyMacroLoc); + bool HasLeadingEmptyMacro = Tok.hasLeadingEmptyMacro(); + return Actions.ActOnNullStmt(ConsumeToken(), HasLeadingEmptyMacro); } case tok::kw_if: // C99 6.8.4.1: if-statement @@ -297,7 +300,7 @@ Retry: StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { // If a case keyword is missing, this is where it should be inserted. Token OldToken = Tok; - + // FIXME: Use the attributes // expression[opt] ';' ExprResult Expr(ParseExpression()); @@ -310,18 +313,18 @@ StmtResult Parser::ParseExprStatement(ParsedAttributes &Attrs) { ConsumeToken(); return StmtError(); } - + if (Tok.is(tok::colon) && getCurScope()->isSwitchScope() && Actions.CheckCaseExpression(Expr.get())) { // If a constant expression is followed by a colon inside a switch block, // suggest a missing case keyword. Diag(OldToken, diag::err_expected_case_before_expression) << FixItHint::CreateInsertion(OldToken.getLocation(), "case "); - + // Recover parsing as a case statement. return ParseCaseStatement(Attrs, /*MissingCase=*/true, Expr); } - + // Otherwise, eat the semicolon. ExpectAndConsumeSemi(diag::err_expected_semi_after_expr); return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr.get())); @@ -458,12 +461,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributes &attrs) { // Broken substmt shouldn't prevent the label from being added to the AST. if (SubStmt.isInvalid()) SubStmt = Actions.ActOnNullStmt(ColonLoc); - + LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); if (AttributeList *Attrs = attrs.getList()) Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); - + return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, SubStmt.get()); } @@ -499,7 +502,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which // gets updated each time a new case is parsed, and whose body is unset so // far. When parsing 'case 4', this is the 'case 3' node. - StmtTy *DeepestParsedCaseStmt = 0; + Stmt *DeepestParsedCaseStmt = 0; // While we have case statements, eat and stack them. SourceLocation ColonLoc; @@ -509,14 +512,15 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(getCurScope()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } - + /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'. /// Disable this form of error recovery while we're parsing the case /// expression. ColonProtectionRAIIObject ColonProtection(*this); - + ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); MissingCase = false; if (LHS.isInvalid()) { @@ -537,7 +541,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, return StmtError(); } } - + ColonProtection.restore(); if (Tok.is(tok::colon)) { @@ -554,7 +558,7 @@ StmtResult Parser::ParseCaseStatement(ParsedAttributes &attrs, bool MissingCase, << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } - + StmtResult Case = Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc, RHS.get(), ColonLoc); @@ -631,7 +635,7 @@ StmtResult Parser::ParseDefaultStatement(ParsedAttributes &attrs) { << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } - + // Diagnose the common error "switch (X) {... default: }", which is not valid. if (Tok.is(tok::r_brace)) { SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); @@ -704,8 +708,9 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Tok.getLocation(), "in compound statement ('{}')"); InMessageExpressionRAIIObject InMessage(*this, false); - - SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'. + BalancedDelimiterTracker T(*this, tok::l_brace); + if (T.consumeOpen()) + return StmtError(); StmtVector Stmts(Actions); @@ -714,40 +719,40 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { while (Tok.is(tok::kw___label__)) { SourceLocation LabelLoc = ConsumeToken(); Diag(LabelLoc, diag::ext_gnu_local_label); - - llvm::SmallVector<Decl *, 8> DeclsInGroup; + + SmallVector<Decl *, 8> DeclsInGroup; while (1) { if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); break; } - + IdentifierInfo *II = Tok.getIdentifierInfo(); SourceLocation IdLoc = ConsumeToken(); DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); - + if (!Tok.is(tok::comma)) break; ConsumeToken(); } - + DeclSpec DS(AttrFactory); DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup.data(), DeclsInGroup.size()); StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); - + ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); if (R.isUsable()) Stmts.push_back(R.release()); } - + while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; } - if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || + if (getLang().MicrosoftExt && (Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { ParseMicrosoftIfExistsStatement(Stmts); continue; @@ -803,13 +808,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { // 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(LBraceLoc, diag::note_matching) << "{"; + Diag(T.getOpenLocation(), diag::note_matching) << "{"; return StmtError(); } - SourceLocation RBraceLoc = ConsumeBrace(); - return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts), - isStmtExpr); + if (T.consumeClose()) + return StmtError(); + + return Actions.ActOnCompoundStmt(T.getOpenLocation(), T.getCloseLocation(), + move_arg(Stmts), isStmtExpr); } /// ParseParenExprOrCondition: @@ -827,13 +834,15 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, Decl *&DeclResult, SourceLocation Loc, bool ConvertToBoolean) { - SourceLocation LParenLoc = ConsumeParen(); - if (getLang().CPlusPlus) + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + + if (getLang().CPlusPlus) ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { ExprResult = ParseExpression(); DeclResult = 0; - + // If required, convert to a boolean value. if (!ExprResult.isInvalid() && ConvertToBoolean) ExprResult @@ -852,7 +861,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, } // Otherwise the condition is valid or the rparen is present. - MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); return false; } @@ -950,9 +959,13 @@ StmtResult Parser::ParseIfStatement(ParsedAttributes &attrs) { C99orCXX && Tok.isNot(tok::l_brace)); ElseStmt = ParseStatement(); - + // Pop the 'else' scope if needed. InnerScope.Exit(); + } else if (Tok.is(tok::code_completion)) { + Actions.CodeCompleteAfterIf(getCurScope()); + cutOffParsing(); + return StmtError(); } IfScope.Exit(); @@ -1027,7 +1040,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { = Actions.ActOnStartOfSwitchStmt(SwitchLoc, Cond.get(), CondVar); if (Switch.isInvalid()) { - // Skip the switch body. + // Skip the switch body. // FIXME: This is not optimal recovery, but parsing the body is more // dangerous due to the presence of case and default statements, which // will have no place to connect back with the switch. @@ -1038,7 +1051,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { SkipUntil(tok::semi); return move(Switch); } - + // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this // if the body isn't a compound statement to avoid push/pop in common cases. @@ -1063,7 +1076,7 @@ StmtResult Parser::ParseSwitchStatement(ParsedAttributes &attrs) { if (Body.isInvalid()) // FIXME: Remove the case statement list from the Switch statement. Body = Actions.ActOnNullStmt(Tok.getLocation()); - + return Actions.ActOnFinishSwitchStmt(SwitchLoc, Switch.get(), Body.get()); } @@ -1196,16 +1209,17 @@ StmtResult Parser::ParseDoStatement(ParsedAttributes &attrs) { } // Parse the parenthesized condition. - SourceLocation LPLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult Cond = ParseExpression(); - SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc); + T.consumeClose(); DoScope.Exit(); if (Cond.isInvalid() || Body.isInvalid()) return StmtError(); - return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, LPLoc, - Cond.get(), RPLoc); + return Actions.ActOnDoStmt(DoLoc, Body.get(), WhileLoc, T.getOpenLocation(), + Cond.get(), T.getCloseLocation()); } /// ParseForStatement @@ -1265,7 +1279,9 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ParseScope ForScope(this, ScopeFlags); - SourceLocation LParenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); + ExprResult Value; bool ForEach = false, ForRange = false; @@ -1276,14 +1292,15 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); Decl *SecondVar = 0; - + if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteOrdinaryName(getCurScope(), + Actions.CodeCompleteOrdinaryName(getCurScope(), C99orCXXorObjC? Sema::PCC_ForInit : Sema::PCC_Expression); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } - + // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // for (; // no first part, eat the ';'. @@ -1302,13 +1319,16 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts(Actions); - DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, + DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, DeclEnd, attrs, false, MightBeForRangeStmt ? &ForRangeInit : 0); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { + if (!getLang().CPlusPlus0x) + Diag(ForRangeInit.ColonLoc, diag::ext_for_range); + ForRange = true; } else if (Tok.is(tok::semi)) { // for (int x = 4; ConsumeToken(); @@ -1316,10 +1336,11 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { Actions.ActOnForEachDeclStmt(DG); // ObjC: for (id x in expr) ConsumeToken(); // consume 'in' - + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCForCollection(getCurScope(), DG); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } Collection = ParseExpression(); } else { @@ -1342,10 +1363,11 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { ConsumeToken(); } else if (ForEach) { ConsumeToken(); // consume 'in' - + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCForCollection(getCurScope(), DeclGroupPtrTy()); - ConsumeCodeCompletionToken(); + cutOffParsing(); + return StmtError(); } Collection = ParseExpression(); } else { @@ -1373,7 +1395,7 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { else { Second = ParseExpression(); if (!Second.isInvalid()) - Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, + Second = Actions.ActOnBooleanCondition(getCurScope(), ForLoc, Second.get()); } SecondPartIsInvalid = Second.isInvalid(); @@ -1399,18 +1421,27 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { } } // Match the ')'. - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); + T.consumeClose(); // We need to perform most of the semantic analysis for a C++0x for-range // statememt before parsing the body, in order to be able to deduce the type // of an auto-typed loop variable. StmtResult ForRangeStmt; - if (ForRange) - ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, LParenLoc, + if (ForRange) { + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), - RParenLoc); + T.getCloseLocation()); + + + // Similarly, we need to do the semantic analysis for a for-range + // statement immediately in order to close over temporaries correctly. + } else if (ForEach) { + if (!Collection.isInvalid()) + Collection = + Actions.ActOnObjCForCollectionOperand(ForLoc, Collection.take()); + } // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1439,18 +1470,18 @@ StmtResult Parser::ParseForStatement(ParsedAttributes &attrs) { return StmtError(); if (ForEach) - // FIXME: It isn't clear how to communicate the late destruction of - // C++ temporaries used to create the collection. - return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc, - FirstPart.take(), - Collection.take(), RParenLoc, - Body.take()); + return Actions.ActOnObjCForCollectionStmt(ForLoc, T.getOpenLocation(), + FirstPart.take(), + Collection.take(), + T.getCloseLocation(), + Body.take()); if (ForRange) return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); - return Actions.ActOnForStmt(ForLoc, LParenLoc, FirstPart.take(), SecondPart, - SecondVar, ThirdPart, RParenLoc, Body.take()); + return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), + SecondPart, SecondVar, ThirdPart, + T.getCloseLocation(), Body.take()); } /// ParseGotoStatement @@ -1529,11 +1560,10 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { if (Tok.isNot(tok::semi)) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteReturn(getCurScope()); - ConsumeCodeCompletionToken(); - SkipUntil(tok::semi, false, true); + cutOffParsing(); 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. @@ -1552,30 +1582,105 @@ StmtResult Parser::ParseReturnStatement(ParsedAttributes &attrs) { return Actions.ActOnReturnStmt(ReturnLoc, R.take()); } -/// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this -/// routine is called to skip/ignore tokens that comprise the MS asm statement. -StmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) { - SourceLocation EndLoc; - if (Tok.is(tok::l_brace)) { - unsigned short savedBraceCount = BraceCount; - do { - EndLoc = Tok.getLocation(); - ConsumeAnyToken(); - } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof)); - } else { - // From the MS website: If used without braces, the __asm keyword means - // that the rest of the line is an assembly-language statement. - SourceManager &SrcMgr = PP.getSourceManager(); +/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, +/// this routine is called to collect the tokens for an MS asm statement. +StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { + SourceManager &SrcMgr = PP.getSourceManager(); + SourceLocation EndLoc = AsmLoc; + do { + bool InBraces = false; + unsigned short savedBraceCount = 0; + bool InAsmComment = false; + FileID FID; + unsigned LineNo = 0; + unsigned NumTokensRead = 0; + SourceLocation LBraceLoc; + + if (Tok.is(tok::l_brace)) { + // Braced inline asm: consume the opening brace. + InBraces = true; + savedBraceCount = BraceCount; + EndLoc = LBraceLoc = ConsumeBrace(); + ++NumTokensRead; + } else { + // Single-line inline asm; compute which line it is on. + std::pair<FileID, unsigned> ExpAsmLoc = + SrcMgr.getDecomposedExpansionLoc(EndLoc); + FID = ExpAsmLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); + } + SourceLocation TokLoc = Tok.getLocation(); - unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc); do { + // If we hit EOF, we're done, period. + if (Tok.is(tok::eof)) + break; + // When we consume the closing brace, we're done. + if (InBraces && BraceCount == savedBraceCount) + break; + + if (!InAsmComment && Tok.is(tok::semi)) { + // A semicolon in an asm is the start of a comment. + InAsmComment = true; + if (InBraces) { + // Compute which line the comment is on. + std::pair<FileID, unsigned> ExpSemiLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + FID = ExpSemiLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); + } + } else if (!InBraces || InAsmComment) { + // If end-of-line is significant, check whether this token is on a + // new line. + std::pair<FileID, unsigned> ExpLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + if (ExpLoc.first != FID || + SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { + // If this is a single-line __asm, we're done. + if (!InBraces) + break; + // We're no longer in a comment. + InAsmComment = false; + } else if (!InAsmComment && Tok.is(tok::r_brace)) { + // Single-line asm always ends when a closing brace is seen. + // FIXME: This is compatible with Apple gcc's -fasm-blocks; what + // does MSVC do here? + break; + } + } + + // Consume the next token; make sure we don't modify the brace count etc. + // if we are in a comment. EndLoc = TokLoc; - ConsumeAnyToken(); + if (InAsmComment) + PP.Lex(Tok); + else + ConsumeAnyToken(); TokLoc = Tok.getLocation(); - } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) && - Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) && - Tok.isNot(tok::eof)); - } + ++NumTokensRead; + } while (1); + + if (InBraces && BraceCount != savedBraceCount) { + // __asm without closing brace (this can happen at EOF). + Diag(Tok, diag::err_expected_rbrace); + Diag(LBraceLoc, diag::note_matching) << "{"; + return StmtError(); + } else if (NumTokensRead == 0) { + // Empty __asm. + Diag(Tok, diag::err_expected_lbrace); + return StmtError(); + } + // Multiple adjacent asm's form together into a single asm statement + // in the AST. + if (!Tok.is(tok::kw_asm)) + break; + EndLoc = ConsumeToken(); + } while (1); + // FIXME: Need to actually grab the data and pass it on to Sema. Ideally, + // what Sema wants is a string of the entire inline asm, with one instruction + // per line and all the __asm keywords stripped out, and a way of mapping + // from any character of that string to its location in the original source + // code. I'm not entirely sure how to go about that, though. Token t; t.setKind(tok::string_literal); t.setLiteralData("\"/*FIXME: not done*/\""); @@ -1611,20 +1716,24 @@ StmtResult Parser::FuzzyParseMicrosoftAsmStatement(SourceLocation AsmLoc) { /// asm-clobbers ',' asm-string-literal /// /// [MS] ms-asm-statement: -/// '__asm' assembly-instruction ';'[opt] -/// '__asm' '{' assembly-instruction-list '}' ';'[opt] +/// ms-asm-block +/// ms-asm-block ms-asm-statement +/// +/// [MS] ms-asm-block: +/// '__asm' ms-asm-line '\n' +/// '__asm' '{' ms-asm-instruction-block[opt] '}' ';'[opt] /// -/// [MS] assembly-instruction-list: -/// assembly-instruction ';'[opt] -/// assembly-instruction-list ';' assembly-instruction ';'[opt] +/// [MS] ms-asm-instruction-block +/// ms-asm-line +/// ms-asm-line '\n' ms-asm-instruction-block /// StmtResult Parser::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { + if (getLang().MicrosoftExt && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { msAsm = true; - return FuzzyParseMicrosoftAsmStatement(AsmLoc); + return ParseMicrosoftAsmStatement(AsmLoc); } DeclSpec DS(AttrFactory); SourceLocation Loc = Tok.getLocation(); @@ -1643,25 +1752,26 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { SkipUntil(tok::r_paren); return StmtError(); } - Loc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult AsmString(ParseAsmStringLiteral()); if (AsmString.isInvalid()) return StmtError(); - llvm::SmallVector<IdentifierInfo *, 4> Names; + SmallVector<IdentifierInfo *, 4> Names; ExprVector Constraints(Actions); ExprVector Exprs(Actions); ExprVector Clobbers(Actions); if (Tok.is(tok::r_paren)) { // We have a simple asm expression like 'asm("foo")'. - SourceLocation RParenLoc = ConsumeParen(); + T.consumeClose(); return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, - /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, + /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, move_arg(Constraints), move_arg(Exprs), AsmString.take(), move_arg(Clobbers), - RParenLoc); + T.getCloseLocation()); } // Parse Outputs, if present. @@ -1670,12 +1780,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { // In C++ mode, parse "::" like ": :". AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); - + if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); } - + unsigned NumOutputs = Names.size(); // Parse Inputs, if present. @@ -1688,7 +1798,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { AteExtraColon = Tok.is(tok::coloncolon); ConsumeToken(); } - + if (!AteExtraColon && ParseAsmOperandsOpt(Names, Constraints, Exprs)) return StmtError(); @@ -1721,12 +1831,12 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { } } - SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc); + T.consumeClose(); return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile, NumOutputs, NumInputs, Names.data(), move_arg(Constraints), move_arg(Exprs), AsmString.take(), move_arg(Clobbers), - RParenLoc); + T.getCloseLocation()); } /// ParseAsmOperands - Parse the asm-operands production as used by @@ -1742,9 +1852,9 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) { /// // // FIXME: Avoid unnecessary std::string trashing. -bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, - llvm::SmallVectorImpl<ExprTy *> &Constraints, - llvm::SmallVectorImpl<ExprTy *> &Exprs) { +bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, + SmallVectorImpl<Expr *> &Constraints, + SmallVectorImpl<Expr *> &Exprs) { // 'asm-operands' isn't present? if (!isTokenStringLiteral() && Tok.isNot(tok::l_square)) return false; @@ -1752,7 +1862,8 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, while (1) { // Read the [id] if present. if (Tok.is(tok::l_square)) { - SourceLocation Loc = ConsumeBracket(); + BalancedDelimiterTracker T(*this, tok::l_square); + T.consumeOpen(); if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_ident); @@ -1764,7 +1875,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, ConsumeToken(); Names.push_back(II); - MatchRHSPunctuation(tok::r_square, Loc); + T.consumeClose(); } else Names.push_back(0); @@ -1782,9 +1893,10 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names, } // Read the parenthesized expression. - SourceLocation OpenLoc = ConsumeParen(); + BalancedDelimiterTracker T(*this, tok::l_paren); + T.consumeOpen(); ExprResult Res(ParseExpression()); - MatchRHSPunctuation(tok::r_paren, OpenLoc); + T.consumeClose(); if (Res.isInvalid()) { SkipUntil(tok::r_paren); return true; @@ -1808,7 +1920,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { return Actions.ActOnFinishFunctionBody(Decl, 0); } } - + PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); @@ -1841,6 +1953,8 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { // Constructor initializer list? if (Tok.is(tok::colon)) ParseConstructorInitializer(Decl); + else + Actions.ActOnDefaultCtorInitializers(Decl); if (PP.isCodeCompletionEnabled()) { if (trySkippingFunctionBodyForCodeCompletion()) { @@ -1977,8 +2091,8 @@ StmtResult Parser::ParseCXXCatchBlock() { SourceLocation CatchLoc = ConsumeToken(); - SourceLocation LParenLoc = Tok.getLocation(); - if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen)) + BalancedDelimiterTracker T(*this, tok::l_paren); + if (T.expectAndConsume(diag::err_expected_lparen)) return StmtError(); // C++ 3.3.2p3: @@ -1999,7 +2113,8 @@ StmtResult Parser::ParseCXXCatchBlock() { } else ConsumeToken(); - if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid()) + T.consumeClose(); + if (T.getCloseLocation().isInvalid()) return StmtError(); if (Tok.isNot(tok::l_brace)) @@ -2018,7 +2133,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { bool Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - + if (Tok.isNot(tok::l_brace)) { Diag(Tok, diag::err_expected_lbrace); return; |