summaryrefslogtreecommitdiffstats
path: root/lib/Parse/ParseStmt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseStmt.cpp')
-rw-r--r--lib/Parse/ParseStmt.cpp209
1 files changed, 136 insertions, 73 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp
index 43b6965..d1f2138 100644
--- a/lib/Parse/ParseStmt.cpp
+++ b/lib/Parse/ParseStmt.cpp
@@ -41,6 +41,21 @@ using namespace clang;
// C99 6.8: Statements and Blocks.
//===----------------------------------------------------------------------===//
+/// \brief Parse a standalone statement (for instance, as the body of an 'if',
+/// 'while', or 'for').
+StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc) {
+ StmtResult Res;
+
+ // We may get back a null statement if we found a #pragma. Keep going until
+ // we get an actual statement.
+ do {
+ StmtVector Stmts;
+ Res = ParseStatementOrDeclaration(Stmts, true, TrailingElseLoc);
+ } while (!Res.isInvalid() && !Res.get());
+
+ return Res;
+}
+
/// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
/// StatementOrDeclaration:
/// statement
@@ -111,6 +126,38 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, bool OnlyStatement,
return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range);
}
+namespace {
+class StatementFilterCCC : public CorrectionCandidateCallback {
+public:
+ StatementFilterCCC(Token nextTok) : NextToken(nextTok) {
+ WantTypeSpecifiers = nextTok.is(tok::l_paren) || nextTok.is(tok::less) ||
+ nextTok.is(tok::identifier) || nextTok.is(tok::star) ||
+ nextTok.is(tok::amp) || nextTok.is(tok::l_square);
+ WantExpressionKeywords = nextTok.is(tok::l_paren) ||
+ nextTok.is(tok::identifier) ||
+ nextTok.is(tok::arrow) || nextTok.is(tok::period);
+ WantRemainingKeywords = nextTok.is(tok::l_paren) || nextTok.is(tok::semi) ||
+ nextTok.is(tok::identifier) ||
+ nextTok.is(tok::l_brace);
+ WantCXXNamedCasts = false;
+ }
+
+ virtual bool ValidateCandidate(const TypoCorrection &candidate) {
+ if (FieldDecl *FD = candidate.getCorrectionDeclAs<FieldDecl>())
+ return !candidate.getCorrectionSpecifier() || isa<ObjCIvarDecl>(FD);
+ if (NextToken.is(tok::equal))
+ return candidate.getCorrectionDeclAs<VarDecl>();
+ if (NextToken.is(tok::period) &&
+ candidate.getCorrectionDeclAs<NamespaceDecl>())
+ return false;
+ return CorrectionCandidateCallback::ValidateCandidate(candidate);
+ }
+
+private:
+ Token NextToken;
+};
+}
+
StmtResult
Parser::ParseStatementOrDeclarationAfterAttributes(StmtVector &Stmts,
bool OnlyStatement, SourceLocation *TrailingElseLoc,
@@ -149,25 +196,12 @@ Retry:
if (Next.isNot(tok::coloncolon)) {
// Try to limit which sets of keywords should be included in typo
// correction based on what the next token is.
- // FIXME: Pass the next token into the CorrectionCandidateCallback and
- // do this filtering in a more fine-grained manner.
- CorrectionCandidateCallback DefaultValidator;
- DefaultValidator.WantTypeSpecifiers =
- Next.is(tok::l_paren) || Next.is(tok::less) ||
- Next.is(tok::identifier) || Next.is(tok::star) ||
- Next.is(tok::amp) || Next.is(tok::l_square);
- DefaultValidator.WantExpressionKeywords =
- Next.is(tok::l_paren) || Next.is(tok::identifier) ||
- Next.is(tok::arrow) || Next.is(tok::period);
- DefaultValidator.WantRemainingKeywords =
- Next.is(tok::l_paren) || Next.is(tok::semi) ||
- Next.is(tok::identifier) || Next.is(tok::l_brace);
- DefaultValidator.WantCXXNamedCasts = false;
- if (TryAnnotateName(/*IsAddressOfOperand*/false, &DefaultValidator)
+ StatementFilterCCC Validator(Next);
+ if (TryAnnotateName(/*IsAddressOfOperand*/false, &Validator)
== ANK_Error) {
// Handle errors here by skipping up to the next semicolon or '}', and
// eat the semicolon if that's what stopped us.
- SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return StmtError();
@@ -293,6 +327,7 @@ Retry:
return StmtEmpty();
case tok::annot_pragma_fp_contract:
+ ProhibitAttributes(Attrs);
Diag(Tok, diag::err_pragma_fp_contract_scope);
ConsumeToken();
return StmtError();
@@ -303,12 +338,13 @@ Retry:
return StmtEmpty();
case tok::annot_pragma_captured:
+ ProhibitAttributes(Attrs);
return HandlePragmaCaptured();
case tok::annot_pragma_openmp:
- SourceLocation DeclStart = Tok.getLocation();
- DeclGroupPtrTy Res = ParseOpenMPDeclarativeDirective();
- return Actions.ActOnDeclStmt(Res, DeclStart, Tok.getLocation());
+ ProhibitAttributes(Attrs);
+ return ParseOpenMPDeclarativeOrExecutableDirective();
+
}
// If we reached this code, the statement must end in a semicolon.
@@ -320,7 +356,7 @@ Retry:
// succeed.
ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
// Skip until we see a } or ;, but don't eat it.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
}
return Res;
@@ -337,7 +373,7 @@ StmtResult Parser::ParseExprStatement() {
// If the expression is invalid, skip ahead to the next semicolon or '}'.
// Not doing this opens us up to the possibility of infinite loops if
// ParseExpression does not consume any tokens.
- SkipUntil(tok::r_brace, /*StopAtSemi=*/true, /*DontConsume=*/true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return Actions.ActOnExprStmtError();
@@ -480,11 +516,40 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) {
// identifier ':' statement
SourceLocation ColonLoc = ConsumeToken();
- // Read label attributes, if present. attrs will contain both C++11 and GNU
- // attributes (if present) after this point.
- MaybeParseGNUAttributes(attrs);
+ // Read label attributes, if present.
+ StmtResult SubStmt;
+ if (Tok.is(tok::kw___attribute)) {
+ ParsedAttributesWithRange TempAttrs(AttrFactory);
+ ParseGNUAttributes(TempAttrs);
+
+ // In C++, GNU attributes only apply to the label if they are followed by a
+ // semicolon, to disambiguate label attributes from attributes on a labeled
+ // declaration.
+ //
+ // This doesn't quite match what GCC does; if the attribute list is empty
+ // and followed by a semicolon, GCC will reject (it appears to parse the
+ // attributes as part of a statement in that case). That looks like a bug.
+ if (!getLangOpts().CPlusPlus || Tok.is(tok::semi))
+ attrs.takeAllFrom(TempAttrs);
+ else if (isDeclarationStatement()) {
+ StmtVector Stmts;
+ // FIXME: We should do this whether or not we have a declaration
+ // statement, but that doesn't work correctly (because ProhibitAttributes
+ // 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);
+ if (!TempAttrs.empty() && !SubStmt.isInvalid())
+ SubStmt = Actions.ProcessStmtAttributes(
+ SubStmt.get(), TempAttrs.getList(), TempAttrs.Range);
+ } else {
+ Diag(Tok, diag::err_expected_semi_after) << "__attribute__";
+ }
+ }
- StmtResult SubStmt(ParseStatement());
+ // If we've not parsed a statement yet, parse one now.
+ if (!SubStmt.isInvalid() && !SubStmt.isUsable())
+ SubStmt = ParseStatement();
// Broken substmt shouldn't prevent the label from being added to the AST.
if (SubStmt.isInvalid())
@@ -521,7 +586,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
// out of stack space in our recursive descent parser. As a special case,
// flatten this recursion into an iterative loop. This is complex and gross,
// but all the grossness is constrained to ParseCaseStatement (and some
- // wierdness in the actions), so this is just local grossness :).
+ // weirdness in the actions), so this is just local grossness :).
// TopLevelCase - This is the highest level we have parsed. 'case 1' in the
// example above.
@@ -552,7 +617,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
ExprResult LHS(MissingCase ? Expr : ParseConstantExpression());
MissingCase = false;
if (LHS.isInvalid()) {
- SkipUntil(tok::colon);
+ SkipUntil(tok::colon, StopAtSemi);
return StmtError();
}
@@ -565,7 +630,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) {
RHS = ParseConstantExpression();
if (RHS.isInvalid()) {
- SkipUntil(tok::colon);
+ SkipUntil(tok::colon, StopAtSemi);
return StmtError();
}
}
@@ -798,7 +863,6 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
// only allowed at the start of a compound stmt regardless of the language.
while (Tok.is(tok::kw___label__)) {
SourceLocation LabelLoc = ConsumeToken();
- Diag(LabelLoc, diag::ext_gnu_local_label);
SmallVector<Decl *, 8> DeclsInGroup;
while (1) {
@@ -817,8 +881,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
}
DeclSpec DS(AttrFactory);
- DeclGroupPtrTy Res = Actions.FinalizeDeclaratorGroup(getCurScope(), DS,
- DeclsInGroup.data(), DeclsInGroup.size());
+ DeclGroupPtrTy Res =
+ Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation());
ExpectAndConsumeSemi(diag::err_expected_semi_declaration);
@@ -1132,7 +1196,7 @@ StmtResult Parser::ParseSwitchStatement(SourceLocation *TrailingElseLoc) {
// will have no place to connect back with the switch.
if (Tok.is(tok::l_brace)) {
ConsumeBrace();
- SkipUntil(tok::r_brace, false, false);
+ SkipUntil(tok::r_brace);
} else
SkipUntil(tok::semi);
return Switch;
@@ -1283,7 +1347,7 @@ StmtResult Parser::ParseDoStatement() {
if (!Body.isInvalid()) {
Diag(Tok, diag::err_expected_while);
Diag(DoLoc, diag::note_matching) << "do";
- SkipUntil(tok::semi, false, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
}
return StmtError();
}
@@ -1291,18 +1355,16 @@ StmtResult Parser::ParseDoStatement() {
if (Tok.isNot(tok::l_paren)) {
Diag(Tok, diag::err_expected_lparen_after) << "do/while";
- SkipUntil(tok::semi, false, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
return StmtError();
}
- // Parse the parenthesized condition.
+ // Parse the parenthesized expression.
BalancedDelimiterTracker T(*this, tok::l_paren);
T.consumeOpen();
- // FIXME: Do not just parse the attribute contents and throw them away
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- ProhibitAttributes(attrs);
+ // A do-while expression is not a condition, so can't have attributes.
+ DiagnoseAndSkipCXX11Attributes();
ExprResult Cond = ParseExpression();
T.consumeClose();
@@ -1469,14 +1531,14 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
// for (expr : expr) { ... }
Diag(Tok, diag::err_for_range_expected_decl)
<< FirstPart.get()->getSourceRange();
- SkipUntil(tok::r_paren, false, true);
+ SkipUntil(tok::r_paren, StopBeforeMatch);
SecondPartIsInvalid = true;
} else {
if (!Value.isInvalid()) {
Diag(Tok, diag::err_expected_semi_for);
} else {
// Skip until semicolon or rparen, don't consume it.
- SkipUntil(tok::r_paren, true, true);
+ SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
}
@@ -1508,7 +1570,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
Diag(Tok, diag::err_expected_semi_for);
else
// Skip until semicolon or rparen, don't consume it.
- SkipUntil(tok::r_paren, true, true);
+ SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch);
}
if (Tok.is(tok::semi)) {
@@ -1610,7 +1672,7 @@ StmtResult Parser::ParseGotoStatement() {
SourceLocation StarLoc = ConsumeToken();
ExprResult R(ParseExpression());
if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
- SkipUntil(tok::semi, false, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
return StmtError();
}
Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, R.take());
@@ -1669,7 +1731,7 @@ StmtResult Parser::ParseReturnStatement() {
} else
R = ParseExpression();
if (R.isInvalid()) { // Skip to the semicolon, but don't consume it.
- SkipUntil(tok::semi, false, true);
+ SkipUntil(tok::semi, StopBeforeMatch);
return StmtError();
}
}
@@ -2067,14 +2129,22 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
// 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)
+ 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 (UnsupportedArch || AsmToks.empty()) {
+ if (!TheTarget || AsmToks.empty()) {
return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, AsmToks, StringRef(),
/*NumOutputs*/ 0, /*NumInputs*/ 0,
ConstraintRefs, ClobberRefs, Exprs, EndLoc);
@@ -2086,19 +2156,16 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
if (buildMSAsmString(PP, AsmLoc, AsmToks, TokOffsets, AsmString))
return StmtError();
- // Find the target and create the target specific parser.
- std::string Error;
- const std::string &TT = TheTriple.getTriple();
- const llvm::Target *TheTarget = llvm::TargetRegistry::lookupTarget(TT, Error);
-
- OwningPtr<llvm::MCAsmInfo> MAI(TheTarget->createMCAsmInfo(TT));
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, *MRI, MOFI.get(), &TempSrcMgr);
+ llvm::MCContext Ctx(MAI.get(), MRI.get(), MOFI.get(), &TempSrcMgr);
llvm::MemoryBuffer *Buffer =
llvm::MemoryBuffer::getMemBuffer(AsmString, "<MS inline asm>");
@@ -2109,10 +2176,8 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) {
OwningPtr<llvm::MCAsmParser>
Parser(createMCAsmParser(TempSrcMgr, Ctx, *Str.get(), *MAI));
OwningPtr<llvm::MCTargetAsmParser>
- TargetParser(TheTarget->createMCAsmParser(*STI, *Parser));
+ TargetParser(TheTarget->createMCAsmParser(*STI, *Parser, *MII));
- // Get the instruction descriptor.
- const llvm::MCInstrInfo *MII = TheTarget->createMCInstrInfo();
llvm::MCInstPrinter *IP =
TheTarget->createMCInstPrinter(1, *MAI, *MII, *MRI, *STI);
@@ -2214,7 +2279,7 @@ StmtResult Parser::ParseAsmStatement(bool &msAsm) {
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);
+ SkipUntil(tok::r_paren, StopAtSemi);
return StmtError();
}
BalancedDelimiterTracker T(*this, tok::l_paren);
@@ -2333,7 +2398,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
if (Tok.isNot(tok::identifier)) {
Diag(Tok, diag::err_expected_ident);
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -2347,14 +2412,14 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
ExprResult Constraint(ParseAsmStringLiteral());
if (Constraint.isInvalid()) {
- SkipUntil(tok::r_paren);
+ 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);
+ SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
@@ -2364,7 +2429,7 @@ bool Parser::ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names,
ExprResult Res(ParseExpression());
T.consumeClose();
if (Res.isInvalid()) {
- SkipUntil(tok::r_paren);
+ SkipUntil(tok::r_paren, StopAtSemi);
return true;
}
Exprs.push_back(Res.release());
@@ -2395,8 +2460,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) {
// If the function body could not be parsed, make a bogus compoundstmt.
if (FnBody.isInvalid()) {
Sema::CompoundScopeRAII CompoundScope(Actions);
- FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
- MultiStmtArg(), false);
+ FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
}
BodyScope.Exit();
@@ -2433,8 +2497,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) {
// compound statement as the body.
if (FnBody.isInvalid()) {
Sema::CompoundScopeRAII CompoundScope(Actions);
- FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
- MultiStmtArg(), false);
+ FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc, None, false);
}
BodyScope.Exit();
@@ -2448,7 +2511,7 @@ bool Parser::trySkippingFunctionBody() {
if (!PP.isCodeCompletionEnabled()) {
ConsumeBrace();
- SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false);
+ SkipUntil(tok::r_brace);
return true;
}
@@ -2456,8 +2519,7 @@ bool Parser::trySkippingFunctionBody() {
// the body contains the code-completion point.
TentativeParsingAction PA(*this);
ConsumeBrace();
- if (SkipUntil(tok::r_brace, /*StopAtSemi=*/false, /*DontConsume=*/false,
- /*StopAtCodeCompletion=*/true)) {
+ if (SkipUntil(tok::r_brace, StopAtCodeCompletion)) {
PA.Commit();
return true;
}
@@ -2530,9 +2592,10 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
}
else {
StmtVector Handlers;
- ParsedAttributesWithRange attrs(AttrFactory);
- MaybeParseCXX11Attributes(attrs);
- ProhibitAttributes(attrs);
+
+ // C++11 attributes can't appear here, despite this context seeming
+ // statement-like.
+ DiagnoseAndSkipCXX11Attributes();
if (Tok.isNot(tok::kw_catch))
return StmtError(Diag(Tok, diag::err_expected_catch));
@@ -2546,7 +2609,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc, bool FnTry) {
if (Handlers.empty())
return StmtError();
- return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(),Handlers);
+ return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), Handlers);
}
}
OpenPOWER on IntegriCloud