diff options
Diffstat (limited to 'lib/Parse/ParseStmt.cpp')
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 127 |
1 files changed, 76 insertions, 51 deletions
diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 44320df..d2e4309 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -20,6 +20,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallString.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -771,7 +772,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { DeclsInGroup.data(), DeclsInGroup.size()); StmtResult R = Actions.ActOnDeclStmt(Res, LabelLoc, Tok.getLocation()); - ExpectAndConsume(tok::semi, diag::err_expected_semi_declaration); + ExpectAndConsumeSemi(diag::err_expected_semi_declaration); if (R.isUsable()) Stmts.push_back(R.release()); } @@ -895,6 +896,16 @@ bool Parser::ParseParenExprOrCondition(ExprResult &ExprResult, // Otherwise the condition is valid or the rparen is present. T.consumeClose(); + + // Check for extraneous ')'s to catch things like "if (foo())) {". We know + // that all callers are looking for a statement after the condition, so ")" + // isn't valid. + while (Tok.is(tok::r_paren)) { + Diag(Tok, diag::err_extraneous_rparen_in_condition) + << FixItHint::CreateRemoval(Tok.getLocation()); + ConsumeParen(); + } + return false; } @@ -938,7 +949,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { if (ParseParenExprOrCondition(CondExp, CondVar, IfLoc, true)) return StmtError(); - FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get())); + FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp.get(), IfLoc)); // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1164,7 +1175,7 @@ StmtResult Parser::ParseWhileStatement(SourceLocation *TrailingElseLoc) { if (ParseParenExprOrCondition(Cond, CondVar, WhileLoc, true)) return StmtError(); - FullExprArg FullCond(Actions.MakeFullExpr(Cond.get())); + FullExprArg FullCond(Actions.MakeFullExpr(Cond.get(), WhileLoc)); // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if // there is no compound stmt. C90 does not have this clause. We only do this @@ -1248,6 +1259,12 @@ StmtResult Parser::ParseDoStatement() { // Parse the parenthesized condition. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); + + // FIXME: Do not just parse the attribute contents and throw them away + ParsedAttributesWithRange attrs(AttrFactory); + MaybeParseCXX0XAttributes(attrs); + ProhibitAttributes(attrs); + ExprResult Cond = ParseExpression(); T.consumeClose(); DoScope.Exit(); @@ -1288,7 +1305,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); } - bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus || getLangOpts().ObjC1; + bool C99orCXXorObjC = getLangOpts().C99 || getLangOpts().CPlusPlus || + getLangOpts().ObjC1; // C99 6.8.5p5 - In C99, the for statement is a block. This is not // the case for C90. Start the loop scope. @@ -1336,8 +1354,12 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); } + ParsedAttributesWithRange attrs(AttrFactory); + MaybeParseCXX0XAttributes(attrs); + // Parse the first part of the for specifier. if (Tok.is(tok::semi)) { // for (; + ProhibitAttributes(attrs); // no first part, eat the ';'. ConsumeToken(); } else if (isForInitDeclaration()) { // for (int X = 4; @@ -1382,6 +1404,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Diag(Tok, diag::err_expected_semi_for); } } else { + ProhibitAttributes(attrs); Value = ParseExpression(); ForEach = isTokIdentifier_in(); @@ -1441,7 +1464,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { Second.get()); } SecondPartIsInvalid = Second.isInvalid(); - SecondPart = Actions.MakeFullExpr(Second.get()); + SecondPart = Actions.MakeFullExpr(Second.get(), ForLoc); } if (Tok.isNot(tok::semi)) { @@ -1469,6 +1492,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // statememt before parsing the body, in order to be able to deduce the type // of an auto-typed loop variable. StmtResult ForRangeStmt; + StmtResult ForEachStmt; + if (ForRange) { ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, T.getOpenLocation(), FirstPart.take(), @@ -1480,9 +1505,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Similarly, we need to do the semantic analysis for a for-range // statement immediately in order to close over temporaries correctly. } else if (ForEach) { - if (!Collection.isInvalid()) - Collection = - Actions.ActOnObjCForCollectionOperand(ForLoc, Collection.take()); + ForEachStmt = Actions.ActOnObjCForCollectionStmt(ForLoc, T.getOpenLocation(), + FirstPart.take(), + Collection.take(), + T.getCloseLocation()); } // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if @@ -1512,11 +1538,8 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { return StmtError(); if (ForEach) - return Actions.ActOnObjCForCollectionStmt(ForLoc, T.getOpenLocation(), - FirstPart.take(), - Collection.take(), - T.getCloseLocation(), - Body.take()); + return Actions.FinishObjCForCollectionStmt(ForEachStmt.take(), + Body.take()); if (ForRange) return Actions.FinishCXXForRangeStmt(ForRangeStmt.take(), Body.take()); @@ -1617,9 +1640,24 @@ StmtResult Parser::ParseReturnStatement() { /// 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; + SmallVector<unsigned, 4> LineEnds; do { bool InBraces = false; unsigned short savedBraceCount = 0; @@ -1648,8 +1686,10 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { // If we hit EOF, we're done, period. if (Tok.is(tok::eof)) break; - // When we consume the closing brace, we're done. - if (InBraces && BraceCount == savedBraceCount) + + // The asm keyword is a statement separator, so multiple asm statements + // are allowed. + if (!InAsmComment && Tok.is(tok::kw_asm)) break; if (!InAsmComment && Tok.is(tok::semi)) { @@ -1681,18 +1721,28 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { 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 + else { + AsmToks.push_back(Tok); ConsumeAnyToken(); + } TokLoc = Tok.getLocation(); ++NumTokensRead; } while (1); + LineEnds.push_back(AsmToks.size()); + if (InBraces && BraceCount != savedBraceCount) { // __asm without closing brace (this can happen at EOF). Diag(Tok, diag::err_expected_rbrace); @@ -1709,24 +1759,10 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { break; EndLoc = ConsumeToken(); } while (1); - // FIXME: Need to actually grab the data and pass it on to Sema. Ideally, - // what Sema wants is a string of the entire inline asm, with one instruction - // per line and all the __asm keywords stripped out, and a way of mapping - // from any character of that string to its location in the original source - // code. I'm not entirely sure how to go about that, though. - Token t; - t.setKind(tok::string_literal); - t.setLiteralData("\"/*FIXME: not done*/\""); - t.clearFlag(Token::NeedsCleaning); - t.setLength(21); - ExprResult AsmString(Actions.ActOnStringLiteral(&t, 1)); - ExprVector Constraints(Actions); - ExprVector Exprs(Actions); - ExprVector Clobbers(Actions); - return Actions.ActOnAsmStmt(AsmLoc, true, true, 0, 0, 0, - move_arg(Constraints), move_arg(Exprs), - AsmString.take(), move_arg(Clobbers), - EndLoc, true); + + // FIXME: We should be passing source locations for better diagnostics. + return Actions.ActOnMSAsmStmt(AsmLoc, llvm::makeArrayRef(AsmToks), + llvm::makeArrayRef(LineEnds), EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. @@ -1748,23 +1784,12 @@ StmtResult Parser::ParseMicrosoftAsmStatement(SourceLocation AsmLoc) { /// asm-string-literal /// asm-clobbers ',' asm-string-literal /// -/// [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::ParseAsmStatement(bool &msAsm) { assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); - if (getLangOpts().MicrosoftExt && Tok.isNot(tok::l_paren) && !isTypeQualifier()) { + if (getLangOpts().MicrosoftExt && Tok.isNot(tok::l_paren) && + !isTypeQualifier()) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); } @@ -2067,7 +2092,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { return move(TryBlock); // Borland allows SEH-handlers with 'try' - + if ((Tok.is(tok::identifier) && Tok.getIdentifierInfo() == getSEHExceptKeyword()) || Tok.is(tok::kw___finally)) { @@ -2107,7 +2132,7 @@ StmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) { if (Handlers.empty()) return StmtError(); - return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(), move_arg(Handlers)); + return Actions.ActOnCXXTryBlock(TryLoc, TryBlock.take(),move_arg(Handlers)); } } @@ -2203,10 +2228,10 @@ void Parser::ParseMicrosoftIfExistsStatement(StmtVector &Stmts) { case IEB_Parse: // Parse the statements below. break; - + case IEB_Dependent: llvm_unreachable("Dependent case handled above"); - + case IEB_Skip: Braces.skipToEnd(); return; |