diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 1150 |
1 files changed, 290 insertions, 860 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index d1f2138..ec0ca6b 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp @@ -15,25 +15,14 @@ #include "clang/Parse/Parser.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" +#include "clang/Basic/Attributes.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/LoopHint.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCParser/MCAsmParser.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCStreamer.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCTargetAsmParser.h" -#include "llvm/Support/SourceMgr.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/TargetSelect.h" #include "llvm/ADT/SmallString.h" using namespace clang; @@ -112,7 +101,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement, ParenBraceBracketBalancer BalancerRAIIObj(*this); ParsedAttributesWithRange Attrs(AttrFactory); - MaybeParseCXX11Attributes(Attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(Attrs, nullptr, /*MightBeObjCMessageSend*/ true); StmtResult Res = ParseStatementOrDeclarationAfterAttributes(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -142,7 +131,7 @@ public: WantCXXNamedCasts = false; } - virtual bool ValidateCandidate(const TypoCorrection &candidate) { + bool ValidateCandidate(const TypoCorrection &candidate) override { if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>()) return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD); if (NextToken.is(tok::equal)) @@ -162,7 +151,7 @@ StmtResult Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts, bool OnlyStatement, SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs) { - const char *SemiError = 0; + const char *SemiError = nullptr; StmtResult Res; // Cases in this switch statement should fall through if the parser expects @@ -284,6 +273,14 @@ Retry: break; } + case tok::kw___if_exists: + case tok::kw___if_not_exists: + ProhibitAttributes(Attrs); + ParseMicrosoftIfExistsStatement(Stmts); + // An __if_exists block is like a compound statement, but it doesn't create + // a new scope. + return StmtEmpty(); + case tok::kw_try: // C++ 15: try-block return ParseCXXTryBlock(); @@ -291,6 +288,11 @@ Retry: ProhibitAttributes(Attrs); // TODO: is it correct? return ParseSEHTryBlock(); + case tok::kw___leave: + Res = ParseSEHLeaveStatement(); + SemiError = "__leave"; + break; + case tok::annot_pragma_vis: ProhibitAttributes(Attrs); HandlePragmaVisibility(); @@ -343,14 +345,25 @@ Retry: case tok::annot_pragma_openmp: ProhibitAttributes(Attrs); - return ParseOpenMPDeclarativeOrExecutableDirective(); + return ParseOpenMPDeclarativeOrExecutableDirective(!OnlyStatement); + + case tok::annot_pragma_ms_pointers_to_members: + ProhibitAttributes(Attrs); + HandlePragmaMSPointersToMembers(); + return StmtEmpty(); + case tok::annot_pragma_ms_pragma: + ProhibitAttributes(Attrs); + HandlePragmaMSPragma(); + return StmtEmpty(); + + case tok::annot_pragma_loop_hint: + ProhibitAttributes(Attrs); + return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); } // If we reached this code, the statement must end in a semicolon. - if (Tok.is(tok::semi)) { - ConsumeToken(); - } else if (!Res.isInvalid()) { + if (!TryConsumeToken(tok::semi) && !Res.isInvalid()) { // If the result was valid, then we do want to diagnose this. Use // ExpectAndConsume to emit the diagnostic, even though we know it won't // succeed. @@ -411,10 +424,27 @@ StmtResult Parser::ParseSEHTryBlock() { /// seh-finally-block /// StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { - if(Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok,diag::err_expected_lbrace)); + if (Tok.isNot(tok::l_brace)) + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); + + int SEHTryIndex, SEHTryParentIndex; + StmtResult TryBlock; + { + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); + + // Enter a scope to hold everything within the compound stmt. Compound + // statements can always hold declarations. + ParseScope CompoundScope(this, Scope::DeclScope | Scope::SEHTryScope); + SEHTryIndex = getCurScope()->getSEHTryIndex(); + SEHTryParentIndex = getCurScope()->getSEHTryParentIndex(); + + // Parse the statements in the body. + TryBlock = ParseCompoundStatementBody(); + } + + //StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, + // Scope::DeclScope | Scope::SEHTryScope)); - StmtResult TryBlock(ParseCompoundStatement()); if(TryBlock.isInvalid()) return TryBlock; @@ -435,8 +465,10 @@ StmtResult Parser::ParseSEHTryBlockCommon(SourceLocation TryLoc) { return Actions.ActOnSEHTryBlock(false /* IsCXXTry */, TryLoc, - TryBlock.take(), - Handler.take()); + TryBlock.get(), + Handler.get(), + SEHTryIndex, + SEHTryParentIndex); } /// ParseSEHExceptBlock - Handle __except @@ -449,7 +481,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { raii2(Ident___exception_code, false), raii3(Ident_GetExceptionCode, false); - if(ExpectAndConsume(tok::l_paren,diag::err_expected_lparen)) + if (ExpectAndConsume(tok::l_paren)) return StmtError(); ParseScope ExpectScope(this, Scope::DeclScope | Scope::ControlScope); @@ -470,7 +502,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if(FilterExpr.isInvalid()) return StmtError(); - if(ExpectAndConsume(tok::r_paren,diag::err_expected_rparen)) + if (ExpectAndConsume(tok::r_paren)) return StmtError(); StmtResult Block(ParseCompoundStatement()); @@ -478,7 +510,7 @@ StmtResult Parser::ParseSEHExceptBlock(SourceLocation ExceptLoc) { if(Block.isInvalid()) return Block; - return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.take(), Block.take()); + return Actions.ActOnSEHExceptBlock(ExceptLoc, FilterExpr.get(), Block.get()); } /// ParseSEHFinallyBlock - Handle __finally @@ -495,7 +527,17 @@ StmtResult Parser::ParseSEHFinallyBlock(SourceLocation FinallyBlock) { if(Block.isInvalid()) return Block; - return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.take()); + return Actions.ActOnSEHFinallyBlock(FinallyBlock,Block.get()); +} + +/// Handle __leave +/// +/// seh-leave-statement: +/// '__leave' ';' +/// +StmtResult Parser::ParseSEHLeaveStatement() { + SourceLocation LeaveLoc = ConsumeToken(); // eat the '__leave'. + return Actions.ActOnSEHLeaveStmt(LeaveLoc, getCurScope()); } /// ParseLabeledStatement - We have an identifier and a ':' after it. @@ -538,12 +580,12 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { // can't handle GNU attributes), so only call it in the one case where // GNU attributes are allowed. SubStmt = ParseStatementOrDeclarationAfterAttributes( - Stmts, /*OnlyStmts*/ true, 0, TempAttrs); + Stmts, /*OnlyStmts*/ true, nullptr, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ProcessStmtAttributes( SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); } else { - Diag(Tok, diag::err_expected_semi_after) << "__attribute__"; + Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } } @@ -595,13 +637,14 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // 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. - Stmt *DeepestParsedCaseStmt = 0; + Stmt *DeepestParsedCaseStmt = nullptr; // While we have case statements, eat and stack them. SourceLocation ColonLoc; do { SourceLocation CaseLoc = MissingCase ? Expr.get()->getExprLoc() : ConsumeToken(); // eat the 'case'. + ColonLoc = SourceLocation(); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteCase(getCurScope()); @@ -614,41 +657,52 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { /// expression. ColonProtectionRAIIObject ColonProtection(*this); - ExprResult LHS(MissingCase ? Expr : ParseConstantExpression()); - MissingCase = false; - if (LHS.isInvalid()) { - SkipUntil(tok::colon, StopAtSemi); - return StmtError(); + ExprResult LHS; + if (!MissingCase) { + LHS = ParseConstantExpression(); + if (LHS.isInvalid()) { + // If constant-expression is parsed unsuccessfully, recover by skipping + // current case statement (moving to the colon that ends it). + if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { + TryConsumeToken(tok::colon, ColonLoc); + continue; + } + return StmtError(); + } + } else { + LHS = Expr; + MissingCase = false; } // GNU case range extension. SourceLocation DotDotDotLoc; ExprResult RHS; - if (Tok.is(tok::ellipsis)) { - Diag(Tok, diag::ext_gnu_case_range); - DotDotDotLoc = ConsumeToken(); - + if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) { + Diag(DotDotDotLoc, diag::ext_gnu_case_range); RHS = ParseConstantExpression(); if (RHS.isInvalid()) { - SkipUntil(tok::colon, StopAtSemi); + if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { + TryConsumeToken(tok::colon, ColonLoc); + continue; + } return StmtError(); } } ColonProtection.restore(); - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - - // Treat "case blah;" as a typo for "case blah:". - } else if (Tok.is(tok::semi)) { - ColonLoc = ConsumeToken(); - Diag(ColonLoc, diag::err_expected_colon_after) << "'case'" - << FixItHint::CreateReplacement(ColonLoc, ":"); + if (TryConsumeToken(tok::colon, ColonLoc)) { + } else if (TryConsumeToken(tok::semi, ColonLoc) || + TryConsumeToken(tok::coloncolon, ColonLoc)) { + // Treat "case blah;" or "case blah::" as a typo for "case blah:". + Diag(ColonLoc, diag::err_expected_after) + << "'case'" << tok::colon + << FixItHint::CreateReplacement(ColonLoc, ":"); } else { SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); - Diag(ExpectedLoc, diag::err_expected_colon_after) << "'case'" - << FixItHint::CreateInsertion(ExpectedLoc, ":"); + Diag(ExpectedLoc, diag::err_expected_after) + << "'case'" << tok::colon + << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } @@ -676,8 +730,6 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { // Handle all case statements. } while (Tok.is(tok::kw_case)); - assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!"); - // If we found a non-case statement, start by parsing it. StmtResult SubStmt; @@ -685,19 +737,23 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { SubStmt = ParseStatement(); } else { // 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) - << FixItHint::CreateInsertion(AfterColonLoc, " ;"); - SubStmt = true; + // not valid. If ColonLoc doesn't point to a valid text location, there was + // another parsing error, so avoid producing extra diagnostics. + if (ColonLoc.isValid()) { + SourceLocation AfterColonLoc = PP.getLocForEndOfToken(ColonLoc); + Diag(AfterColonLoc, diag::err_label_end_of_compound_statement) + << FixItHint::CreateInsertion(AfterColonLoc, " ;"); + } + SubStmt = StmtError(); } - // Broken sub-stmt shouldn't prevent forming the case statement properly. - if (SubStmt.isInvalid()) - SubStmt = Actions.ActOnNullStmt(SourceLocation()); - // Install the body into the most deeply-nested case. - Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + if (DeepestParsedCaseStmt) { + // Broken sub-stmt shouldn't prevent forming the case statement properly. + if (SubStmt.isInvalid()) + SubStmt = Actions.ActOnNullStmt(SourceLocation()); + Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, SubStmt.get()); + } // Return the top level parsed statement tree. return TopLevelCase; @@ -713,18 +769,17 @@ StmtResult Parser::ParseDefaultStatement() { SourceLocation DefaultLoc = ConsumeToken(); // eat the 'default'. SourceLocation ColonLoc; - if (Tok.is(tok::colon)) { - ColonLoc = ConsumeToken(); - - // Treat "default;" as a typo for "default:". - } else if (Tok.is(tok::semi)) { - ColonLoc = ConsumeToken(); - Diag(ColonLoc, diag::err_expected_colon_after) << "'default'" - << FixItHint::CreateReplacement(ColonLoc, ":"); + if (TryConsumeToken(tok::colon, ColonLoc)) { + } else if (TryConsumeToken(tok::semi, ColonLoc)) { + // Treat "default;" as a typo for "default:". + Diag(ColonLoc, diag::err_expected_after) + << "'default'" << tok::colon + << FixItHint::CreateReplacement(ColonLoc, ":"); } else { SourceLocation ExpectedLoc = PP.getLocForEndOfToken(PrevTokLocation); - Diag(ExpectedLoc, diag::err_expected_colon_after) << "'default'" - << FixItHint::CreateInsertion(ExpectedLoc, ":"); + Diag(ExpectedLoc, diag::err_expected_after) + << "'default'" << tok::colon + << FixItHint::CreateInsertion(ExpectedLoc, ":"); ColonLoc = ExpectedLoc; } @@ -767,7 +822,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// declaration /// [GNU] '__extension__' declaration /// statement -/// [OMP] openmp-directive [TODO] /// /// [GNU] label-declarations: /// [GNU] label-declaration @@ -776,10 +830,6 @@ StmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// [GNU] label-declaration: /// [GNU] '__label__' identifier-list ';' /// -/// [OMP] openmp-directive: [TODO] -/// [OMP] barrier-directive -/// [OMP] flush-directive -/// StmtResult Parser::ParseCompoundStatement(bool isStmtExpr, unsigned ScopeFlags) { assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); @@ -826,6 +876,12 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_fp_contract: HandlePragmaFPContract(); break; + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + break; + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + break; default: checkForPragmas = false; break; @@ -867,7 +923,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { SmallVector<Decl *, 8> DeclsInGroup; while (1) { if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; break; } @@ -875,9 +931,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { SourceLocation IdLoc = ConsumeToken(); DeclsInGroup.push_back(Actions.LookupOrCreateLabel(II, IdLoc, LabelLoc)); - if (!Tok.is(tok::comma)) + if (!TryConsumeToken(tok::comma)) break; - ConsumeToken(); } DeclSpec DS(AttrFactory); @@ -887,21 +942,15 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ExpectAndConsumeSemi(diag::err_expected_semi_declaration); if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; } - if (getLangOpts().MicrosoftExt && (Tok.is(tok::kw___if_exists) || - Tok.is(tok::kw___if_not_exists))) { - ParseMicrosoftIfExistsStatement(Stmts); - continue; - } - StmtResult R; if (Tok.isNot(tok::kw___extension__)) { R = ParseStatementOrDeclaration(Stmts, false); @@ -915,7 +964,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ConsumeToken(); ParsedAttributesWithRange attrs(AttrFactory); - MaybeParseCXX11Attributes(attrs, 0, /*MightBeObjCMessageSend*/ true); + MaybeParseCXX11Attributes(attrs, nullptr, + /*MightBeObjCMessageSend*/ true); // If this is the start of a declaration, parse it as such. if (isDeclarationStatement()) { @@ -946,7 +996,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { } if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } SourceLocation CloseLoc = Tok.getLocation(); @@ -983,7 +1033,7 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, ParseCXXCondition(ExprResult, DeclResult, Loc, ConvertToBoolean); else { ExprResult = ParseExpression(); - DeclResult = 0; + DeclResult = nullptr; // If required, convert to a boolean value. if (!ExprResult.isInvalid() && ConvertToBoolean) @@ -1053,7 +1103,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // Parse the condition. ExprResult CondExp; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); @@ -1077,8 +1127,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // would have to notify ParseStatement not to create a new scope. It's // simpler to let it create a new scope. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the 'then' stmt. SourceLocation ThenStmtLoc = Tok.getLocation(); @@ -1110,8 +1159,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // The substatement in a selection-statement (each substatement, in the else // form of the if statement) implicitly defines a local scope. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); ElseStmt = ParseStatement(); @@ -1131,8 +1179,8 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { // make turn the invalid one into a null stmt to avoid dropping the other // part. If both are invalid, return error. if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) || - (ThenStmt.isInvalid() && ElseStmt.get() == 0) || - (ThenStmt.get() == 0 && ElseStmt.isInvalid())) { + (ThenStmt.isInvalid() && ElseStmt.get() == nullptr) || + (ThenStmt.get() == nullptr && ElseStmt.isInvalid())) { // Both invalid, or one is invalid and other is non-present: return error. return StmtError(); } @@ -1175,14 +1223,14 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // while, for, and switch statements are local to the if, while, for, or // switch statement (including the controlled statement). // - unsigned ScopeFlags = Scope::BreakScope | Scope::SwitchScope; + unsigned ScopeFlags = Scope::SwitchScope; if (C99orCXX) ScopeFlags |= Scope::DeclScope | Scope::ControlScope; ParseScope SwitchScope(this, ScopeFlags); // Parse the condition. ExprResult Cond; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(Cond, CondVar, SwitchLoc, false)) return StmtError(); @@ -1213,8 +1261,13 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + getCurScope()->AddFlags(Scope::BreakScope); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); + + // We have incremented the mangling number for the SwitchScope and the + // InnerScope, which is one too many. + if (C99orCXX) + getCurScope()->decrementMSLocalManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1223,15 +1276,6 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) { InnerScope.Exit(); SwitchScope.Exit(); - if (Body.isInvalid()) { - // FIXME: Remove the case statement list from the Switch statement. - - // 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()); } @@ -1274,13 +1318,13 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { // Parse the condition. ExprResult Cond; - Decl *CondVar = 0; + Decl *CondVar = nullptr; if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the while 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. // @@ -1291,8 +1335,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for the // condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXX && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1325,7 +1368,7 @@ StmtResult Parser::ParseDoStatement() { ParseScope DoScope(this, ScopeFlags); - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the do 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. // @@ -1333,9 +1376,8 @@ StmtResult Parser::ParseDoStatement() { // The substatement in an iteration-statement implicitly defines a local scope // which is entered and exited each time through the loop. // - ParseScope InnerScope(this, Scope::DeclScope, - (getLangOpts().C99 || getLangOpts().CPlusPlus) && - Tok.isNot(tok::l_brace)); + bool C99orCXX = getLangOpts().C99 || getLangOpts().CPlusPlus; + ParseScope InnerScope(this, Scope::DeclScope, C99orCXX, Tok.is(tok::l_brace)); // Read the body statement. StmtResult Body(ParseStatement()); @@ -1346,7 +1388,7 @@ StmtResult Parser::ParseDoStatement() { if (Tok.isNot(tok::kw_while)) { if (!Body.isInvalid()) { Diag(Tok, diag::err_expected_while); - Diag(DoLoc, diag::note_matching) << "do"; + Diag(DoLoc, diag::note_matching) << "'do'"; SkipUntil(tok::semi, StopBeforeMatch); } return StmtError(); @@ -1377,6 +1419,25 @@ StmtResult Parser::ParseDoStatement() { Cond.get(), T.getCloseLocation()); } +bool Parser::isForRangeIdentifier() { + assert(Tok.is(tok::identifier)); + + const Token &Next = NextToken(); + if (Next.is(tok::colon)) + return true; + + if (Next.is(tok::l_square) || Next.is(tok::kw_alignas)) { + TentativeParsingAction PA(*this); + ConsumeToken(); + SkipCXX11Attributes(); + bool Result = Tok.is(tok::colon); + PA.Revert(); + return Result; + } + + return false; +} + /// ParseForStatement /// for-statement: [C99 6.8.5.3] /// 'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement @@ -1424,12 +1485,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Names declared in the for-init-statement are in the same declarative-region // as those declared in the condition. // - unsigned ScopeFlags; + unsigned ScopeFlags = 0; if (C99orCXXorObjC) - ScopeFlags = Scope::BreakScope | Scope::ContinueScope | - Scope::DeclScope | Scope::ControlScope; - else - ScopeFlags = Scope::BreakScope | Scope::ContinueScope; + ScopeFlags = Scope::DeclScope | Scope::ControlScope; ParseScope ForScope(this, ScopeFlags); @@ -1445,7 +1503,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Collection; ForRangeInit ForRangeInit; FullExprArg ThirdPart(Actions); - Decl *SecondVar = 0; + Decl *SecondVar = nullptr; if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), @@ -1463,6 +1521,29 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ProhibitAttributes(attrs); // no first part, eat the ';'. ConsumeToken(); + } else if (getLangOpts().CPlusPlus && Tok.is(tok::identifier) && + isForRangeIdentifier()) { + ProhibitAttributes(attrs); + IdentifierInfo *Name = Tok.getIdentifierInfo(); + SourceLocation Loc = ConsumeToken(); + MaybeParseCXX11Attributes(attrs); + + ForRangeInit.ColonLoc = ConsumeToken(); + if (Tok.is(tok::l_brace)) + ForRangeInit.RangeExpr = ParseBraceInitializer(); + else + ForRangeInit.RangeExpr = ParseExpression(); + + Diag(Loc, getLangOpts().CPlusPlus1z + ? diag::warn_cxx1y_compat_for_range_identifier + : diag::ext_for_range_identifier) + << ((getLangOpts().CPlusPlus11 && !getLangOpts().CPlusPlus1z) + ? FixItHint::CreateInsertion(Loc, "auto &&") + : FixItHint()); + + FirstPart = Actions.ActOnCXXForRangeIdentifier(getCurScope(), Loc, Name, + attrs, attrs.Range.getEnd()); + ForRange = true; } else if (isForInitDeclaration()) { // for (int X = 4; // Parse declaration, which eats the ';'. if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? @@ -1474,12 +1555,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; StmtVector Stmts; - DeclGroupPtrTy DG = ParseSimpleDeclaration(Stmts, Declarator::ForContext, - DeclEnd, attrs, false, - MightBeForRangeStmt ? - &ForRangeInit : 0); + DeclGroupPtrTy DG = ParseSimpleDeclaration( + Stmts, Declarator::ForContext, DeclEnd, attrs, false, + MightBeForRangeStmt ? &ForRangeInit : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); - if (ForRangeInit.ParsedForRangeDecl()) { Diag(ForRangeInit.ColonLoc, getLangOpts().CPlusPlus11 ? diag::warn_cxx98_compat_for_range : diag::ext_for_range); @@ -1544,6 +1623,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { } } } + + // Parse the second part of the for specifier. + getCurScope()->AddFlags(Scope::BreakScope | Scope::ContinueScope); if (!ForEach && !ForRange) { assert(!SecondPart.get() && "Shouldn't have a second expression yet."); // Parse the second part of the for specifier. @@ -1582,7 +1664,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { ExprResult Third = ParseExpression(); // FIXME: The C++11 standard doesn't actually say that this is a // discarded-value expression, but it clearly should be. - ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.take()); + ThirdPart = Actions.MakeFullDiscardedValueExpr(Third.get()); } } // Match the ')'. @@ -1595,7 +1677,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForEachStmt; if (ForRange) { - ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.take(), + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), T.getCloseLocation(), @@ -1606,12 +1688,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // statement immediately in order to close over temporaries correctly. } else if (ForEach) { ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc, - FirstPart.take(), - Collection.take(), + FirstPart.get(), + Collection.get(), T.getCloseLocation()); } - // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if + // C99 6.8.5p5 - In C99, the body of the for 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. // @@ -1622,8 +1704,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // See comments in ParseIfStatement for why we create a scope for // for-init-statement/condition and a new scope for substatement in C++. // - ParseScope InnerScope(this, Scope::DeclScope, - C99orCXXorObjC && Tok.isNot(tok::l_brace)); + ParseScope InnerScope(this, Scope::DeclScope, C99orCXXorObjC, + Tok.is(tok::l_brace)); + + // The body of the for loop has the same local mangling number as the + // for-init-statement. + // It will only be incremented if the body contains other things that would + // normally increment the mangling number (like a compound statement). + if (C99orCXXorObjC) + getCurScope()->decrementMSLocalManglingNumber(); // Read the body statement. StmtResult Body(ParseStatement(TrailingElseLoc)); @@ -1638,15 +1727,15 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); if (ForEach) - return Actions.FinishObjCForCollectionStmt(ForEachStmt.take(), - Body.take()); + return Actions.FinishObjCForCollectionStmt(ForEachStmt.get(), + Body.get()); if (ForRange) - return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); + return Actions.FinishCXXForRangeStmt(ForRangeStmt.get(), Body.get()); - return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), + return Actions.ActOnForStmt(ForLoc, T.getOpenLocation(), FirstPart.get(), SecondPart, SecondVar, ThirdPart, - T.getCloseLocation(), Body.take()); + T.getCloseLocation(), Body.get()); } /// ParseGotoStatement @@ -1675,9 +1764,9 @@ StmtResult Parser::ParseGotoStatement() { SkipUntil(tok::semi, StopBeforeMatch); return StmtError(); } - Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take()); + Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.get()); } else { - Diag(Tok, diag::err_expected_ident); + Diag(Tok, diag::err_expected) << tok::identifier; return StmtError(); } @@ -1730,713 +1819,40 @@ StmtResult Parser::ParseReturnStatement() { << R.get()->getSourceRange(); } else R = ParseExpression(); - if (R.isInvalid()) { // Skip to the semicolon, but don't consume it. - SkipUntil(tok::semi, StopBeforeMatch); + if (R.isInvalid()) { + SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); return StmtError(); } } - return Actions.ActOnReturnStmt(ReturnLoc, R.take()); -} - -namespace { - class ClangAsmParserCallback : public llvm::MCAsmParserSemaCallback { - Parser &TheParser; - SourceLocation AsmLoc; - StringRef AsmString; - - /// The tokens we streamed into AsmString and handed off to MC. - ArrayRef<Token> AsmToks; - - /// The offset of each token in AsmToks within AsmString. - ArrayRef<unsigned> AsmTokOffsets; - - public: - ClangAsmParserCallback(Parser &P, SourceLocation Loc, - StringRef AsmString, - ArrayRef<Token> Toks, - ArrayRef<unsigned> Offsets) - : TheParser(P), AsmLoc(Loc), AsmString(AsmString), - AsmToks(Toks), AsmTokOffsets(Offsets) { - assert(AsmToks.size() == AsmTokOffsets.size()); - } - - void *LookupInlineAsmIdentifier(StringRef &LineBuf, - InlineAsmIdentifierInfo &Info, - bool IsUnevaluatedContext) { - // Collect the desired tokens. - SmallVector<Token, 16> LineToks; - const Token *FirstOrigToken = 0; - findTokensForString(LineBuf, LineToks, FirstOrigToken); - - unsigned NumConsumedToks; - ExprResult Result = - TheParser.ParseMSAsmIdentifier(LineToks, NumConsumedToks, &Info, - IsUnevaluatedContext); - - // If we consumed the entire line, tell MC that. - // Also do this if we consumed nothing as a way of reporting failure. - if (NumConsumedToks == 0 || NumConsumedToks == LineToks.size()) { - // By not modifying LineBuf, we're implicitly consuming it all. - - // Otherwise, consume up to the original tokens. - } else { - assert(FirstOrigToken && "not using original tokens?"); - - // Since we're using original tokens, apply that offset. - assert(FirstOrigToken[NumConsumedToks].getLocation() - == LineToks[NumConsumedToks].getLocation()); - unsigned FirstIndex = FirstOrigToken - AsmToks.begin(); - unsigned LastIndex = FirstIndex + NumConsumedToks - 1; - - // The total length we've consumed is the relative offset - // of the last token we consumed plus its length. - unsigned TotalOffset = (AsmTokOffsets[LastIndex] - + AsmToks[LastIndex].getLength() - - AsmTokOffsets[FirstIndex]); - LineBuf = LineBuf.substr(0, TotalOffset); - } - - // Initialize the "decl" with the lookup result. - Info.OpDecl = static_cast<void*>(Result.take()); - return Info.OpDecl; - } - - bool LookupInlineAsmField(StringRef Base, StringRef Member, - unsigned &Offset) { - return TheParser.getActions().LookupInlineAsmField(Base, Member, - Offset, AsmLoc); - } - - static void DiagHandlerCallback(const llvm::SMDiagnostic &D, - void *Context) { - ((ClangAsmParserCallback*) Context)->handleDiagnostic(D); - } - - private: - /// Collect the appropriate tokens for the given string. - void findTokensForString(StringRef Str, SmallVectorImpl<Token> &TempToks, - const Token *&FirstOrigToken) const { - // For now, assert that the string we're working with is a substring - // of what we gave to MC. This lets us use the original tokens. - assert(!std::less<const char*>()(Str.begin(), AsmString.begin()) && - !std::less<const char*>()(AsmString.end(), Str.end())); - - // Try to find a token whose offset matches the first token. - unsigned FirstCharOffset = Str.begin() - AsmString.begin(); - const unsigned *FirstTokOffset - = std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), - FirstCharOffset); - - // For now, assert that the start of the string exactly - // corresponds to the start of a token. - assert(*FirstTokOffset == FirstCharOffset); - - // Use all the original tokens for this line. (We assume the - // end of the line corresponds cleanly to a token break.) - unsigned FirstTokIndex = FirstTokOffset - AsmTokOffsets.begin(); - FirstOrigToken = &AsmToks[FirstTokIndex]; - unsigned LastCharOffset = Str.end() - AsmString.begin(); - for (unsigned i = FirstTokIndex, e = AsmTokOffsets.size(); i != e; ++i) { - if (AsmTokOffsets[i] >= LastCharOffset) break; - TempToks.push_back(AsmToks[i]); - } - } - - void handleDiagnostic(const llvm::SMDiagnostic &D) { - // Compute an offset into the inline asm buffer. - // FIXME: This isn't right if .macro is involved (but hopefully, no - // real-world code does that). - const llvm::SourceMgr &LSM = *D.getSourceMgr(); - const llvm::MemoryBuffer *LBuf = - LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); - unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); - - // Figure out which token that offset points into. - const unsigned *TokOffsetPtr = - std::lower_bound(AsmTokOffsets.begin(), AsmTokOffsets.end(), Offset); - unsigned TokIndex = TokOffsetPtr - AsmTokOffsets.begin(); - unsigned TokOffset = *TokOffsetPtr; - - // If we come up with an answer which seems sane, use it; otherwise, - // just point at the __asm keyword. - // FIXME: Assert the answer is sane once we handle .macro correctly. - SourceLocation Loc = AsmLoc; - if (TokIndex < AsmToks.size()) { - const Token &Tok = AsmToks[TokIndex]; - Loc = Tok.getLocation(); - Loc = Loc.getLocWithOffset(Offset - TokOffset); - } - TheParser.Diag(Loc, diag::err_inline_ms_asm_parsing) - << D.getMessage(); - } - }; -} - -/// Parse an identifier in an MS-style inline assembly block. -/// -/// \param CastInfo - a void* so that we don't have to teach Parser.h -/// about the actual type. -ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, - unsigned &NumLineToksConsumed, - void *CastInfo, - bool IsUnevaluatedContext) { - llvm::InlineAsmIdentifierInfo &Info = - *(llvm::InlineAsmIdentifierInfo *) CastInfo; - - // Push a fake token on the end so that we don't overrun the token - // stream. We use ';' because it expression-parsing should never - // overrun it. - const tok::TokenKind EndOfStream = tok::semi; - Token EndOfStreamTok; - EndOfStreamTok.startToken(); - EndOfStreamTok.setKind(EndOfStream); - LineToks.push_back(EndOfStreamTok); - - // Also copy the current token over. - LineToks.push_back(Tok); - - PP.EnterTokenStream(LineToks.begin(), - LineToks.size(), - /*disable macros*/ true, - /*owns tokens*/ false); - - // Clear the current token and advance to the first token in LineToks. - ConsumeAnyToken(); - - // Parse an optional scope-specifier if we're in C++. - CXXScopeSpec SS; - if (getLangOpts().CPlusPlus) { - ParseOptionalCXXScopeSpecifier(SS, ParsedType(), /*EnteringContext=*/false); - } - - // Require an identifier here. - SourceLocation TemplateKWLoc; - UnqualifiedId Id; - bool Invalid = ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*ObjectType=*/ ParsedType(), - TemplateKWLoc, - Id); - - // If we've run into the poison token we inserted before, or there - // was a parsing error, then claim the entire line. - if (Invalid || Tok.is(EndOfStream)) { - NumLineToksConsumed = LineToks.size() - 2; - - // Otherwise, claim up to the start of the next token. - } else { - // Figure out how many tokens we are into LineToks. - unsigned LineIndex = 0; - while (LineToks[LineIndex].getLocation() != Tok.getLocation()) { - LineIndex++; - assert(LineIndex < LineToks.size() - 2); // we added two extra tokens - } - - NumLineToksConsumed = LineIndex; - } - - // Finally, restore the old parsing state by consuming all the - // tokens we staged before, implicitly killing off the - // token-lexer we pushed. - for (unsigned n = LineToks.size() - 2 - NumLineToksConsumed; n != 0; --n) { - ConsumeAnyToken(); - } - ConsumeToken(EndOfStream); - - // Leave LineToks in its original state. - LineToks.pop_back(); - LineToks.pop_back(); - - // Perform the lookup. - return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, - IsUnevaluatedContext); + return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } -/// Turn a sequence of our tokens back into a string that we can hand -/// to the MC asm parser. -static bool buildMSAsmString(Preprocessor &PP, - SourceLocation AsmLoc, - ArrayRef<Token> AsmToks, - SmallVectorImpl<unsigned> &TokOffsets, - SmallString<512> &Asm) { - assert (!AsmToks.empty() && "Didn't expect an empty AsmToks!"); - - // Is this the start of a new assembly statement? - bool isNewStatement = true; - - for (unsigned i = 0, e = AsmToks.size(); i < e; ++i) { - const Token &Tok = AsmToks[i]; - - // Start each new statement with a newline and a tab. - if (!isNewStatement && - (Tok.is(tok::kw_asm) || Tok.isAtStartOfLine())) { - Asm += "\n\t"; - isNewStatement = true; - } - - // Preserve the existence of leading whitespace except at the - // start of a statement. - if (!isNewStatement && Tok.hasLeadingSpace()) - Asm += ' '; +StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, bool OnlyStatement, + SourceLocation *TrailingElseLoc, + ParsedAttributesWithRange &Attrs) { + // Create temporary attribute list. + ParsedAttributesWithRange TempAttrs(AttrFactory); - // Remember the offset of this token. - TokOffsets.push_back(Asm.size()); - - // Don't actually write '__asm' into the assembly stream. - if (Tok.is(tok::kw_asm)) { - // Complain about __asm at the end of the stream. - if (i + 1 == e) { - PP.Diag(AsmLoc, diag::err_asm_empty); - return true; - } - - continue; - } - - // Append the spelling of the token. - SmallString<32> SpellingBuffer; - bool SpellingInvalid = false; - Asm += PP.getSpelling(Tok, SpellingBuffer, &SpellingInvalid); - assert(!SpellingInvalid && "spelling was invalid after correct parse?"); - - // We are no longer at the start of a statement. - isNewStatement = false; - } - - // Ensure that the buffer is null-terminated. - Asm.push_back('\0'); - Asm.pop_back(); - - assert(TokOffsets.size() == AsmToks.size()); - return false; -} - -/// ParseMicrosoftAsmStatement. When -fms-extensions/-fasm-blocks is enabled, -/// this routine is called to collect the tokens for an MS asm statement. -/// -/// [MS] ms-asm-statement: -/// 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] ms-asm-instruction-block -/// ms-asm-line -/// ms-asm-line '\n' ms-asm-instruction-block -/// -StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { - SourceManager &SrcMgr = PP.getSourceManager(); - SourceLocation EndLoc = AsmLoc; - SmallVector<Token, 4> AsmToks; - - 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(); - do { - // If we hit EOF, we're done, period. - if (Tok.is(tok::eof)) - 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; - } - } - if (!InAsmComment && InBraces && Tok.is(tok::r_brace) && - BraceCount == (savedBraceCount + 1)) { - // Consume the closing brace, and finish - EndLoc = ConsumeBrace(); - break; - } - - // Consume the next token; make sure we don't modify the brace count etc. - // if we are in a comment. - EndLoc = TokLoc; - if (InAsmComment) - PP.Lex(Tok); - else { - AsmToks.push_back(Tok); - ConsumeAnyToken(); - } - TokLoc = Tok.getLocation(); - ++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(); - } - - // Okay, prepare to use MC to parse the assembly. - SmallVector<StringRef, 4> ConstraintRefs; - SmallVector<Expr*, 4> Exprs; - SmallVector<StringRef, 4> ClobberRefs; - - // We need an actual supported target. - llvm::Triple TheTriple = Actions.Context.getTargetInfo().getTriple(); - llvm::Triple::ArchType ArchTy = TheTriple.getArch(); - const std::string &TT = TheTriple.getTriple(); - const llvm::Target *TheTarget = 0; - bool UnsupportedArch = (ArchTy != llvm::Triple::x86 && - ArchTy != llvm::Triple::x86_64); - if (UnsupportedArch) { - Diag(AsmLoc, diag::err_msasm_unsupported_arch) << TheTriple.getArchName(); - } else { - std::string Error; - TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error); - if (!TheTarget) - Diag(AsmLoc, diag::err_msasm_unable_to_create_target) << Error; - } - - // If we don't support assembly, or the assembly is empty, we don't - // need to instantiate the AsmParser, etc. - if (!TheTarget || AsmToks.empty()) { - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(), - /*NumOutputs*/ 0, /*NumInputs*/ 0, - ConstraintRefs, ClobberRefs, Exprs, EndLoc); - } - - // Expand the tokens into a string buffer. - SmallString<512> AsmString; - SmallVector<unsigned, 8> TokOffsets; - if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString)) - return StmtError(); - - OwningPtr<llvm::MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT)); - OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(*MRI, TT)); - // Get the instruction descriptor. - const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo(); - OwningPtr<llvm::MCObjectFileInfo> MOFI(new llvm::MCObjectFileInfo()); - OwningPtr<llvm::MCSubtargetInfo> - STI(TheTarget->createMCSubtargetInfo(TT, "", "")); - - llvm::SourceMgr TempSrcMgr; - llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr); - llvm::MemoryBuffer *Buffer = - llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>"); - - // Tell SrcMgr about this buffer, which is what the parser will pick up. - TempSrcMgr.AddNewSourceBuffer(Buffer, llvm::SMLoc()); - - OwningPtr<llvm::MCStreamer> Str(createNullStreamer(Ctx)); - OwningPtr<llvm::MCAsmParser> - Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI)); - OwningPtr<llvm::MCTargetAsmParser> - TargetParser(TheTarget->createMCAsmParser(*STI, *Parser, *MII)); - - llvm::MCInstPrinter *IP = - TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI); - - // Change to the Intel dialect. - Parser->setAssemblerDialect(1); - Parser->setTargetParser(*TargetParser.get()); - Parser->setParsingInlineAsm(true); - TargetParser->setParsingInlineAsm(true); - - ClangAsmParserCallback Callback(*this, AsmLoc, AsmString, - AsmToks, TokOffsets); - TargetParser->setSemaCallback(&Callback); - TempSrcMgr.setDiagHandler(ClangAsmParserCallback::DiagHandlerCallback, - &Callback); - - unsigned NumOutputs; - unsigned NumInputs; - std::string AsmStringIR; - SmallVector<std::pair<void *, bool>, 4> OpExprs; - SmallVector<std::string, 4> Constraints; - SmallVector<std::string, 4> Clobbers; - if (Parser->parseMSInlineAsm(AsmLoc.getPtrEncoding(), AsmStringIR, - NumOutputs, NumInputs, OpExprs, Constraints, - Clobbers, MII, IP, Callback)) - return StmtError(); - - // Build the vector of clobber StringRefs. - unsigned NumClobbers = Clobbers.size(); - ClobberRefs.resize(NumClobbers); - for (unsigned i = 0; i != NumClobbers; ++i) - ClobberRefs[i] = StringRef(Clobbers[i]); - - // Recast the void pointers and build the vector of constraint StringRefs. - unsigned NumExprs = NumOutputs + NumInputs; - ConstraintRefs.resize(NumExprs); - Exprs.resize(NumExprs); - for (unsigned i = 0, e = NumExprs; i != e; ++i) { - Expr *OpExpr = static_cast<Expr *>(OpExprs[i].first); - if (!OpExpr) - return StmtError(); - - // Need address of variable. - if (OpExprs[i].second) - OpExpr = Actions.BuildUnaryOp(getCurScope(), AsmLoc, UO_AddrOf, OpExpr) - .take(); - - ConstraintRefs[i] = StringRef(Constraints[i]); - Exprs[i] = OpExpr; - } - - // FIXME: We should be passing source locations for better diagnostics. - return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, AsmStringIR, - NumOutputs, NumInputs, - ConstraintRefs, ClobberRefs, Exprs, EndLoc); -} - -/// ParseAsmStatement - Parse a GNU extended asm statement. -/// asm-statement: -/// gnu-asm-statement -/// ms-asm-statement -/// -/// [GNU] gnu-asm-statement: -/// 'asm' type-qualifier[opt] '(' asm-argument ')' ';' -/// -/// [GNU] asm-argument: -/// asm-string-literal -/// asm-string-literal ':' asm-operands[opt] -/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] -/// asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt] -/// ':' asm-clobbers -/// -/// [GNU] asm-clobbers: -/// asm-string-literal -/// asm-clobbers ',' asm-string-literal -/// -StmtResult Parser::ParseAsmStatement(bool &msAsm) { - assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); - SourceLocation AsmLoc = ConsumeToken(); - - if (getLangOpts().AsmBlocks && Tok.isNot(tok::l_paren) && - !isTypeQualifier()) { - msAsm = true; - return ParseMicrosoftAsmStatement(AsmLoc); - } - DeclSpec DS(AttrFactory); - SourceLocation Loc = Tok.getLocation(); - ParseTypeQualifierListOpt(DS, true, false); - - // GNU asms accept, but warn, about type-qualifiers other than volatile. - if (DS.getTypeQualifiers() & DeclSpec::TQ_const) - Diag(Loc, diag::w_asm_qualifier_ignored) << "const"; - if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict) - Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict"; - // FIXME: Once GCC supports _Atomic, check whether it permits it here. - if (DS.getTypeQualifiers() & DeclSpec::TQ_atomic) - Diag(Loc, diag::w_asm_qualifier_ignored) << "_Atomic"; - - // Remember if this was a volatile asm. - bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile; - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after) << "asm"; - SkipUntil(tok::r_paren, StopAtSemi); - return StmtError(); - } - BalancedDelimiterTracker T(*this, tok::l_paren); - T.consumeOpen(); - - ExprResult AsmString(ParseAsmStringLiteral()); - if (AsmString.isInvalid()) { - // Consume up to and including the closing paren. - T.skipToEnd(); - return StmtError(); - } - - SmallVector<IdentifierInfo *, 4> Names; - ExprVector Constraints; - ExprVector Exprs; - ExprVector Clobbers; - - if (Tok.is(tok::r_paren)) { - // We have a simple asm expression like 'asm("foo")'. - T.consumeClose(); - return Actions.ActOnGCCAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile, - /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, - Constraints, Exprs, AsmString.take(), - Clobbers, T.getCloseLocation()); - } - - // Parse Outputs, if present. - bool AteExtraColon = false; - if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { - // In C++ mode, parse "::" like ": :". - AteExtraColon = Tok.is(tok::coloncolon); + // Get loop hints and consume annotated token. + while (Tok.is(tok::annot_pragma_loop_hint)) { + LoopHint Hint = HandlePragmaLoopHint(); ConsumeToken(); - if (!AteExtraColon && - ParseAsmOperandsOpt(Names, Constraints, Exprs)) - return StmtError(); + ArgsUnion ArgHints[] = {Hint.PragmaNameLoc, Hint.OptionLoc, Hint.ValueLoc, + ArgsUnion(Hint.ValueExpr)}; + TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr, + Hint.PragmaNameLoc->Loc, ArgHints, 4, + AttributeList::AS_Pragma); } - unsigned NumOutputs = Names.size(); - - // Parse Inputs, if present. - if (AteExtraColon || - Tok.is(tok::colon) || Tok.is(tok::coloncolon)) { - // In C++ mode, parse "::" like ": :". - if (AteExtraColon) - AteExtraColon = false; - else { - AteExtraColon = Tok.is(tok::coloncolon); - ConsumeToken(); - } + // Get the next statement. + MaybeParseCXX11Attributes(Attrs); - if (!AteExtraColon && - ParseAsmOperandsOpt(Names, Constraints, Exprs)) - return StmtError(); - } - - assert(Names.size() == Constraints.size() && - Constraints.size() == Exprs.size() && - "Input operand size mismatch!"); - - unsigned NumInputs = Names.size() - NumOutputs; - - // Parse the clobbers, if present. - if (AteExtraColon || Tok.is(tok::colon)) { - if (!AteExtraColon) - ConsumeToken(); - - // Parse the asm-string list for clobbers if present. - if (Tok.isNot(tok::r_paren)) { - while (1) { - ExprResult Clobber(ParseAsmStringLiteral()); - - if (Clobber.isInvalid()) - break; - - Clobbers.push_back(Clobber.release()); - - if (Tok.isNot(tok::comma)) break; - ConsumeToken(); - } - } - } + StmtResult S = ParseStatementOrDeclarationAfterAttributes( + Stmts, OnlyStatement, TrailingElseLoc, Attrs); - T.consumeClose(); - return Actions.ActOnGCCAsmStmt(AsmLoc, false, isVolatile, NumOutputs, - NumInputs, Names.data(), Constraints, Exprs, - AsmString.take(), Clobbers, - T.getCloseLocation()); -} - -/// ParseAsmOperands - Parse the asm-operands production as used by -/// asm-statement, assuming the leading ':' token was eaten. -/// -/// [GNU] asm-operands: -/// asm-operand -/// asm-operands ',' asm-operand -/// -/// [GNU] asm-operand: -/// asm-string-literal '(' expression ')' -/// '[' identifier ']' asm-string-literal '(' expression ')' -/// -// -// FIXME: Avoid unnecessary std::string trashing. -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; - - while (1) { - // Read the [id] if present. - if (Tok.is(tok::l_square)) { - BalancedDelimiterTracker T(*this, tok::l_square); - T.consumeOpen(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_expected_ident); - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - - IdentifierInfo *II = Tok.getIdentifierInfo(); - ConsumeToken(); - - Names.push_back(II); - T.consumeClose(); - } else - Names.push_back(0); - - ExprResult Constraint(ParseAsmStringLiteral()); - if (Constraint.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - Constraints.push_back(Constraint.release()); - - if (Tok.isNot(tok::l_paren)) { - Diag(Tok, diag::err_expected_lparen_after) << "asm operand"; - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - - // Read the parenthesized expression. - BalancedDelimiterTracker T(*this, tok::l_paren); - T.consumeOpen(); - ExprResult Res(ParseExpression()); - T.consumeClose(); - if (Res.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return true; - } - Exprs.push_back(Res.release()); - // Eat the comma and continue parsing if it exists. - if (Tok.isNot(tok::comma)) return false; - ConsumeToken(); - } + Attrs.takeAllFrom(TempAttrs); + return S; } Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { @@ -2464,7 +1880,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { } BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); + return Actions.ActOnFinishFunctionBody(Decl, FnBody.get()); } /// ParseFunctionTryBlock - Parse a C++ function-try-block. @@ -2501,7 +1917,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { } BodyScope.Exit(); - return Actions.ActOnFinishFunctionBody(Decl, FnBody.take()); + return Actions.ActOnFinishFunctionBody(Decl, FnBody.get()); } bool Parser::trySkippingFunctionBody() { @@ -2554,16 +1970,28 @@ StmtResult Parser::ParseCXXTryBlock() { /// /// [Borland] try-block: /// 'try' compound-statement seh-except-block -/// 'try' compound-statment seh-finally-block +/// 'try' compound-statement seh-finally-block /// StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { if (Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok, diag::err_expected_lbrace)); + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? - StmtResult TryBlock(ParseCompoundStatement(/*isStmtExpr=*/false, - Scope::DeclScope | Scope::TryScope | - (FnTry ? Scope::FnTryCatchScope : 0))); + int SEHTryIndex, SEHTryParentIndex; + StmtResult TryBlock; + { + assert(Tok.is(tok::l_brace) && "Not a compount stmt!"); + + // Enter a scope to hold everything within the compound stmt. Compound + // statements can always hold declarations. + ParseScope CompoundScope(this, Scope::DeclScope | Scope::TryScope | + (FnTry ? Scope::FnTryCatchScope : 0)); + SEHTryIndex = getCurScope()->getSEHTryIndex(); + SEHTryParentIndex = getCurScope()->getSEHTryParentIndex(); + + // Parse the statements in the body. + TryBlock = ParseCompoundStatementBody(); + } if (TryBlock.isInvalid()) return TryBlock; @@ -2587,8 +2015,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { return Actions.ActOnSEHTryBlock(true /* IsCXXTry */, TryLoc, - TryBlock.take(), - Handler.take()); + TryBlock.get(), + Handler.get(), + SEHTryIndex, + SEHTryParentIndex); } else { StmtVector Handlers; @@ -2602,14 +2032,14 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) { while (Tok.is(tok::kw_catch)) { StmtResult Handler(ParseCXXCatchBlock(FnTry)); if (!Handler.isInvalid()) - Handlers.push_back(Handler.release()); + Handlers.push_back(Handler.get()); } // Don't bother creating the full statement if we don't have any usable // handlers. if (Handlers.empty()) return StmtError(); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), Handlers); + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.get(), Handlers); } } @@ -2629,7 +2059,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { SourceLocation CatchLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_paren); - if (T.expectAndConsume(diag::err_expected_lparen)) + if (T.expectAndConsume()) return StmtError(); // C++ 3.3.2p3: @@ -2640,7 +2070,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { // exception-declaration is equivalent to '...' or a parameter-declaration // without default arguments. - Decl *ExceptionDecl = 0; + Decl *ExceptionDecl = nullptr; if (Tok.isNot(tok::ellipsis)) { ParsedAttributesWithRange Attributes(AttrFactory); MaybeParseCXX11Attributes(Attributes); @@ -2662,14 +2092,14 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { return StmtError(); if (Tok.isNot(tok::l_brace)) - return StmtError(Diag(Tok, diag::err_expected_lbrace)); + return StmtError(Diag(Tok, diag::err_expected) << tok::l_brace); // FIXME: Possible draft standard bug: attribute-specifier should be allowed? StmtResult Block(ParseCompoundStatement()); if (Block.isInvalid()) return Block; - return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.take()); + return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, Block.get()); } void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { @@ -2683,7 +2113,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { // 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); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -2703,7 +2133,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -2724,7 +2154,7 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { while (Tok.isNot(tok::r_brace)) { StmtResult R = ParseStatementOrDeclaration(Stmts, false); if (R.isUsable()) - Stmts.push_back(R.release()); + Stmts.push_back(R.get()); } Braces.consumeClose(); } |