zcov: / lib/Parse/ParseStmt.cpp


Files: 1 Branches Taken: 79.3% 388 / 489
Generated: 2010-02-10 01:31 Branches Executed: 98.8% 483 / 489
Line Coverage: 87.6% 522 / 596


Programs: 2 Runs 3018


       1                 : //===--- ParseStmt.cpp - Statement and Block Parser -----------------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This file implements the Statement and Block portions of the Parser
      11                 : // interface.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Parse/Parser.h"
      16                 : #include "RAIIObjectsForParser.h"
      17                 : #include "clang/Parse/DeclSpec.h"
      18                 : #include "clang/Parse/Scope.h"
      19                 : #include "clang/Basic/Diagnostic.h"
      20                 : #include "clang/Basic/PrettyStackTrace.h"
      21                 : #include "clang/Basic/SourceManager.h"
      22                 : using namespace clang;
      23                 : 
      24                 : //===----------------------------------------------------------------------===//
      25                 : // C99 6.8: Statements and Blocks.
      26                 : //===----------------------------------------------------------------------===//
      27                 : 
      28                 : /// ParseStatementOrDeclaration - Read 'statement' or 'declaration'.
      29                 : ///       StatementOrDeclaration:
      30                 : ///         statement
      31                 : ///         declaration
      32                 : ///
      33                 : ///       statement:
      34                 : ///         labeled-statement
      35                 : ///         compound-statement
      36                 : ///         expression-statement
      37                 : ///         selection-statement
      38                 : ///         iteration-statement
      39                 : ///         jump-statement
      40                 : /// [C++]   declaration-statement
      41                 : /// [C++]   try-block
      42                 : /// [OBC]   objc-throw-statement
      43                 : /// [OBC]   objc-try-catch-statement
      44                 : /// [OBC]   objc-synchronized-statement
      45                 : /// [GNU]   asm-statement
      46                 : /// [OMP]   openmp-construct             [TODO]
      47                 : ///
      48                 : ///       labeled-statement:
      49                 : ///         identifier ':' statement
      50                 : ///         'case' constant-expression ':' statement
      51                 : ///         'default' ':' statement
      52                 : ///
      53                 : ///       selection-statement:
      54                 : ///         if-statement
      55                 : ///         switch-statement
      56                 : ///
      57                 : ///       iteration-statement:
      58                 : ///         while-statement
      59                 : ///         do-statement
      60                 : ///         for-statement
      61                 : ///
      62                 : ///       expression-statement:
      63                 : ///         expression[opt] ';'
      64                 : ///
      65                 : ///       jump-statement:
      66                 : ///         'goto' identifier ';'
      67                 : ///         'continue' ';'
      68                 : ///         'break' ';'
      69                 : ///         'return' expression[opt] ';'
      70                 : /// [GNU]   'goto' '*' expression ';'
      71                 : ///
      72                 : /// [OBC] objc-throw-statement:
      73                 : /// [OBC]   '@' 'throw' expression ';'
      74                 : /// [OBC]   '@' 'throw' ';'
      75                 : ///
      76                 : Parser::OwningStmtResult
      77            25500: Parser::ParseStatementOrDeclaration(bool OnlyStatement) {
      78            25500:   const char *SemiError = 0;
      79            25500:   OwningStmtResult Res(Actions);
      80                 : 
      81            25500:   CXX0XAttributeList Attr;
                      779: branch 1 taken
                    24721: branch 2 taken
                       15: branch 4 taken
                      764: branch 5 taken
                       15: branch 6 taken
                    25485: branch 7 taken
      82            25500:   if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
      83               15:     Attr = ParseCXX0XAttributes();
      84                 : 
      85                 :   // Cases in this switch statement should fall through if the parser expects
      86                 :   // the token to end in a semicolon (in which case SemiError should be set),
      87                 :   // or they directly 'return;' if not.
      88            25500:   tok::TokenKind Kind  = Tok.getKind();
      89            25500:   SourceLocation AtLoc;
                      118: branch 0 taken
                        5: branch 1 taken
                     8476: branch 2 taken
                     7877: branch 3 taken
                      258: branch 4 taken
                       53: branch 5 taken
                     1135: branch 6 taken
                      264: branch 7 taken
                     1559: branch 8 taken
                      139: branch 9 taken
                      173: branch 10 taken
                       74: branch 11 taken
                      284: branch 12 taken
                      158: branch 13 taken
                       32: branch 14 taken
                      265: branch 15 taken
                     4502: branch 16 taken
                      108: branch 17 taken
                       20: branch 18 taken
      90            25500:   switch (Kind) {
      91                 :   case tok::at: // May be a @try or @throw statement
      92                 :     {
      93              118:       AtLoc = ConsumeToken();  // consume @
      94              118:       return ParseObjCAtStatement(AtLoc);
      95                 :     }
      96                 : 
      97                 :   case tok::code_completion:
      98                5:     Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Statement);
      99                5:     ConsumeToken();
     100                5:     return ParseStatementOrDeclaration(OnlyStatement);
     101                 :       
     102                 :   case tok::identifier:
                      151: branch 2 taken
                     8325: branch 3 taken
     103             8476:     if (NextToken().is(tok::colon)) { // C99 6.8.1: labeled-statement
     104                 :       // identifier ':' statement
     105              151:       return ParseLabeledStatement(Attr.AttrList);
     106                 :     }
     107                 :     // PASS THROUGH.
     108                 : 
     109                 :   default: {
                    11236: branch 1 taken
                     4966: branch 2 taken
                    10488: branch 3 taken
                      748: branch 4 taken
                     7091: branch 6 taken
                     8363: branch 7 taken
                     7091: branch 8 taken
                     9111: branch 9 taken
     110            16202:     if ((getLang().CPlusPlus || !OnlyStatement) && isDeclarationStatement()) {
     111             7091:       SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
     112                 :       DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, DeclEnd,
     113             7091:                                              Attr);
     114             7091:       return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd);
     115                 :     }
     116                 : 
                        0: branch 1 not taken
                     9111: branch 2 taken
     117             9111:     if (Tok.is(tok::r_brace)) {
     118                0:       Diag(Tok, diag::err_expected_statement);
     119                0:       return StmtError();
     120                 :     }
     121                 : 
     122                 :     // FIXME: Use the attributes
     123                 :     // expression[opt] ';'
     124             9111:     OwningExprResult Expr(ParseExpression());
                      637: branch 1 taken
                     8474: branch 2 taken
     125             9111:     if (Expr.isInvalid()) {
     126                 :       // If the expression is invalid, skip ahead to the next semicolon.  Not
     127                 :       // doing this opens us up to the possibility of infinite loops if
     128                 :       // ParseExpression does not consume any tokens.
     129              637:       SkipUntil(tok::semi);
     130              637:       return StmtError();
     131                 :     }
     132                 :     // Otherwise, eat the semicolon.
     133             8474:     ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
     134             8474:     return Actions.ActOnExprStmt(Actions.MakeFullExpr(Expr));
     135                 :   }
     136                 : 
     137                 :   case tok::kw_case:                // C99 6.8.1: labeled-statement
     138              258:     return ParseCaseStatement(Attr.AttrList);
     139                 :   case tok::kw_default:             // C99 6.8.1: labeled-statement
     140               53:     return ParseDefaultStatement(Attr.AttrList);
     141                 : 
     142                 :   case tok::l_brace:                // C99 6.8.2: compound-statement
     143             1135:     return ParseCompoundStatement(Attr.AttrList);
     144                 :   case tok::semi:                   // C99 6.8.3p3: expression[opt] ';'
     145              264:     return Actions.ActOnNullStmt(ConsumeToken());
     146                 : 
     147                 :   case tok::kw_if:                  // C99 6.8.4.1: if-statement
     148             1559:     return ParseIfStatement(Attr.AttrList);
     149                 :   case tok::kw_switch:              // C99 6.8.4.2: switch-statement
     150              139:     return ParseSwitchStatement(Attr.AttrList);
     151                 : 
     152                 :   case tok::kw_while:               // C99 6.8.5.1: while-statement
     153              173:     return ParseWhileStatement(Attr.AttrList);
     154                 :   case tok::kw_do:                  // C99 6.8.5.2: do-statement
     155               74:     Res = ParseDoStatement(Attr.AttrList);
     156               74:     SemiError = "do/while";
     157               74:     break;
     158                 :   case tok::kw_for:                 // C99 6.8.5.3: for-statement
     159              284:     return ParseForStatement(Attr.AttrList);
     160                 : 
     161                 :   case tok::kw_goto:                // C99 6.8.6.1: goto-statement
     162              158:     Res = ParseGotoStatement(Attr.AttrList);
     163              158:     SemiError = "goto";
     164              158:     break;
     165                 :   case tok::kw_continue:            // C99 6.8.6.2: continue-statement
     166               32:     Res = ParseContinueStatement(Attr.AttrList);
     167               32:     SemiError = "continue";
     168               32:     break;
     169                 :   case tok::kw_break:               // C99 6.8.6.3: break-statement
     170              265:     Res = ParseBreakStatement(Attr.AttrList);
     171              265:     SemiError = "break";
     172              265:     break;
     173                 :   case tok::kw_return:              // C99 6.8.6.4: return-statement
     174             4502:     Res = ParseReturnStatement(Attr.AttrList);
     175             4502:     SemiError = "return";
     176             4502:     break;
     177                 : 
     178                 :   case tok::kw_asm: {
                        0: branch 0 not taken
                      108: branch 1 taken
     179              108:     if (Attr.HasAttr)
     180                 :       Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
     181                0:         << Attr.Range;
     182              108:     bool msAsm = false;
     183              108:     Res = ParseAsmStatement(msAsm);
                        5: branch 0 taken
                      103: branch 1 taken
     184              108:     if (msAsm) return move(Res);
     185              103:     SemiError = "asm";
     186              103:     break;
     187                 :   }
     188                 : 
     189                 :   case tok::kw_try:                 // C++ 15: try-block
     190               20:     return ParseCXXTryBlock(Attr.AttrList);
     191                 :   }
     192                 : 
     193                 :   // If we reached this code, the statement must end in a semicolon.
                     5129: branch 1 taken
                        5: branch 2 taken
     194             5134:   if (Tok.is(tok::semi)) {
     195             5129:     ConsumeToken();
                        1: branch 1 taken
                        4: branch 2 taken
     196                5:   } else if (!Res.isInvalid()) {
     197                 :     // If the result was valid, then we do want to diagnose this.  Use
     198                 :     // ExpectAndConsume to emit the diagnostic, even though we know it won't
     199                 :     // succeed.
     200                1:     ExpectAndConsume(tok::semi, diag::err_expected_semi_after_stmt, SemiError);
     201                 :     // Skip until we see a } or ;, but don't eat it.
     202                1:     SkipUntil(tok::r_brace, true, true);
     203                 :   }
     204                 : 
     205             5134:   return move(Res);
     206                 : }
     207                 : 
     208                 : /// ParseLabeledStatement - We have an identifier and a ':' after it.
     209                 : ///
     210                 : ///       labeled-statement:
     211                 : ///         identifier ':' statement
     212                 : /// [GNU]   identifier ':' attributes[opt] statement
     213                 : ///
     214              151: Parser::OwningStmtResult Parser::ParseLabeledStatement(AttributeList *Attr) {
     215                 :   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
                      151: branch 1 taken
                        0: branch 2 not taken
                      151: branch 4 taken
                        0: branch 5 not taken
     216              151:          "Not an identifier!");
     217                 : 
     218              151:   Token IdentTok = Tok;  // Save the whole token.
     219              151:   ConsumeToken();  // eat the identifier.
     220                 : 
                      151: branch 1 taken
                        0: branch 2 not taken
     221              151:   assert(Tok.is(tok::colon) && "Not a label!");
     222                 : 
     223                 :   // identifier ':' statement
     224              151:   SourceLocation ColonLoc = ConsumeToken();
     225                 : 
     226                 :   // Read label attributes, if present.
                        0: branch 1 not taken
                      151: branch 2 taken
     227              151:   if (Tok.is(tok::kw___attribute))
     228                0:     Attr = addAttributeLists(Attr, ParseGNUAttributes());
     229                 : 
     230              151:   OwningStmtResult SubStmt(ParseStatement());
     231                 : 
     232                 :   // Broken substmt shouldn't prevent the label from being added to the AST.
                        4: branch 1 taken
                      147: branch 2 taken
     233              151:   if (SubStmt.isInvalid())
     234                4:     SubStmt = Actions.ActOnNullStmt(ColonLoc);
     235                 : 
     236                 :   return Actions.ActOnLabelStmt(IdentTok.getLocation(),
     237                 :                                 IdentTok.getIdentifierInfo(),
     238              151:                                 ColonLoc, move(SubStmt));
     239                 : }
     240                 : 
     241                 : /// ParseCaseStatement
     242                 : ///       labeled-statement:
     243                 : ///         'case' constant-expression ':' statement
     244                 : /// [GNU]   'case' constant-expression '...' constant-expression ':' statement
     245                 : ///
     246              258: Parser::OwningStmtResult Parser::ParseCaseStatement(AttributeList *Attr) {
                      258: branch 1 taken
                        0: branch 2 not taken
     247              258:   assert(Tok.is(tok::kw_case) && "Not a case stmt!");
     248                 :   // FIXME: Use attributes?
     249                 : 
     250                 :   // It is very very common for code to contain many case statements recursively
     251                 :   // nested, as in (but usually without indentation):
     252                 :   //  case 1:
     253                 :   //    case 2:
     254                 :   //      case 3:
     255                 :   //         case 4:
     256                 :   //           case 5: etc.
     257                 :   //
     258                 :   // Parsing this naively works, but is both inefficient and can cause us to run
     259                 :   // out of stack space in our recursive descent parser.  As a special case,
     260                 :   // flatten this recursion into an iterative loop.  This is complex and gross,
     261                 :   // but all the grossness is constrained to ParseCaseStatement (and some
     262                 :   // wierdness in the actions), so this is just local grossness :).
     263                 : 
     264                 :   // TopLevelCase - This is the highest level we have parsed.  'case 1' in the
     265                 :   // example above.
     266              258:   OwningStmtResult TopLevelCase(Actions, true);
     267                 : 
     268                 :   // DeepestParsedCaseStmt - This is the deepest statement we have parsed, which
     269                 :   // gets updated each time a new case is parsed, and whose body is unset so
     270                 :   // far.  When parsing 'case 4', this is the 'case 3' node.
     271              258:   StmtTy *DeepestParsedCaseStmt = 0;
     272                 : 
     273                 :   // While we have case statements, eat and stack them.
                       47: branch 1 taken
                      247: branch 2 taken
     274              294:   do {
     275              305:     SourceLocation CaseLoc = ConsumeToken();  // eat the 'case'.
     276                 : 
                        5: branch 1 taken
                      300: branch 2 taken
     277              305:     if (Tok.is(tok::code_completion)) {
     278                5:       Actions.CodeCompleteCase(CurScope);
     279                5:       ConsumeToken();
     280                 :     }
     281                 :     
     282                 :     /// We don't want to treat 'case x : y' as a potential typo for 'case x::y'.
     283                 :     /// Disable this form of error recovery while we're parsing the case
     284                 :     /// expression.
     285              305:     ColonProtectionRAIIObject ColonProtection(*this);
     286                 :     
     287              305:     OwningExprResult LHS(ParseConstantExpression());
                        5: branch 1 taken
                      300: branch 2 taken
     288              305:     if (LHS.isInvalid()) {
     289                5:       SkipUntil(tok::colon);
     290                5:       return StmtError();
     291                 :     }
     292                 : 
     293                 :     // GNU case range extension.
     294              300:     SourceLocation DotDotDotLoc;
     295              300:     OwningExprResult RHS(Actions);
                       44: branch 1 taken
                      256: branch 2 taken
     296              300:     if (Tok.is(tok::ellipsis)) {
     297               44:       Diag(Tok, diag::ext_gnu_case_range);
     298               44:       DotDotDotLoc = ConsumeToken();
     299                 : 
     300               44:       RHS = ParseConstantExpression();
                        0: branch 1 not taken
                       44: branch 2 taken
     301               44:       if (RHS.isInvalid()) {
     302                0:         SkipUntil(tok::colon);
     303                0:         return StmtError();
     304                 :       }
     305                 :     }
     306                 :     
     307              300:     ColonProtection.restore();
     308                 : 
                        0: branch 1 not taken
                      300: branch 2 taken
     309              300:     if (Tok.isNot(tok::colon)) {
     310                0:       Diag(Tok, diag::err_expected_colon_after) << "'case'";
     311                0:       SkipUntil(tok::colon);
     312                0:       return StmtError();
     313                 :     }
     314                 : 
     315              300:     SourceLocation ColonLoc = ConsumeToken();
     316                 : 
     317                 :     OwningStmtResult Case =
     318                 :       Actions.ActOnCaseStmt(CaseLoc, move(LHS), DotDotDotLoc,
     319              300:                             move(RHS), ColonLoc);
     320                 : 
     321                 :     // If we had a sema error parsing this case, then just ignore it and
     322                 :     // continue parsing the sub-stmt.
                        6: branch 1 taken
                      294: branch 2 taken
     323              300:     if (Case.isInvalid()) {
                        6: branch 1 taken
                        0: branch 2 not taken
     324                6:       if (TopLevelCase.isInvalid())  // No parsed case stmts.
     325                6:         return ParseStatement();
     326                 :       // Otherwise, just don't add it as a nested case.
     327                 :     } else {
     328                 :       // If this is the first case statement we parsed, it becomes TopLevelCase.
     329                 :       // Otherwise we link it into the current chain.
     330              294:       StmtTy *NextDeepest = Case.get();
                      247: branch 1 taken
                       47: branch 2 taken
     331              294:       if (TopLevelCase.isInvalid())
     332              247:         TopLevelCase = move(Case);
     333                 :       else
     334               47:         Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(Case));
     335              294:       DeepestParsedCaseStmt = NextDeepest;
                      294: branch 1 taken
                        6: branch 2 taken
                      294: branch 4 taken
                        6: branch 5 taken
                      294: branch 7 taken
                       11: branch 8 taken
                      294: branch 10 taken
                       11: branch 11 taken
     336              300:     }
     337                 : 
     338                 :     // Handle all case statements.
     339                 :   } while (Tok.is(tok::kw_case));
     340                 : 
                      247: branch 1 taken
                        0: branch 2 not taken
     341              247:   assert(!TopLevelCase.isInvalid() && "Should have parsed at least one case!");
     342                 : 
     343                 :   // If we found a non-case statement, start by parsing it.
     344              247:   OwningStmtResult SubStmt(Actions);
     345                 : 
                      247: branch 1 taken
                        0: branch 2 not taken
     346              247:   if (Tok.isNot(tok::r_brace)) {
     347              247:     SubStmt = ParseStatement();
     348                 :   } else {
     349                 :     // Nicely diagnose the common error "switch (X) { case 4: }", which is
     350                 :     // not valid.
     351                 :     // FIXME: add insertion hint.
     352                0:     Diag(Tok, diag::err_label_end_of_compound_statement);
     353                0:     SubStmt = true;
     354                 :   }
     355                 : 
     356                 :   // Broken sub-stmt shouldn't prevent forming the case statement properly.
                        0: branch 1 not taken
                      247: branch 2 taken
     357              247:   if (SubStmt.isInvalid())
     358                0:     SubStmt = Actions.ActOnNullStmt(SourceLocation());
     359                 : 
     360                 :   // Install the body into the most deeply-nested case.
     361              247:   Actions.ActOnCaseStmtBody(DeepestParsedCaseStmt, move(SubStmt));
     362                 : 
     363                 :   // Return the top level parsed statement tree.
     364              247:   return move(TopLevelCase);
     365                 : }
     366                 : 
     367                 : /// ParseDefaultStatement
     368                 : ///       labeled-statement:
     369                 : ///         'default' ':' statement
     370                 : /// Note that this does not parse the 'statement' at the end.
     371                 : ///
     372               53: Parser::OwningStmtResult Parser::ParseDefaultStatement(AttributeList *Attr) {
     373                 :   //FIXME: Use attributes?
                       53: branch 1 taken
                        0: branch 2 not taken
     374               53:   assert(Tok.is(tok::kw_default) && "Not a default stmt!");
     375               53:   SourceLocation DefaultLoc = ConsumeToken();  // eat the 'default'.
     376                 : 
                        0: branch 1 not taken
                       53: branch 2 taken
     377               53:   if (Tok.isNot(tok::colon)) {
     378                0:     Diag(Tok, diag::err_expected_colon_after) << "'default'";
     379                0:     SkipUntil(tok::colon);
     380                0:     return StmtError();
     381                 :   }
     382                 : 
     383               53:   SourceLocation ColonLoc = ConsumeToken();
     384                 : 
     385                 :   // Diagnose the common error "switch (X) {... default: }", which is not valid.
                        0: branch 1 not taken
                       53: branch 2 taken
     386               53:   if (Tok.is(tok::r_brace)) {
     387                0:     Diag(Tok, diag::err_label_end_of_compound_statement);
     388                0:     return StmtError();
     389                 :   }
     390                 : 
     391               53:   OwningStmtResult SubStmt(ParseStatement());
                        0: branch 1 not taken
                       53: branch 2 taken
     392               53:   if (SubStmt.isInvalid())
     393                0:     return StmtError();
     394                 : 
     395                 :   return Actions.ActOnDefaultStmt(DefaultLoc, ColonLoc,
     396               53:                                   move(SubStmt), CurScope);
     397                 : }
     398                 : 
     399                 : 
     400                 : /// ParseCompoundStatement - Parse a "{}" block.
     401                 : ///
     402                 : ///       compound-statement: [C99 6.8.2]
     403                 : ///         { block-item-list[opt] }
     404                 : /// [GNU]   { label-declarations block-item-list } [TODO]
     405                 : ///
     406                 : ///       block-item-list:
     407                 : ///         block-item
     408                 : ///         block-item-list block-item
     409                 : ///
     410                 : ///       block-item:
     411                 : ///         declaration
     412                 : /// [GNU]   '__extension__' declaration
     413                 : ///         statement
     414                 : /// [OMP]   openmp-directive            [TODO]
     415                 : ///
     416                 : /// [GNU] label-declarations:
     417                 : /// [GNU]   label-declaration
     418                 : /// [GNU]   label-declarations label-declaration
     419                 : ///
     420                 : /// [GNU] label-declaration:
     421                 : /// [GNU]   '__label__' identifier-list ';'
     422                 : ///
     423                 : /// [OMP] openmp-directive:             [TODO]
     424                 : /// [OMP]   barrier-directive
     425                 : /// [OMP]   flush-directive
     426                 : ///
     427                 : Parser::OwningStmtResult Parser::ParseCompoundStatement(AttributeList *Attr,
     428             1265:                                                         bool isStmtExpr) {
     429                 :   //FIXME: Use attributes?
                     1265: branch 1 taken
                        0: branch 2 not taken
     430             1265:   assert(Tok.is(tok::l_brace) && "Not a compount stmt!");
     431                 : 
     432                 :   // Enter a scope to hold everything within the compound stmt.  Compound
     433                 :   // statements can always hold declarations.
     434             1265:   ParseScope CompoundScope(this, Scope::DeclScope);
     435                 : 
     436                 :   // Parse the statements in the body.
     437             1265:   return ParseCompoundStatementBody(isStmtExpr);
     438                 : }
     439                 : 
     440                 : 
     441                 : /// ParseCompoundStatementBody - Parse a sequence of statements and invoke the
     442                 : /// ActOnCompoundStmt action.  This expects the '{' to be the current token, and
     443                 : /// consume the '}' at the end of the block.  It does not manipulate the scope
     444                 : /// stack.
     445            10872: Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) {
     446                 :   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(),
     447                 :                                 Tok.getLocation(),
     448            10872:                                 "in compound statement ('{}')");
     449                 : 
     450            10872:   SourceLocation LBraceLoc = ConsumeBrace();  // eat the '{'.
     451                 : 
     452                 :   // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension.  These are
     453                 :   // only allowed at the start of a compound stmt regardless of the language.
     454                 : 
     455                 :   typedef StmtVector StmtsTy;
     456            10872:   StmtsTy Stmts(Actions);
                    22612: branch 1 taken
                        2: branch 2 taken
                    22674: branch 4 taken
                    10812: branch 5 taken
                    22614: branch 7 taken
                       60: branch 8 taken
                    22614: branch 9 taken
                    10872: branch 10 taken
     457            66972:   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     458            22614:     OwningStmtResult R(Actions);
                    22605: branch 1 taken
                        9: branch 2 taken
     459            22614:     if (Tok.isNot(tok::kw___extension__)) {
     460            22605:       R = ParseStatementOrDeclaration(false);
     461                 :     } else {
     462                 :       // __extension__ can start declarations and it can also be a unary
     463                 :       // operator for expressions.  Consume multiple __extension__ markers here
     464                 :       // until we can determine which is which.
     465                 :       // FIXME: This loses extension expressions in the AST!
     466                9:       SourceLocation ExtLoc = ConsumeToken();
                        0: branch 1 not taken
                        9: branch 2 taken
     467               18:       while (Tok.is(tok::kw___extension__))
     468                0:         ConsumeToken();
     469                 : 
     470                9:       CXX0XAttributeList Attr;
                        0: branch 1 not taken
                        9: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        9: branch 7 taken
     471                9:       if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
     472                0:         Attr = ParseCXX0XAttributes();
     473                 : 
     474                 :       // If this is the start of a declaration, parse it as such.
                        3: branch 1 taken
                        6: branch 2 taken
     475                9:       if (isDeclarationStatement()) {
     476                 :         // __extension__ silences extension warnings in the subdeclaration.
     477                 :         // FIXME: Save the __extension__ on the decl as a node somehow?
     478                3:         ExtensionRAIIObject O(Diags);
     479                 : 
     480                3:         SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
     481                 :         DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd,
     482                3:                                               Attr);
     483                3:         R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd);
     484                 :       } else {
     485                 :         // Otherwise this was a unary __extension__ marker.
     486                6:         OwningExprResult Res(ParseExpressionWithLeadingExtension(ExtLoc));
     487                 : 
                        2: branch 1 taken
                        4: branch 2 taken
     488                6:         if (Res.isInvalid()) {
     489                2:           SkipUntil(tok::semi);
     490                2:           continue;
     491                 :         }
     492                 : 
     493                 :         // FIXME: Use attributes?
     494                 :         // Eat the semicolon at the end of stmt and convert the expr into a
     495                 :         // statement.
     496                4:         ExpectAndConsume(tok::semi, diag::err_expected_semi_after_expr);
                        4: branch 7 taken
                        2: branch 8 taken
     497                4:         R = Actions.ActOnExprStmt(Actions.MakeFullExpr(Res));
     498                 :       }
     499                 :     }
     500                 : 
                    21471: branch 1 taken
                     1141: branch 2 taken
     501            22612:     if (R.isUsable())
     502            21471:       Stmts.push_back(R.release());
     503                 :   }
     504                 : 
     505                 :   // We broke out of the while loop because we found a '}' or EOF.
                       60: branch 1 taken
                    10812: branch 2 taken
     506            10872:   if (Tok.isNot(tok::r_brace)) {
     507               60:     Diag(Tok, diag::err_expected_rbrace);
     508               60:     return StmtError();
     509                 :   }
     510                 : 
     511            10812:   SourceLocation RBraceLoc = ConsumeBrace();
     512                 :   return Actions.ActOnCompoundStmt(LBraceLoc, RBraceLoc, move_arg(Stmts),
     513            10812:                                    isStmtExpr);
     514                 : }
     515                 : 
     516                 : /// ParseParenExprOrCondition:
     517                 : /// [C  ]     '(' expression ')'
     518                 : /// [C++]     '(' condition ')'       [not allowed if OnlyAllowCondition=true]
     519                 : ///
     520                 : /// This function parses and performs error recovery on the specified condition
     521                 : /// or expression (depending on whether we're in C++ or C mode).  This function
     522                 : /// goes out of its way to recover well.  It returns true if there was a parser
     523                 : /// error (the right paren couldn't be found), which indicates that the caller
     524                 : /// should try to recover harder.  It returns false if the condition is
     525                 : /// successfully parsed.  Note that a successful parse can still have semantic
     526                 : /// errors in the condition.
     527                 : bool Parser::ParseParenExprOrCondition(OwningExprResult &ExprResult,
     528             1871:                                        DeclPtrTy &DeclResult) {
     529             1871:   bool ParseError = false;
     530                 :   
     531             1871:   SourceLocation LParenLoc = ConsumeParen();
                      292: branch 1 taken
                     1579: branch 2 taken
     532             1871:   if (getLang().CPlusPlus) 
     533              292:     ParseError = ParseCXXCondition(ExprResult, DeclResult);
     534                 :   else {
     535             1579:     ExprResult = ParseExpression();
     536             1579:     DeclResult = DeclPtrTy();
     537                 :   }
     538                 : 
     539                 :   // If the parser was confused by the condition and we don't have a ')', try to
     540                 :   // recover by skipping ahead to a semi and bailing out.  If condexp is
     541                 :   // semantically invalid but we have well formed code, keep going.
                       63: branch 1 taken
                     1808: branch 2 taken
                       17: branch 4 taken
                       46: branch 5 taken
                        4: branch 7 taken
                       13: branch 8 taken
                        4: branch 9 taken
                     1867: branch 10 taken
     542             1871:   if (ExprResult.isInvalid() && !DeclResult.get() && Tok.isNot(tok::r_paren)) {
     543                4:     SkipUntil(tok::semi);
     544                 :     // Skipping may have stopped if it found the containing ')'.  If so, we can
     545                 :     // continue parsing the if statement.
                        2: branch 1 taken
                        2: branch 2 taken
     546                4:     if (Tok.isNot(tok::r_paren))
     547                2:       return true;
     548                 :   }
     549                 : 
     550                 :   // Otherwise the condition is valid or the rparen is present.
     551             1869:   MatchRHSPunctuation(tok::r_paren, LParenLoc);
     552             1869:   return false;
     553                 : }
     554                 : 
     555                 : 
     556                 : /// ParseIfStatement
     557                 : ///       if-statement: [C99 6.8.4.1]
     558                 : ///         'if' '(' expression ')' statement
     559                 : ///         'if' '(' expression ')' statement 'else' statement
     560                 : /// [C++]   'if' '(' condition ')' statement
     561                 : /// [C++]   'if' '(' condition ')' statement 'else' statement
     562                 : ///
     563             1559: Parser::OwningStmtResult Parser::ParseIfStatement(AttributeList *Attr) {
     564                 :   // FIXME: Use attributes?
                     1559: branch 1 taken
                        0: branch 2 not taken
     565             1559:   assert(Tok.is(tok::kw_if) && "Not an if stmt!");
     566             1559:   SourceLocation IfLoc = ConsumeToken();  // eat the 'if'.
     567                 : 
                        0: branch 1 not taken
                     1559: branch 2 taken
     568             1559:   if (Tok.isNot(tok::l_paren)) {
     569                0:     Diag(Tok, diag::err_expected_lparen_after) << "if";
     570                0:     SkipUntil(tok::semi);
     571                0:     return StmtError();
     572                 :   }
     573                 : 
                      219: branch 1 taken
                     1340: branch 2 taken
                      217: branch 4 taken
                        2: branch 5 taken
     574             1559:   bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
     575                 : 
     576                 :   // C99 6.8.4p3 - In C99, the if statement is a block.  This is not
     577                 :   // the case for C90.
     578                 :   //
     579                 :   // C++ 6.4p3:
     580                 :   // A name introduced by a declaration in a condition is in scope from its
     581                 :   // point of declaration until the end of the substatements controlled by the
     582                 :   // condition.
     583                 :   // C++ 3.3.2p4:
     584                 :   // Names declared in the for-init-statement, and in the condition of if,
     585                 :   // while, for, and switch statements are local to the if, while, for, or
     586                 :   // switch statement (including the controlled statement).
     587                 :   //
     588             1559:   ParseScope IfScope(this, Scope::DeclScope | Scope::ControlScope, C99orCXX);
     589                 : 
     590                 :   // Parse the condition.
     591             1559:   OwningExprResult CondExp(Actions);
     592             1559:   DeclPtrTy CondVar;
                        0: branch 1 not taken
                     1559: branch 2 taken
     593             1559:   if (ParseParenExprOrCondition(CondExp, CondVar))
     594                0:     return StmtError();
     595                 : 
     596             1559:   FullExprArg FullCondExp(Actions.MakeFullExpr(CondExp));
     597                 : 
     598                 :   // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
     599                 :   // there is no compound stmt.  C90 does not have this clause.  We only do this
     600                 :   // if the body isn't a compound statement to avoid push/pop in common cases.
     601                 :   //
     602                 :   // C++ 6.4p1:
     603                 :   // The substatement in a selection-statement (each substatement, in the else
     604                 :   // form of the if statement) implicitly defines a local scope.
     605                 :   //
     606                 :   // For C++ we create a scope for the condition and a new scope for
     607                 :   // substatements because:
     608                 :   // -When the 'then' scope exits, we want the condition declaration to still be
     609                 :   //    active for the 'else' scope too.
     610                 :   // -Sema will detect name clashes by considering declarations of a
     611                 :   //    'ControlScope' as part of its direct subscope.
     612                 :   // -If we wanted the condition and substatement to be in the same scope, we
     613                 :   //    would have to notify ParseStatement not to create a new scope. It's
     614                 :   //    simpler to let it create a new scope.
     615                 :   //
     616                 :   ParseScope InnerScope(this, Scope::DeclScope,
                     1557: branch 0 taken
                        2: branch 1 taken
                     1054: branch 3 taken
                      503: branch 4 taken
     617             1559:                         C99orCXX && Tok.isNot(tok::l_brace));
     618                 : 
     619                 :   // Read the 'then' stmt.
     620             1559:   SourceLocation ThenStmtLoc = Tok.getLocation();
     621             1559:   OwningStmtResult ThenStmt(ParseStatement());
     622                 : 
     623                 :   // Pop the 'if' scope if needed.
     624             1559:   InnerScope.Exit();
     625                 : 
     626                 :   // If it has an else, parse it.
     627             1559:   SourceLocation ElseLoc;
     628             1559:   SourceLocation ElseStmtLoc;
     629             1559:   OwningStmtResult ElseStmt(Actions);
     630                 : 
                      206: branch 1 taken
                     1353: branch 2 taken
     631             1559:   if (Tok.is(tok::kw_else)) {
     632              206:     ElseLoc = ConsumeToken();
     633                 : 
     634                 :     // C99 6.8.4p3 - In C99, the body of the if statement is a scope, even if
     635                 :     // there is no compound stmt.  C90 does not have this clause.  We only do
     636                 :     // this if the body isn't a compound statement to avoid push/pop in common
     637                 :     // cases.
     638                 :     //
     639                 :     // C++ 6.4p1:
     640                 :     // The substatement in a selection-statement (each substatement, in the else
     641                 :     // form of the if statement) implicitly defines a local scope.
     642                 :     //
     643                 :     ParseScope InnerScope(this, Scope::DeclScope,
                      206: branch 0 taken
                        0: branch 1 not taken
                      158: branch 3 taken
                       48: branch 4 taken
     644              206:                           C99orCXX && Tok.isNot(tok::l_brace));
     645                 : 
     646              206:     bool WithinElse = CurScope->isWithinElse();
     647              206:     CurScope->setWithinElse(true);
     648              206:     ElseStmtLoc = Tok.getLocation();
     649              206:     ElseStmt = ParseStatement();
     650              206:     CurScope->setWithinElse(WithinElse);
     651                 : 
     652                 :     // Pop the 'else' scope if needed.
     653              206:     InnerScope.Exit();
     654                 :   }
     655                 : 
     656             1559:   IfScope.Exit();
     657                 : 
     658                 :   // If the condition was invalid, discard the if statement.  We could recover
     659                 :   // better by replacing it with a valid expr, but don't do that yet.
                       32: branch 1 taken
                     1527: branch 2 taken
                        9: branch 4 taken
                       23: branch 5 taken
                        9: branch 6 taken
                     1550: branch 7 taken
     660             1559:   if (CondExp.isInvalid() && !CondVar.get())
     661                9:     return StmtError();
     662                 : 
     663                 :   // If the then or else stmt is invalid and the other is valid (and present),
     664                 :   // make turn the invalid one into a null stmt to avoid dropping the other
     665                 :   // part.  If both are invalid, return error.
                        9: branch 1 taken
                     1541: branch 2 taken
                        6: branch 4 taken
                        3: branch 5 taken
                        6: branch 7 taken
                     1541: branch 8 taken
                        3: branch 10 taken
                        3: branch 11 taken
                        9: branch 13 taken
                     1535: branch 14 taken
                        0: branch 16 not taken
                        9: branch 17 taken
                        6: branch 18 taken
                     1544: branch 19 taken
     666             1550:   if ((ThenStmt.isInvalid() && ElseStmt.isInvalid()) ||
     667                 :       (ThenStmt.isInvalid() && ElseStmt.get() == 0) ||
     668                 :       (ThenStmt.get() == 0  && ElseStmt.isInvalid())) {
     669                 :     // Both invalid, or one is invalid and other is non-present: return error.
     670                6:     return StmtError();
     671                 :   }
     672                 : 
     673                 :   // Now if either are invalid, replace with a ';'.
                        3: branch 1 taken
                     1541: branch 2 taken
     674             1544:   if (ThenStmt.isInvalid())
     675                3:     ThenStmt = Actions.ActOnNullStmt(ThenStmtLoc);
                        4: branch 1 taken
                     1540: branch 2 taken
     676             1544:   if (ElseStmt.isInvalid())
     677                4:     ElseStmt = Actions.ActOnNullStmt(ElseStmtLoc);
     678                 : 
     679                 :   return Actions.ActOnIfStmt(IfLoc, FullCondExp, CondVar, move(ThenStmt),
     680             1544:                              ElseLoc, move(ElseStmt));
     681                 : }
     682                 : 
     683                 : /// ParseSwitchStatement
     684                 : ///       switch-statement:
     685                 : ///         'switch' '(' expression ')' statement
     686                 : /// [C++]   'switch' '(' condition ')' statement
     687              139: Parser::OwningStmtResult Parser::ParseSwitchStatement(AttributeList *Attr) {
     688                 :   // FIXME: Use attributes?
                      139: branch 1 taken
                        0: branch 2 not taken
     689              139:   assert(Tok.is(tok::kw_switch) && "Not a switch stmt!");
     690              139:   SourceLocation SwitchLoc = ConsumeToken();  // eat the 'switch'.
     691                 : 
                        0: branch 1 not taken
                      139: branch 2 taken
     692              139:   if (Tok.isNot(tok::l_paren)) {
     693                0:     Diag(Tok, diag::err_expected_lparen_after) << "switch";
     694                0:     SkipUntil(tok::semi);
     695                0:     return StmtError();
     696                 :   }
     697                 : 
                       34: branch 1 taken
                      105: branch 2 taken
                       34: branch 4 taken
                        0: branch 5 not taken
     698              139:   bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
     699                 : 
     700                 :   // C99 6.8.4p3 - In C99, the switch statement is a block.  This is
     701                 :   // not the case for C90.  Start the switch scope.
     702                 :   //
     703                 :   // C++ 6.4p3:
     704                 :   // A name introduced by a declaration in a condition is in scope from its
     705                 :   // point of declaration until the end of the substatements controlled by the
     706                 :   // condition.
     707                 :   // C++ 3.3.2p4:
     708                 :   // Names declared in the for-init-statement, and in the condition of if,
     709                 :   // while, for, and switch statements are local to the if, while, for, or
     710                 :   // switch statement (including the controlled statement).
     711                 :   //
     712              139:   unsigned ScopeFlags = Scope::BreakScope;
                      139: branch 0 taken
                        0: branch 1 not taken
     713              139:   if (C99orCXX)
     714              139:     ScopeFlags |= Scope::DeclScope | Scope::ControlScope;
     715              139:   ParseScope SwitchScope(this, ScopeFlags);
     716                 : 
     717                 :   // Parse the condition.
     718              139:   OwningExprResult Cond(Actions);
     719              139:   DeclPtrTy CondVar;
                        2: branch 1 taken
                      137: branch 2 taken
     720              139:   if (ParseParenExprOrCondition(Cond, CondVar))
     721                2:     return StmtError();
     722                 : 
     723              137:   FullExprArg FullCond(Actions.MakeFullExpr(Cond));
     724                 :   
     725              137:   OwningStmtResult Switch = Actions.ActOnStartOfSwitchStmt(FullCond, CondVar);
     726                 : 
     727                 :   // C99 6.8.4p3 - In C99, the body of the switch statement is a scope, even if
     728                 :   // there is no compound stmt.  C90 does not have this clause.  We only do this
     729                 :   // if the body isn't a compound statement to avoid push/pop in common cases.
     730                 :   //
     731                 :   // C++ 6.4p1:
     732                 :   // The substatement in a selection-statement (each substatement, in the else
     733                 :   // form of the if statement) implicitly defines a local scope.
     734                 :   //
     735                 :   // See comments in ParseIfStatement for why we create a scope for the
     736                 :   // condition and a new scope for substatement in C++.
     737                 :   //
     738                 :   ParseScope InnerScope(this, Scope::DeclScope,
                      137: branch 0 taken
                        0: branch 1 not taken
                        4: branch 3 taken
                      133: branch 4 taken
     739              137:                         C99orCXX && Tok.isNot(tok::l_brace));
     740                 : 
     741                 :   // Read the body statement.
     742              137:   OwningStmtResult Body(ParseStatement());
     743                 : 
     744                 :   // Pop the scopes.
     745              137:   InnerScope.Exit();
     746              137:   SwitchScope.Exit();
     747                 : 
                       10: branch 1 taken
                      127: branch 2 taken
                        3: branch 4 taken
                        7: branch 5 taken
                        3: branch 6 taken
                      134: branch 7 taken
     748              137:   if (Cond.isInvalid() && !CondVar.get()) {
     749                3:     Actions.ActOnSwitchBodyError(SwitchLoc, move(Switch), move(Body));
     750                3:     return StmtError();
     751                 :   }
     752                 : 
                        6: branch 1 taken
                      128: branch 2 taken
     753              134:   if (Body.isInvalid())
     754                 :     // FIXME: Remove the case statement list from the Switch statement.
     755                6:     Body = Actions.ActOnNullStmt(Tok.getLocation());
     756                 :   
     757              134:   return Actions.ActOnFinishSwitchStmt(SwitchLoc, move(Switch), move(Body));
     758                 : }
     759                 : 
     760                 : /// ParseWhileStatement
     761                 : ///       while-statement: [C99 6.8.5.1]
     762                 : ///         'while' '(' expression ')' statement
     763                 : /// [C++]   'while' '(' condition ')' statement
     764              173: Parser::OwningStmtResult Parser::ParseWhileStatement(AttributeList *Attr) {
     765                 :   // FIXME: Use attributes?
                      173: branch 1 taken
                        0: branch 2 not taken
     766              173:   assert(Tok.is(tok::kw_while) && "Not a while stmt!");
     767              173:   SourceLocation WhileLoc = Tok.getLocation();
     768              173:   ConsumeToken();  // eat the 'while'.
     769                 : 
                        0: branch 1 not taken
                      173: branch 2 taken
     770              173:   if (Tok.isNot(tok::l_paren)) {
     771                0:     Diag(Tok, diag::err_expected_lparen_after) << "while";
     772                0:     SkipUntil(tok::semi);
     773                0:     return StmtError();
     774                 :   }
     775                 : 
                       41: branch 1 taken
                      132: branch 2 taken
                       41: branch 4 taken
                        0: branch 5 not taken
     776              173:   bool C99orCXX = getLang().C99 || getLang().CPlusPlus;
     777                 : 
     778                 :   // C99 6.8.5p5 - In C99, the while statement is a block.  This is not
     779                 :   // the case for C90.  Start the loop scope.
     780                 :   //
     781                 :   // C++ 6.4p3:
     782                 :   // A name introduced by a declaration in a condition is in scope from its
     783                 :   // point of declaration until the end of the substatements controlled by the
     784                 :   // condition.
     785                 :   // C++ 3.3.2p4:
     786                 :   // Names declared in the for-init-statement, and in the condition of if,
     787                 :   // while, for, and switch statements are local to the if, while, for, or
     788                 :   // switch statement (including the controlled statement).
     789                 :   //
     790                 :   unsigned ScopeFlags;
                      173: branch 0 taken
                        0: branch 1 not taken
     791              173:   if (C99orCXX)
     792                 :     ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
     793              173:                  Scope::DeclScope  | Scope::ControlScope;
     794                 :   else
     795                0:     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
     796              173:   ParseScope WhileScope(this, ScopeFlags);
     797                 : 
     798                 :   // Parse the condition.
     799              173:   OwningExprResult Cond(Actions);
     800              173:   DeclPtrTy CondVar;
                        0: branch 1 not taken
                      173: branch 2 taken
     801              173:   if (ParseParenExprOrCondition(Cond, CondVar))
     802                0:     return StmtError();
     803                 : 
     804              173:   FullExprArg FullCond(Actions.MakeFullExpr(Cond));
     805                 : 
     806                 :   // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
     807                 :   // there is no compound stmt.  C90 does not have this clause.  We only do this
     808                 :   // if the body isn't a compound statement to avoid push/pop in common cases.
     809                 :   //
     810                 :   // C++ 6.5p2:
     811                 :   // The substatement in an iteration-statement implicitly defines a local scope
     812                 :   // which is entered and exited each time through the loop.
     813                 :   //
     814                 :   // See comments in ParseIfStatement for why we create a scope for the
     815                 :   // condition and a new scope for substatement in C++.
     816                 :   //
     817                 :   ParseScope InnerScope(this, Scope::DeclScope,
                      173: branch 0 taken
                        0: branch 1 not taken
                       32: branch 3 taken
                      141: branch 4 taken
     818              173:                         C99orCXX && Tok.isNot(tok::l_brace));
     819                 : 
     820                 :   // Read the body statement.
     821              173:   OwningStmtResult Body(ParseStatement());
     822                 : 
     823                 :   // Pop the body scope if needed.
     824              173:   InnerScope.Exit();
     825              173:   WhileScope.Exit();
     826                 : 
                       19: branch 1 taken
                      154: branch 2 taken
                       16: branch 4 taken
                        3: branch 5 taken
                        0: branch 7 not taken
                      170: branch 8 taken
                        3: branch 9 taken
                      170: branch 10 taken
     827              173:   if ((Cond.isInvalid() && !CondVar.get()) || Body.isInvalid())
     828                3:     return StmtError();
     829                 : 
     830              170:   return Actions.ActOnWhileStmt(WhileLoc, FullCond, CondVar, move(Body));
     831                 : }
     832                 : 
     833                 : /// ParseDoStatement
     834                 : ///       do-statement: [C99 6.8.5.2]
     835                 : ///         'do' statement 'while' '(' expression ')' ';'
     836                 : /// Note: this lets the caller parse the end ';'.
     837               74: Parser::OwningStmtResult Parser::ParseDoStatement(AttributeList *Attr) {
     838                 :   // FIXME: Use attributes?
                       74: branch 1 taken
                        0: branch 2 not taken
     839               74:   assert(Tok.is(tok::kw_do) && "Not a do stmt!");
     840               74:   SourceLocation DoLoc = ConsumeToken();  // eat the 'do'.
     841                 : 
     842                 :   // C99 6.8.5p5 - In C99, the do statement is a block.  This is not
     843                 :   // the case for C90.  Start the loop scope.
     844                 :   unsigned ScopeFlags;
                       59: branch 1 taken
                       15: branch 2 taken
     845               74:   if (getLang().C99)
     846               59:     ScopeFlags = Scope::BreakScope | Scope::ContinueScope | Scope::DeclScope;
     847                 :   else
     848               15:     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
     849                 : 
     850               74:   ParseScope DoScope(this, ScopeFlags);
     851                 : 
     852                 :   // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
     853                 :   // there is no compound stmt.  C90 does not have this clause. We only do this
     854                 :   // if the body isn't a compound statement to avoid push/pop in common cases.
     855                 :   //
     856                 :   // C++ 6.5p2:
     857                 :   // The substatement in an iteration-statement implicitly defines a local scope
     858                 :   // which is entered and exited each time through the loop.
     859                 :   //
     860                 :   ParseScope InnerScope(this, Scope::DeclScope,
     861                 :                         (getLang().C99 || getLang().CPlusPlus) &&
                       15: branch 1 taken
                       59: branch 2 taken
                       15: branch 4 taken
                        0: branch 5 not taken
                       10: branch 7 taken
                       64: branch 8 taken
     862               74:                         Tok.isNot(tok::l_brace));
     863                 : 
     864                 :   // Read the body statement.
     865               74:   OwningStmtResult Body(ParseStatement());
     866                 : 
     867                 :   // Pop the body scope if needed.
     868               74:   InnerScope.Exit();
     869                 : 
                        1: branch 1 taken
                       73: branch 2 taken
     870               74:   if (Tok.isNot(tok::kw_while)) {
                        0: branch 1 not taken
                        1: branch 2 taken
     871                1:     if (!Body.isInvalid()) {
     872                0:       Diag(Tok, diag::err_expected_while);
     873                0:       Diag(DoLoc, diag::note_matching) << "do";
     874                0:       SkipUntil(tok::semi, false, true);
     875                 :     }
     876                1:     return StmtError();
     877                 :   }
     878               73:   SourceLocation WhileLoc = ConsumeToken();
     879                 : 
                        0: branch 1 not taken
                       73: branch 2 taken
     880               73:   if (Tok.isNot(tok::l_paren)) {
     881                0:     Diag(Tok, diag::err_expected_lparen_after) << "do/while";
     882                0:     SkipUntil(tok::semi, false, true);
     883                0:     return StmtError();
     884                 :   }
     885                 : 
     886                 :   // Parse the parenthesized condition.
     887               73:   SourceLocation LPLoc = ConsumeParen();
     888               73:   OwningExprResult Cond = ParseExpression();
     889               73:   SourceLocation RPLoc = MatchRHSPunctuation(tok::r_paren, LPLoc);
     890               73:   DoScope.Exit();
     891                 : 
                       73: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                       73: branch 5 taken
                        0: branch 6 not taken
                       73: branch 7 taken
     892               73:   if (Cond.isInvalid() || Body.isInvalid())
     893                0:     return StmtError();
     894                 : 
     895                 :   return Actions.ActOnDoStmt(DoLoc, move(Body), WhileLoc, LPLoc,
     896               73:                              move(Cond), RPLoc);
     897                 : }
     898                 : 
     899                 : /// ParseForStatement
     900                 : ///       for-statement: [C99 6.8.5.3]
     901                 : ///         'for' '(' expr[opt] ';' expr[opt] ';' expr[opt] ')' statement
     902                 : ///         'for' '(' declaration expr[opt] ';' expr[opt] ')' statement
     903                 : /// [C++]   'for' '(' for-init-statement condition[opt] ';' expression[opt] ')'
     904                 : /// [C++]       statement
     905                 : /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement
     906                 : /// [OBJC2] 'for' '(' expr 'in' expr ')' statement
     907                 : ///
     908                 : /// [C++] for-init-statement:
     909                 : /// [C++]   expression-statement
     910                 : /// [C++]   simple-declaration
     911                 : ///
     912              284: Parser::OwningStmtResult Parser::ParseForStatement(AttributeList *Attr) {
     913                 :   // FIXME: Use attributes?
                      284: branch 1 taken
                        0: branch 2 not taken
     914              284:   assert(Tok.is(tok::kw_for) && "Not a for stmt!");
     915              284:   SourceLocation ForLoc = ConsumeToken();  // eat the 'for'.
     916                 : 
                        0: branch 1 not taken
                      284: branch 2 taken
     917              284:   if (Tok.isNot(tok::l_paren)) {
     918                0:     Diag(Tok, diag::err_expected_lparen_after) << "for";
     919                0:     SkipUntil(tok::semi);
     920                0:     return StmtError();
     921                 :   }
     922                 : 
                       83: branch 1 taken
                      201: branch 2 taken
                        5: branch 4 taken
                       78: branch 5 taken
                        5: branch 7 taken
                        0: branch 8 not taken
     923              284:   bool C99orCXXorObjC = getLang().C99 || getLang().CPlusPlus || getLang().ObjC1;
     924                 : 
     925                 :   // C99 6.8.5p5 - In C99, the for statement is a block.  This is not
     926                 :   // the case for C90.  Start the loop scope.
     927                 :   //
     928                 :   // C++ 6.4p3:
     929                 :   // A name introduced by a declaration in a condition is in scope from its
     930                 :   // point of declaration until the end of the substatements controlled by the
     931                 :   // condition.
     932                 :   // C++ 3.3.2p4:
     933                 :   // Names declared in the for-init-statement, and in the condition of if,
     934                 :   // while, for, and switch statements are local to the if, while, for, or
     935                 :   // switch statement (including the controlled statement).
     936                 :   // C++ 6.5.3p1:
     937                 :   // Names declared in the for-init-statement are in the same declarative-region
     938                 :   // as those declared in the condition.
     939                 :   //
     940                 :   unsigned ScopeFlags;
                      284: branch 0 taken
                        0: branch 1 not taken
     941              284:   if (C99orCXXorObjC)
     942                 :     ScopeFlags = Scope::BreakScope | Scope::ContinueScope |
     943              284:                  Scope::DeclScope  | Scope::ControlScope;
     944                 :   else
     945                0:     ScopeFlags = Scope::BreakScope | Scope::ContinueScope;
     946                 : 
     947              284:   ParseScope ForScope(this, ScopeFlags);
     948                 : 
     949              284:   SourceLocation LParenLoc = ConsumeParen();
     950              284:   OwningExprResult Value(Actions);
     951                 : 
     952              284:   bool ForEach = false;
     953              284:   OwningStmtResult FirstPart(Actions);
     954              284:   OwningExprResult SecondPart(Actions), ThirdPart(Actions);
     955              284:   DeclPtrTy SecondVar;
     956                 :   
                        0: branch 1 not taken
                      284: branch 2 taken
     957              284:   if (Tok.is(tok::code_completion)) {
     958                 :     Actions.CodeCompleteOrdinaryName(CurScope, 
     959                 :                                      C99orCXXorObjC? Action::CCC_ForInit
                        0: branch 0 not taken
                        0: branch 1 not taken
     960                0:                                                    : Action::CCC_Expression);
     961                0:     ConsumeToken();
     962                 :   }
     963                 :   
     964                 :   // Parse the first part of the for specifier.
                       58: branch 1 taken
                      226: branch 2 taken
     965              284:   if (Tok.is(tok::semi)) {  // for (;
     966                 :     // no first part, eat the ';'.
     967               58:     ConsumeToken();
                      131: branch 1 taken
                       95: branch 2 taken
     968              226:   } else if (isSimpleDeclaration()) {  // for (int X = 4;
     969                 :     // Parse declaration, which eats the ';'.
                        0: branch 0 not taken
                      131: branch 1 taken
     970              131:     if (!C99orCXXorObjC)   // Use of C99-style for loops in C90 mode?
     971                0:       Diag(Tok, diag::ext_c99_variable_decl_in_for_loop);
     972                 : 
     973              131:     AttributeList *AttrList = 0;
                       22: branch 1 taken
                      109: branch 2 taken
                        0: branch 4 not taken
                       22: branch 5 taken
                        0: branch 6 not taken
                      131: branch 7 taken
     974              131:     if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
     975                0:       AttrList = ParseCXX0XAttributes().AttrList;
     976                 : 
     977              131:     SourceLocation DeclStart = Tok.getLocation(), DeclEnd;
     978                 :     DeclGroupPtrTy DG = ParseSimpleDeclaration(Declarator::ForContext, DeclEnd,
     979              131:                                                AttrList);
     980              131:     FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation());
     981                 : 
                       99: branch 1 taken
                       32: branch 2 taken
     982              131:     if (Tok.is(tok::semi)) {  // for (int x = 4;
     983               99:       ConsumeToken();
                       32: branch 1 taken
                        0: branch 2 not taken
     984               32:     } else if ((ForEach = isTokIdentifier_in())) {
     985               32:       Actions.ActOnForEachDeclStmt(DG);
     986                 :       // ObjC: for (id x in expr)
     987               32:       ConsumeToken(); // consume 'in'
     988               32:       SecondPart = ParseExpression();
     989                 :     } else {
     990                0:       Diag(Tok, diag::err_expected_semi_for);
     991                0:       SkipUntil(tok::semi);
     992                 :     }
     993                 :   } else {
     994               95:     Value = ParseExpression();
     995                 : 
     996                 :     // Turn the expression into a stmt.
                       95: branch 1 taken
                        0: branch 2 not taken
     997               95:     if (!Value.isInvalid())
     998               95:       FirstPart = Actions.ActOnExprStmt(Actions.MakeFullExpr(Value));
     999                 : 
                       71: branch 1 taken
                       24: branch 2 taken
    1000               95:     if (Tok.is(tok::semi)) {
    1001               71:       ConsumeToken();
                       24: branch 1 taken
                        0: branch 2 not taken
    1002               24:     } else if ((ForEach = isTokIdentifier_in())) {
    1003               24:       ConsumeToken(); // consume 'in'
    1004               24:       SecondPart = ParseExpression();
    1005                 :     } else {
                        0: branch 1 not taken
                        0: branch 2 not taken
    1006                0:       if (!Value.isInvalid()) Diag(Tok, diag::err_expected_semi_for);
    1007                0:       SkipUntil(tok::semi);
    1008                 :     }
    1009                 :   }
                      228: branch 0 taken
                       56: branch 1 taken
    1010              284:   if (!ForEach) {
                      228: branch 1 taken
                        0: branch 2 not taken
    1011              228:     assert(!SecondPart.get() && "Shouldn't have a second expression yet.");
    1012                 :     // Parse the second part of the for specifier.
                      192: branch 1 taken
                       36: branch 2 taken
    1013              228:     if (Tok.is(tok::semi)) {  // for (...;;
    1014                 :       // no second part.
    1015                 :     } else {
                       73: branch 1 taken
                      119: branch 2 taken
    1016              192:       if (getLang().CPlusPlus)
    1017               73:         ParseCXXCondition(SecondPart, SecondVar);
    1018                 :       else
    1019              119:         SecondPart = ParseExpression();
    1020                 :     }
    1021                 : 
                      227: branch 1 taken
                        1: branch 2 taken
    1022              228:     if (Tok.is(tok::semi)) {
    1023              227:       ConsumeToken();
    1024                 :     } else {
                        1: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                        1: branch 5 taken
                        0: branch 6 not taken
                        1: branch 7 taken
    1025                1:       if (!SecondPart.isInvalid() || SecondVar.get()) 
    1026                0:         Diag(Tok, diag::err_expected_semi_for);
    1027                1:       SkipUntil(tok::semi);
    1028                 :     }
    1029                 : 
    1030                 :     // Parse the third part of the for specifier.
                      164: branch 1 taken
                       64: branch 2 taken
    1031              228:     if (Tok.isNot(tok::r_paren))    // for (...;...;)
    1032              164:       ThirdPart = ParseExpression();
    1033                 :   }
    1034                 :   // Match the ')'.
    1035              284:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1036                 : 
    1037                 :   // C99 6.8.5p5 - In C99, the body of the if statement is a scope, even if
    1038                 :   // there is no compound stmt.  C90 does not have this clause.  We only do this
    1039                 :   // if the body isn't a compound statement to avoid push/pop in common cases.
    1040                 :   //
    1041                 :   // C++ 6.5p2:
    1042                 :   // The substatement in an iteration-statement implicitly defines a local scope
    1043                 :   // which is entered and exited each time through the loop.
    1044                 :   //
    1045                 :   // See comments in ParseIfStatement for why we create a scope for
    1046                 :   // for-init-statement/condition and a new scope for substatement in C++.
    1047                 :   //
    1048                 :   ParseScope InnerScope(this, Scope::DeclScope,
                      284: branch 0 taken
                        0: branch 1 not taken
                      147: branch 3 taken
                      137: branch 4 taken
    1049              284:                         C99orCXXorObjC && Tok.isNot(tok::l_brace));
    1050                 : 
    1051                 :   // Read the body statement.
    1052              284:   OwningStmtResult Body(ParseStatement());
    1053                 : 
    1054                 :   // Pop the body scope if needed.
    1055              284:   InnerScope.Exit();
    1056                 : 
    1057                 :   // Leave the for-scope.
    1058              284:   ForScope.Exit();
    1059                 : 
                        0: branch 1 not taken
                      284: branch 2 taken
    1060              284:   if (Body.isInvalid())
    1061                0:     return StmtError();
    1062                 : 
                      228: branch 0 taken
                       56: branch 1 taken
    1063              284:   if (!ForEach)
    1064                 :     return Actions.ActOnForStmt(ForLoc, LParenLoc, move(FirstPart),
    1065                 :                                 Actions.MakeFullExpr(SecondPart), SecondVar,
    1066                 :                                 Actions.MakeFullExpr(ThirdPart), RParenLoc, 
    1067              228:                                 move(Body));
    1068                 : 
    1069                 :   return Actions.ActOnObjCForCollectionStmt(ForLoc, LParenLoc,
    1070                 :                                             move(FirstPart),
    1071                 :                                             move(SecondPart),
    1072               56:                                             RParenLoc, move(Body));
    1073                 : }
    1074                 : 
    1075                 : /// ParseGotoStatement
    1076                 : ///       jump-statement:
    1077                 : ///         'goto' identifier ';'
    1078                 : /// [GNU]   'goto' '*' expression ';'
    1079                 : ///
    1080                 : /// Note: this lets the caller parse the end ';'.
    1081                 : ///
    1082              158: Parser::OwningStmtResult Parser::ParseGotoStatement(AttributeList *Attr) {
    1083                 :   // FIXME: Use attributes?
                      158: branch 1 taken
                        0: branch 2 not taken
    1084              158:   assert(Tok.is(tok::kw_goto) && "Not a goto stmt!");
    1085              158:   SourceLocation GotoLoc = ConsumeToken();  // eat the 'goto'.
    1086                 : 
    1087              158:   OwningStmtResult Res(Actions);
                      123: branch 1 taken
                       35: branch 2 taken
    1088              158:   if (Tok.is(tok::identifier)) {
    1089                 :     Res = Actions.ActOnGotoStmt(GotoLoc, Tok.getLocation(),
    1090              123:                                 Tok.getIdentifierInfo());
    1091              123:     ConsumeToken();
                       34: branch 1 taken
                        1: branch 2 taken
    1092               35:   } else if (Tok.is(tok::star)) {
    1093                 :     // GNU indirect goto extension.
    1094               34:     Diag(Tok, diag::ext_gnu_indirect_goto);
    1095               34:     SourceLocation StarLoc = ConsumeToken();
    1096               34:     OwningExprResult R(ParseExpression());
                        0: branch 1 not taken
                       34: branch 2 taken
    1097               34:     if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
    1098                0:       SkipUntil(tok::semi, false, true);
    1099                0:       return StmtError();
    1100                 :     }
                       34: branch 10 taken
                        0: branch 11 not taken
    1101               34:     Res = Actions.ActOnIndirectGotoStmt(GotoLoc, StarLoc, move(R));
    1102                 :   } else {
    1103                1:     Diag(Tok, diag::err_expected_ident);
    1104                1:     return StmtError();
    1105                 :   }
    1106                 : 
    1107              157:   return move(Res);
    1108                 : }
    1109                 : 
    1110                 : /// ParseContinueStatement
    1111                 : ///       jump-statement:
    1112                 : ///         'continue' ';'
    1113                 : ///
    1114                 : /// Note: this lets the caller parse the end ';'.
    1115                 : ///
    1116               32: Parser::OwningStmtResult Parser::ParseContinueStatement(AttributeList *Attr) {
    1117                 :   // FIXME: Use attributes?
    1118               32:   SourceLocation ContinueLoc = ConsumeToken();  // eat the 'continue'.
    1119               32:   return Actions.ActOnContinueStmt(ContinueLoc, CurScope);
    1120                 : }
    1121                 : 
    1122                 : /// ParseBreakStatement
    1123                 : ///       jump-statement:
    1124                 : ///         'break' ';'
    1125                 : ///
    1126                 : /// Note: this lets the caller parse the end ';'.
    1127                 : ///
    1128              265: Parser::OwningStmtResult Parser::ParseBreakStatement(AttributeList *Attr) {
    1129                 :   // FIXME: Use attributes?
    1130              265:   SourceLocation BreakLoc = ConsumeToken();  // eat the 'break'.
    1131              265:   return Actions.ActOnBreakStmt(BreakLoc, CurScope);
    1132                 : }
    1133                 : 
    1134                 : /// ParseReturnStatement
    1135                 : ///       jump-statement:
    1136                 : ///         'return' expression[opt] ';'
    1137             4502: Parser::OwningStmtResult Parser::ParseReturnStatement(AttributeList *Attr) {
    1138                 :   // FIXME: Use attributes?
                     4502: branch 1 taken
                        0: branch 2 not taken
    1139             4502:   assert(Tok.is(tok::kw_return) && "Not a return stmt!");
    1140             4502:   SourceLocation ReturnLoc = ConsumeToken();  // eat the 'return'.
    1141                 : 
    1142             4502:   OwningExprResult R(Actions);
                     4198: branch 1 taken
                      304: branch 2 taken
    1143             4502:   if (Tok.isNot(tok::semi)) {
    1144             4198:     R = ParseExpression();
                       79: branch 1 taken
                     4119: branch 2 taken
    1145             4198:     if (R.isInvalid()) {  // Skip to the semicolon, but don't consume it.
    1146               79:       SkipUntil(tok::semi, false, true);
    1147               79:       return StmtError();
    1148                 :     }
    1149                 :   }
    1150             4423:   return Actions.ActOnReturnStmt(ReturnLoc, move(R));
    1151                 : }
    1152                 : 
    1153                 : /// FuzzyParseMicrosoftAsmStatement. When -fms-extensions is enabled, this
    1154                 : /// routine is called to skip/ignore tokens that comprise the MS asm statement.
    1155                5: Parser::OwningStmtResult Parser::FuzzyParseMicrosoftAsmStatement() {
                        1: branch 1 taken
                        4: branch 2 taken
    1156                5:   if (Tok.is(tok::l_brace)) {
    1157                1:     unsigned short savedBraceCount = BraceCount;
                       18: branch 0 taken
                        1: branch 1 taken
                       18: branch 3 taken
                        0: branch 4 not taken
                       18: branch 5 taken
                        1: branch 6 taken
    1158               19:     do {
    1159               19:       ConsumeAnyToken();
    1160                 :     } while (BraceCount > savedBraceCount && Tok.isNot(tok::eof));
    1161                 :   } else {
    1162                 :     // From the MS website: If used without braces, the __asm keyword means
    1163                 :     // that the rest of the line is an assembly-language statement.
    1164                4:     SourceManager &SrcMgr = PP.getSourceManager();
    1165                4:     SourceLocation TokLoc = Tok.getLocation();
    1166                4:     unsigned LineNo = SrcMgr.getInstantiationLineNumber(TokLoc);
                       14: branch 1 taken
                        0: branch 2 not taken
                       10: branch 4 taken
                        4: branch 5 taken
                       10: branch 7 taken
                        0: branch 8 not taken
                       10: branch 10 taken
                        0: branch 11 not taken
                       10: branch 12 taken
                        4: branch 13 taken
    1167               14:     do {
    1168               14:       ConsumeAnyToken();
    1169               14:       TokLoc = Tok.getLocation();
    1170                 :     } while ((SrcMgr.getInstantiationLineNumber(TokLoc) == LineNo) &&
    1171                 :              Tok.isNot(tok::r_brace) && Tok.isNot(tok::semi) &&
    1172                 :              Tok.isNot(tok::eof));
    1173                 :   }
    1174                5:   Token t;
    1175                5:   t.setKind(tok::string_literal);
    1176                5:   t.setLiteralData("\"FIXME: not done\"");
    1177                5:   t.clearFlag(Token::NeedsCleaning);
    1178                5:   t.setLength(17);
    1179                5:   OwningExprResult AsmString(Actions.ActOnStringLiteral(&t, 1));
    1180                5:   ExprVector Constraints(Actions);
    1181                5:   ExprVector Exprs(Actions);
    1182                5:   ExprVector Clobbers(Actions);
    1183                 :   return Actions.ActOnAsmStmt(Tok.getLocation(), true, true, 0, 0, 0,
    1184                 :                               move_arg(Constraints), move_arg(Exprs),
    1185                 :                               move(AsmString), move_arg(Clobbers),
    1186                5:                               Tok.getLocation(), true);
    1187                 : }
    1188                 : 
    1189                 : /// ParseAsmStatement - Parse a GNU extended asm statement.
    1190                 : ///       asm-statement:
    1191                 : ///         gnu-asm-statement
    1192                 : ///         ms-asm-statement
    1193                 : ///
    1194                 : /// [GNU] gnu-asm-statement:
    1195                 : ///         'asm' type-qualifier[opt] '(' asm-argument ')' ';'
    1196                 : ///
    1197                 : /// [GNU] asm-argument:
    1198                 : ///         asm-string-literal
    1199                 : ///         asm-string-literal ':' asm-operands[opt]
    1200                 : ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    1201                 : ///         asm-string-literal ':' asm-operands[opt] ':' asm-operands[opt]
    1202                 : ///                 ':' asm-clobbers
    1203                 : ///
    1204                 : /// [GNU] asm-clobbers:
    1205                 : ///         asm-string-literal
    1206                 : ///         asm-clobbers ',' asm-string-literal
    1207                 : ///
    1208                 : /// [MS]  ms-asm-statement:
    1209                 : ///         '__asm' assembly-instruction ';'[opt]
    1210                 : ///         '__asm' '{' assembly-instruction-list '}' ';'[opt]
    1211                 : ///
    1212                 : /// [MS]  assembly-instruction-list:
    1213                 : ///         assembly-instruction ';'[opt]
    1214                 : ///         assembly-instruction-list ';' assembly-instruction ';'[opt]
    1215                 : ///
    1216              108: Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {
                      108: branch 1 taken
                        0: branch 2 not taken
    1217              108:   assert(Tok.is(tok::kw_asm) && "Not an asm stmt");
    1218              108:   SourceLocation AsmLoc = ConsumeToken();
    1219                 : 
                        5: branch 1 taken
                      103: branch 2 taken
                        5: branch 4 taken
                        0: branch 5 not taken
                        5: branch 7 taken
                        0: branch 8 not taken
                        5: branch 9 taken
                      103: branch 10 taken
    1220              113:   if (getLang().Microsoft && Tok.isNot(tok::l_paren) && !isTypeQualifier()) {
    1221                5:     msAsm = true;
    1222                5:     return FuzzyParseMicrosoftAsmStatement();
    1223                 :   }
    1224              103:   DeclSpec DS;
    1225              103:   SourceLocation Loc = Tok.getLocation();
    1226              103:   ParseTypeQualifierListOpt(DS, true, false);
    1227                 : 
    1228                 :   // GNU asms accept, but warn, about type-qualifiers other than volatile.
                        0: branch 1 not taken
                      103: branch 2 taken
    1229              103:   if (DS.getTypeQualifiers() & DeclSpec::TQ_const)
    1230                0:     Diag(Loc, diag::w_asm_qualifier_ignored) << "const";
                        0: branch 1 not taken
                      103: branch 2 taken
    1231              103:   if (DS.getTypeQualifiers() & DeclSpec::TQ_restrict)
    1232                0:     Diag(Loc, diag::w_asm_qualifier_ignored) << "restrict";
    1233                 : 
    1234                 :   // Remember if this was a volatile asm.
    1235              103:   bool isVolatile = DS.getTypeQualifiers() & DeclSpec::TQ_volatile;
                        0: branch 1 not taken
                      103: branch 2 taken
    1236              103:   if (Tok.isNot(tok::l_paren)) {
    1237                0:     Diag(Tok, diag::err_expected_lparen_after) << "asm";
    1238                0:     SkipUntil(tok::r_paren);
    1239                0:     return StmtError();
    1240                 :   }
    1241              103:   Loc = ConsumeParen();
    1242                 : 
    1243              103:   OwningExprResult AsmString(ParseAsmStringLiteral());
                        0: branch 1 not taken
                      103: branch 2 taken
    1244              103:   if (AsmString.isInvalid())
    1245                0:     return StmtError();
    1246                 : 
    1247              103:   llvm::SmallVector<IdentifierInfo *, 4> Names;
    1248              103:   ExprVector Constraints(Actions);
    1249              103:   ExprVector Exprs(Actions);
    1250              103:   ExprVector Clobbers(Actions);
    1251                 : 
                       22: branch 1 taken
                       81: branch 2 taken
    1252              103:   if (Tok.is(tok::r_paren)) {
    1253                 :     // We have a simple asm expression like 'asm("foo")'.
    1254               22:     SourceLocation RParenLoc = ConsumeParen();
    1255                 :     return Actions.ActOnAsmStmt(AsmLoc, /*isSimple*/ true, isVolatile,
    1256                 :                                 /*NumOutputs*/ 0, /*NumInputs*/ 0, 0, 
    1257                 :                                 move_arg(Constraints), move_arg(Exprs),
    1258                 :                                 move(AsmString), move_arg(Clobbers),
    1259               22:                                 RParenLoc);
    1260                 :   }
    1261                 : 
    1262                 :   // Parse Outputs, if present.
    1263               81:   bool AteExtraColon = false;
                        1: branch 1 taken
                       80: branch 2 taken
                        1: branch 4 taken
                        0: branch 5 not taken
                       81: branch 6 taken
                        0: branch 7 not taken
    1264               81:   if (Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    1265                 :     // In C++ mode, parse "::" like ": :".
    1266               81:     AteExtraColon = Tok.is(tok::coloncolon);
    1267               81:     ConsumeToken();
    1268                 :   
                       80: branch 0 taken
                        1: branch 1 taken
                        1: branch 3 taken
                       79: branch 4 taken
                        1: branch 5 taken
                       80: branch 6 taken
    1269               81:     if (!AteExtraColon &&
    1270                 :         ParseAsmOperandsOpt(Names, Constraints, Exprs))
    1271                1:       return StmtError();
    1272                 :   }
    1273                 :   
    1274               80:   unsigned NumOutputs = Names.size();
    1275                 : 
    1276                 :   // Parse Inputs, if present.
                       79: branch 0 taken
                        1: branch 1 taken
                       17: branch 3 taken
                       62: branch 4 taken
                        1: branch 6 taken
                       16: branch 7 taken
                       64: branch 8 taken
                       16: branch 9 taken
    1277               80:   if (AteExtraColon ||
    1278                 :       Tok.is(tok::colon) || Tok.is(tok::coloncolon)) {
    1279                 :     // In C++ mode, parse "::" like ": :".
                        1: branch 0 taken
                       63: branch 1 taken
    1280               64:     if (AteExtraColon)
    1281                1:       AteExtraColon = false;
    1282                 :     else {
    1283               63:       AteExtraColon = Tok.is(tok::coloncolon);
    1284               63:       ConsumeToken();
    1285                 :     }
    1286                 :     
                       63: branch 0 taken
                        1: branch 1 taken
                        1: branch 3 taken
                       62: branch 4 taken
                        1: branch 5 taken
                       63: branch 6 taken
    1287               64:     if (!AteExtraColon &&
    1288                 :         ParseAsmOperandsOpt(Names, Constraints, Exprs))
    1289                1:       return StmtError();
    1290                 :   }
    1291                 : 
    1292                 :   assert(Names.size() == Constraints.size() &&
    1293                 :          Constraints.size() == Exprs.size() &&
                       79: branch 2 taken
                        0: branch 3 not taken
                       79: branch 6 taken
                        0: branch 7 not taken
    1294               79:          "Input operand size mismatch!");
    1295                 : 
    1296               79:   unsigned NumInputs = Names.size() - NumOutputs;
    1297                 : 
    1298                 :   // Parse the clobbers, if present.
                       78: branch 0 taken
                        1: branch 1 taken
                       21: branch 3 taken
                       57: branch 4 taken
                       22: branch 5 taken
                       57: branch 6 taken
    1299              157:   if (AteExtraColon || Tok.is(tok::colon)) {
                       21: branch 0 taken
                        1: branch 1 taken
    1300               22:     if (!AteExtraColon)
    1301               21:       ConsumeToken();
    1302                 : 
    1303                 :     // Parse the asm-string list for clobbers.
                       34: branch 1 taken
                       22: branch 2 taken
    1304               56:     while (1) {
    1305               56:       OwningExprResult Clobber(ParseAsmStringLiteral());
    1306                 : 
                        1: branch 1 taken
                       55: branch 2 taken
    1307               56:       if (Clobber.isInvalid())
    1308               22:         break;
    1309                 : 
    1310               55:       Clobbers.push_back(Clobber.release());
    1311                 : 
                       21: branch 1 taken
                       34: branch 2 taken
    1312               55:       if (Tok.isNot(tok::comma)) break;
    1313               34:       ConsumeToken();
    1314                 :     }
    1315                 :   }
    1316                 : 
    1317               79:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, Loc);
    1318                 :   return Actions.ActOnAsmStmt(AsmLoc, false, isVolatile,
    1319                 :                               NumOutputs, NumInputs, Names.data(),
    1320                 :                               move_arg(Constraints), move_arg(Exprs),
    1321                 :                               move(AsmString), move_arg(Clobbers),
    1322               79:                               RParenLoc);
    1323                 : }
    1324                 : 
    1325                 : /// ParseAsmOperands - Parse the asm-operands production as used by
    1326                 : /// asm-statement, assuming the leading ':' token was eaten.
    1327                 : ///
    1328                 : /// [GNU] asm-operands:
    1329                 : ///         asm-operand
    1330                 : ///         asm-operands ',' asm-operand
    1331                 : ///
    1332                 : /// [GNU] asm-operand:
    1333                 : ///         asm-string-literal '(' expression ')'
    1334                 : ///         '[' identifier ']' asm-string-literal '(' expression ')'
    1335                 : ///
    1336                 : //
    1337                 : // FIXME: Avoid unnecessary std::string trashing.
    1338                 : bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<IdentifierInfo *> &Names,
    1339                 :                                  llvm::SmallVectorImpl<ExprTy *> &Constraints,
    1340              143:                                  llvm::SmallVectorImpl<ExprTy *> &Exprs) {
    1341                 :   // 'asm-operands' isn't present?
                       76: branch 1 taken
                       67: branch 2 taken
                       68: branch 4 taken
                        8: branch 5 taken
                       68: branch 6 taken
                       75: branch 7 taken
    1342              143:   if (!isTokenStringLiteral() && Tok.isNot(tok::l_square))
    1343               68:     return false;
    1344                 : 
                       13: branch 1 taken
                       75: branch 2 taken
                       13: branch 4 taken
                       75: branch 5 taken
    1345               88:   while (1) {
    1346                 :     // Read the [id] if present.
                       10: branch 1 taken
                       78: branch 2 taken
    1347               88:     if (Tok.is(tok::l_square)) {
    1348               10:       SourceLocation Loc = ConsumeBracket();
    1349                 : 
                        0: branch 1 not taken
                       10: branch 2 taken
    1350               10:       if (Tok.isNot(tok::identifier)) {
    1351                0:         Diag(Tok, diag::err_expected_ident);
    1352                0:         SkipUntil(tok::r_paren);
    1353                0:         return true;
    1354                 :       }
    1355                 : 
    1356               10:       IdentifierInfo *II = Tok.getIdentifierInfo();
    1357               10:       ConsumeToken();
    1358                 : 
    1359               10:       Names.push_back(II);
    1360               10:       MatchRHSPunctuation(tok::r_square, Loc);
    1361                 :     } else
    1362               78:       Names.push_back(0);
    1363                 : 
    1364               88:     OwningExprResult Constraint(ParseAsmStringLiteral());
                        0: branch 1 not taken
                       88: branch 2 taken
    1365               88:     if (Constraint.isInvalid()) {
    1366                0:         SkipUntil(tok::r_paren);
    1367               75:         return true;
    1368                 :     }
    1369               88:     Constraints.push_back(Constraint.release());
    1370                 : 
                        0: branch 1 not taken
                       88: branch 2 taken
    1371               88:     if (Tok.isNot(tok::l_paren)) {
    1372                0:       Diag(Tok, diag::err_expected_lparen_after) << "asm operand";
    1373                0:       SkipUntil(tok::r_paren);
    1374                0:       return true;
    1375                 :     }
    1376                 : 
    1377                 :     // Read the parenthesized expression.
    1378               88:     SourceLocation OpenLoc = ConsumeParen();
    1379               88:     OwningExprResult Res(ParseExpression());
    1380               88:     MatchRHSPunctuation(tok::r_paren, OpenLoc);
                        2: branch 1 taken
                       86: branch 2 taken
    1381               88:     if (Res.isInvalid()) {
    1382                2:       SkipUntil(tok::r_paren);
    1383                2:       return true;
    1384                 :     }
    1385               86:     Exprs.push_back(Res.release());
    1386                 :     // Eat the comma and continue parsing if it exists.
                       73: branch 1 taken
                       13: branch 2 taken
    1387               86:     if (Tok.isNot(tok::comma)) return false;
    1388               13:     ConsumeToken();
    1389                 :   }
    1390                 : 
    1391                 :   return true;
    1392                 : }
    1393                 : 
    1394             8250: Parser::DeclPtrTy Parser::ParseFunctionStatementBody(DeclPtrTy Decl) {
                        0: branch 1 not taken
                     8250: branch 2 taken
    1395             8250:   assert(Tok.is(tok::l_brace));
    1396             8250:   SourceLocation LBraceLoc = Tok.getLocation();
    1397                 : 
    1398                 :   PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
    1399                 :                                         PP.getSourceManager(),
    1400             8250:                                         "parsing function body");
    1401                 : 
    1402                 :   // Do not enter a scope for the brace, as the arguments are in the same scope
    1403                 :   // (the function body) as the body itself.  Instead, just read the statement
    1404                 :   // list and put it into a CompoundStmt for safe keeping.
    1405             8250:   OwningStmtResult FnBody(ParseCompoundStatementBody());
    1406                 : 
    1407                 :   // If the function body could not be parsed, make a bogus compoundstmt.
                       46: branch 1 taken
                     8204: branch 2 taken
    1408             8250:   if (FnBody.isInvalid())
    1409                 :     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
    1410               46:                                        MultiStmtArg(Actions), false);
    1411                 : 
    1412             8250:   return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
    1413                 : }
    1414                 : 
    1415                 : /// ParseFunctionTryBlock - Parse a C++ function-try-block.
    1416                 : ///
    1417                 : ///       function-try-block:
    1418                 : ///         'try' ctor-initializer[opt] compound-statement handler-seq
    1419                 : ///
    1420                8: Parser::DeclPtrTy Parser::ParseFunctionTryBlock(DeclPtrTy Decl) {
                        8: branch 1 taken
                        0: branch 2 not taken
    1421                8:   assert(Tok.is(tok::kw_try) && "Expected 'try'");
    1422                8:   SourceLocation TryLoc = ConsumeToken();
    1423                 : 
    1424                 :   PrettyStackTraceActionsDecl CrashInfo(Decl, TryLoc, Actions,
    1425                 :                                         PP.getSourceManager(),
    1426                8:                                         "parsing function try block");
    1427                 : 
    1428                 :   // Constructor initializer list?
                        2: branch 1 taken
                        6: branch 2 taken
    1429                8:   if (Tok.is(tok::colon))
    1430                2:     ParseConstructorInitializer(Decl);
    1431                 : 
    1432                8:   SourceLocation LBraceLoc = Tok.getLocation();
    1433                8:   OwningStmtResult FnBody(ParseCXXTryBlockCommon(TryLoc));
    1434                 :   // If we failed to parse the try-catch, we just give the function an empty
    1435                 :   // compound statement as the body.
                        0: branch 1 not taken
                        8: branch 2 taken
    1436                8:   if (FnBody.isInvalid())
    1437                 :     FnBody = Actions.ActOnCompoundStmt(LBraceLoc, LBraceLoc,
    1438                0:                                        MultiStmtArg(Actions), false);
    1439                 : 
    1440                8:   return Actions.ActOnFinishFunctionBody(Decl, move(FnBody));
    1441                 : }
    1442                 : 
    1443                 : /// ParseCXXTryBlock - Parse a C++ try-block.
    1444                 : ///
    1445                 : ///       try-block:
    1446                 : ///         'try' compound-statement handler-seq
    1447                 : ///
    1448               20: Parser::OwningStmtResult Parser::ParseCXXTryBlock(AttributeList* Attr) {
    1449                 :   // FIXME: Add attributes?
                       20: branch 1 taken
                        0: branch 2 not taken
    1450               20:   assert(Tok.is(tok::kw_try) && "Expected 'try'");
    1451                 : 
    1452               20:   SourceLocation TryLoc = ConsumeToken();
    1453               20:   return ParseCXXTryBlockCommon(TryLoc);
    1454                 : }
    1455                 : 
    1456                 : /// ParseCXXTryBlockCommon - Parse the common part of try-block and
    1457                 : /// function-try-block.
    1458                 : ///
    1459                 : ///       try-block:
    1460                 : ///         'try' compound-statement handler-seq
    1461                 : ///
    1462                 : ///       function-try-block:
    1463                 : ///         'try' ctor-initializer[opt] compound-statement handler-seq
    1464                 : ///
    1465                 : ///       handler-seq:
    1466                 : ///         handler handler-seq[opt]
    1467                 : ///
    1468               28: Parser::OwningStmtResult Parser::ParseCXXTryBlockCommon(SourceLocation TryLoc) {
                        1: branch 1 taken
                       27: branch 2 taken
    1469               28:   if (Tok.isNot(tok::l_brace))
    1470                1:     return StmtError(Diag(Tok, diag::err_expected_lbrace));
    1471                 :   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
    1472               27:   OwningStmtResult TryBlock(ParseCompoundStatement(0));
                        0: branch 1 not taken
                       27: branch 2 taken
    1473               27:   if (TryBlock.isInvalid())
    1474                0:     return move(TryBlock);
    1475                 : 
    1476               27:   StmtVector Handlers(Actions);
                        4: branch 1 taken
                       23: branch 2 taken
                        1: branch 4 taken
                        3: branch 5 taken
                        1: branch 6 taken
                       26: branch 7 taken
    1477               27:   if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
    1478                1:     CXX0XAttributeList Attr = ParseCXX0XAttributes();
    1479                 :     Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
    1480                1:       << Attr.Range;
    1481                 :   }
                        0: branch 1 not taken
                       27: branch 2 taken
    1482               27:   if (Tok.isNot(tok::kw_catch))
    1483                0:     return StmtError(Diag(Tok, diag::err_expected_catch));
                       41: branch 2 taken
                       27: branch 3 taken
    1484               68:   while (Tok.is(tok::kw_catch)) {
    1485               41:     OwningStmtResult Handler(ParseCXXCatchBlock());
                       38: branch 1 taken
                        3: branch 2 taken
    1486               41:     if (!Handler.isInvalid())
    1487               38:       Handlers.push_back(Handler.release());
    1488                 :   }
    1489                 :   // Don't bother creating the full statement if we don't have any usable
    1490                 :   // handlers.
                        3: branch 1 taken
                       24: branch 2 taken
    1491               27:   if (Handlers.empty())
    1492                3:     return StmtError();
    1493                 : 
    1494               24:   return Actions.ActOnCXXTryBlock(TryLoc, move(TryBlock), move_arg(Handlers));
    1495                 : }
    1496                 : 
    1497                 : /// ParseCXXCatchBlock - Parse a C++ catch block, called handler in the standard
    1498                 : ///
    1499                 : ///       handler:
    1500                 : ///         'catch' '(' exception-declaration ')' compound-statement
    1501                 : ///
    1502                 : ///       exception-declaration:
    1503                 : ///         type-specifier-seq declarator
    1504                 : ///         type-specifier-seq abstract-declarator
    1505                 : ///         type-specifier-seq
    1506                 : ///         '...'
    1507                 : ///
    1508               41: Parser::OwningStmtResult Parser::ParseCXXCatchBlock() {
                       41: branch 1 taken
                        0: branch 2 not taken
    1509               41:   assert(Tok.is(tok::kw_catch) && "Expected 'catch'");
    1510                 : 
    1511               41:   SourceLocation CatchLoc = ConsumeToken();
    1512                 : 
    1513               41:   SourceLocation LParenLoc = Tok.getLocation();
                        2: branch 1 taken
                       39: branch 2 taken
    1514               41:   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
    1515                2:     return StmtError();
    1516                 : 
    1517                 :   // C++ 3.3.2p3:
    1518                 :   // The name in a catch exception-declaration is local to the handler and
    1519                 :   // shall not be redeclared in the outermost block of the handler.
    1520               39:   ParseScope CatchScope(this, Scope::DeclScope | Scope::ControlScope);
    1521                 : 
    1522                 :   // exception-declaration is equivalent to '...' or a parameter-declaration
    1523                 :   // without default arguments.
    1524               39:   DeclPtrTy ExceptionDecl;
                       24: branch 1 taken
                       15: branch 2 taken
    1525               39:   if (Tok.isNot(tok::ellipsis)) {
    1526               24:     DeclSpec DS;
                        0: branch 1 not taken
                       24: branch 2 taken
    1527               24:     if (ParseCXXTypeSpecifierSeq(DS))
    1528                0:       return StmtError();
    1529               24:     Declarator ExDecl(DS, Declarator::CXXCatchContext);
    1530               24:     ParseDeclarator(ExDecl);
                       24: branch 3 taken
                        0: branch 4 not taken
    1531               24:     ExceptionDecl = Actions.ActOnExceptionDeclarator(CurScope, ExDecl);
    1532                 :   } else
    1533               15:     ConsumeToken();
    1534                 : 
                        0: branch 2 not taken
                       39: branch 3 taken
    1535               39:   if (MatchRHSPunctuation(tok::r_paren, LParenLoc).isInvalid())
    1536                0:     return StmtError();
    1537                 : 
                        1: branch 1 taken
                       38: branch 2 taken
    1538               39:   if (Tok.isNot(tok::l_brace))
    1539                1:     return StmtError(Diag(Tok, diag::err_expected_lbrace));
    1540                 : 
    1541                 :   // FIXME: Possible draft standard bug: attribute-specifier should be allowed?
    1542               38:   OwningStmtResult Block(ParseCompoundStatement(0));
                        0: branch 1 not taken
                       38: branch 2 taken
    1543               38:   if (Block.isInvalid())
    1544                0:     return move(Block);
    1545                 : 
    1546               38:   return Actions.ActOnCXXCatchBlock(CatchLoc, ExceptionDecl, move(Block));
    1547                 : }

Generated: 2010-02-10 01:31 by zcov