summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp1150
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();
}
OpenPOWER on IntegriCloud