diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp | 274 |
1 files changed, 142 insertions, 132 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp index 44320df..df9b996 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseStmt.cpp +++ b/contrib/llvm/tools/clang/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,9 +1492,10 @@ 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(), + ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.take(), ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), T.getCloseLocation()); @@ -1480,9 +1504,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, + 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 +1537,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,116 +1639,115 @@ 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; - do { - bool InBraces = false; - unsigned short savedBraceCount = 0; - bool InAsmComment = false; - FileID FID; - unsigned LineNo = 0; - unsigned NumTokensRead = 0; - SourceLocation LBraceLoc; - - if (Tok.is(tok::l_brace)) { - // Braced inline asm: consume the opening brace. - InBraces = true; - savedBraceCount = BraceCount; - EndLoc = LBraceLoc = ConsumeBrace(); - ++NumTokensRead; - } else { - // Single-line inline asm; compute which line it is on. - std::pair<FileID, unsigned> ExpAsmLoc = - SrcMgr.getDecomposedExpansionLoc(EndLoc); - FID = ExpAsmLoc.first; - LineNo = SrcMgr.getLineNumber(FID, ExpAsmLoc.second); - } + 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; - // When we consume the closing brace, we're done. - if (InBraces && BraceCount == savedBraceCount) - break; + 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? + if (!InAsmComment && Tok.is(tok::semi)) { + // A semicolon in an asm is the start of a comment. + InAsmComment = true; + if (InBraces) { + // Compute which line the comment is on. + std::pair<FileID, unsigned> ExpSemiLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + FID = ExpSemiLoc.first; + LineNo = SrcMgr.getLineNumber(FID, ExpSemiLoc.second); + } + } else if (!InBraces || InAsmComment) { + // If end-of-line is significant, check whether this token is on a + // new line. + std::pair<FileID, unsigned> ExpLoc = + SrcMgr.getDecomposedExpansionLoc(TokLoc); + if (ExpLoc.first != FID || + SrcMgr.getLineNumber(ExpLoc.first, ExpLoc.second) != LineNo) { + // If this is a single-line __asm, we're done. + if (!InBraces) break; - } + // We're no longer in a comment. + InAsmComment = false; + } else if (!InAsmComment && Tok.is(tok::r_brace)) { + // Single-line asm always ends when a closing brace is seen. + // FIXME: This is compatible with Apple gcc's -fasm-blocks; what + // does MSVC do here? + break; } - - // Consume the next token; make sure we don't modify the brace count etc. - // if we are in a comment. - EndLoc = TokLoc; - if (InAsmComment) - PP.Lex(Tok); - else - 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(); } - // Multiple adjacent asm's form together into a single asm statement - // in the AST. - if (!Tok.is(tok::kw_asm)) + if (!InAsmComment && InBraces && Tok.is(tok::r_brace) && + BraceCount == (savedBraceCount + 1)) { + // Consume the closing brace, and finish + EndLoc = ConsumeBrace(); break; - EndLoc = ConsumeToken(); + } + + // 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); - // 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); + + 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(); + } + + // FIXME: We should be passing source locations for better diagnostics. + return Actions.ActOnMSAsmStmt(AsmLoc, LBraceLoc, + llvm::makeArrayRef(AsmToks), EndLoc); } /// ParseAsmStatement - Parse a GNU extended asm statement. @@ -1748,23 +1769,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 +2077,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 +2117,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 +2213,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; |