zcov: / lib/Parse/ParseTentative.cpp


Files: 1 Branches Taken: 80.5% 231 / 287
Generated: 2010-02-10 01:31 Branches Executed: 97.9% 281 / 287
Line Coverage: 89.1% 237 / 266


Programs: 2 Runs 3018


       1                 : //===--- ParseTentative.cpp - Ambiguity Resolution Parsing ----------------===//
       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 tentative parsing portions of the Parser
      11                 : //  interfaces, for ambiguity resolution.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "clang/Parse/Parser.h"
      16                 : #include "clang/Parse/ParseDiagnostic.h"
      17                 : using namespace clang;
      18                 : 
      19                 : /// isCXXDeclarationStatement - C++-specialized function that disambiguates
      20                 : /// between a declaration or an expression statement, when parsing function
      21                 : /// bodies. Returns true for declaration, false for expression.
      22                 : ///
      23                 : ///         declaration-statement:
      24                 : ///           block-declaration
      25                 : ///
      26                 : ///         block-declaration:
      27                 : ///           simple-declaration
      28                 : ///           asm-definition
      29                 : ///           namespace-alias-definition
      30                 : ///           using-declaration
      31                 : ///           using-directive
      32                 : /// [C++0x]   static_assert-declaration
      33                 : ///
      34                 : ///         asm-definition:
      35                 : ///           'asm' '(' string-literal ')' ';'
      36                 : ///
      37                 : ///         namespace-alias-definition:
      38                 : ///           'namespace' identifier = qualified-namespace-specifier ';'
      39                 : ///
      40                 : ///         using-declaration:
      41                 : ///           'using' typename[opt] '::'[opt] nested-name-specifier
      42                 : ///                 unqualified-id ';'
      43                 : ///           'using' '::' unqualified-id ;
      44                 : ///
      45                 : ///         using-directive:
      46                 : ///           'using' 'namespace' '::'[opt] nested-name-specifier[opt]
      47                 : ///                 namespace-name ';'
      48                 : ///
      49             4968: bool Parser::isCXXDeclarationStatement() {
                       43: branch 1 taken
                     4925: branch 2 taken
      50             4968:   switch (Tok.getKind()) {
      51                 :     // asm-definition
      52                 :   case tok::kw_asm:
      53                 :     // namespace-alias-definition
      54                 :   case tok::kw_namespace:
      55                 :     // using-declaration
      56                 :     // using-directive
      57                 :   case tok::kw_using:
      58                 :     // static_assert-declaration
      59                 :   case tok::kw_static_assert:
      60               43:     return true;
      61                 :     // simple-declaration
      62                 :   default:
      63             4925:     return isCXXSimpleDeclaration();
      64                 :   }
      65                 : }
      66                 : 
      67                 : /// isCXXSimpleDeclaration - C++-specialized function that disambiguates
      68                 : /// between a simple-declaration or an expression-statement.
      69                 : /// If during the disambiguation process a parsing error is encountered,
      70                 : /// the function returns true to let the declaration parsing code handle it.
      71                 : /// Returns false if the statement is disambiguated as expression.
      72                 : ///
      73                 : /// simple-declaration:
      74                 : ///   decl-specifier-seq init-declarator-list[opt] ';'
      75                 : ///
      76             4985: bool Parser::isCXXSimpleDeclaration() {
      77                 :   // C++ 6.8p1:
      78                 :   // There is an ambiguity in the grammar involving expression-statements and
      79                 :   // declarations: An expression-statement with a function-style explicit type
      80                 :   // conversion (5.2.3) as its leftmost subexpression can be indistinguishable
      81                 :   // from a declaration where the first declarator starts with a '('. In those
      82                 :   // cases the statement is a declaration. [Note: To disambiguate, the whole
      83                 :   // statement might have to be examined to determine if it is an
      84                 :   // expression-statement or a declaration].
      85                 : 
      86                 :   // C++ 6.8p3:
      87                 :   // The disambiguation is purely syntactic; that is, the meaning of the names
      88                 :   // occurring in such a statement, beyond whether they are type-names or not,
      89                 :   // is not generally used in or changed by the disambiguation. Class
      90                 :   // templates are instantiated as necessary to determine if a qualified name
      91                 :   // is a type-name. Disambiguation precedes parsing, and a statement
      92                 :   // disambiguated as a declaration may be an ill-formed declaration.
      93                 : 
      94                 :   // We don't have to parse all of the decl-specifier-seq part. There's only
      95                 :   // an ambiguity if the first decl-specifier is
      96                 :   // simple-type-specifier/typename-specifier followed by a '(', which may
      97                 :   // indicate a function-style cast expression.
      98                 :   // isCXXDeclarationSpecifier will return TPResult::Ambiguous() only in such
      99                 :   // a case.
     100                 : 
     101             4985:   TPResult TPR = isCXXDeclarationSpecifier();
                     4822: branch 2 taken
                      163: branch 3 taken
     102             4985:   if (TPR != TPResult::Ambiguous())
     103             4822:     return TPR != TPResult::False(); // Returns true for TPResult::True() or
     104                 :                                      // TPResult::Error().
     105                 : 
     106                 :   // FIXME: Add statistics about the number of ambiguous statements encountered
     107                 :   // and how they were resolved (number of declarations+number of expressions).
     108                 : 
     109                 :   // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
     110                 :   // We need tentative parsing...
     111                 : 
     112              163:   TentativeParsingAction PA(*this);
     113                 : 
     114              163:   TPR = TryParseSimpleDeclaration();
     115              163:   SourceLocation TentativeParseLoc = Tok.getLocation();
     116                 : 
     117              163:   PA.Revert();
     118                 : 
     119                 :   // In case of an error, let the declaration parsing code handle it.
                        0: branch 2 not taken
                      163: branch 3 taken
     120              163:   if (TPR == TPResult::Error())
     121                0:     return true;
     122                 : 
     123                 :   // Declarations take precedence over expressions.
                      122: branch 2 taken
                       41: branch 3 taken
     124              163:   if (TPR == TPResult::Ambiguous())
     125              122:     TPR = TPResult::True();
     126                 : 
                       38: branch 2 taken
                      125: branch 3 taken
                        0: branch 6 not taken
                       38: branch 7 taken
     127              163:   assert(TPR == TPResult::True() || TPR == TPResult::False());
     128              163:   return TPR == TPResult::True();
     129                 : }
     130                 : 
     131                 : /// simple-declaration:
     132                 : ///   decl-specifier-seq init-declarator-list[opt] ';'
     133                 : ///
     134              163: Parser::TPResult Parser::TryParseSimpleDeclaration() {
     135                 :   // We know that we have a simple-type-specifier/typename-specifier followed
     136                 :   // by a '('.
                        0: branch 3 not taken
                      163: branch 4 taken
     137              163:   assert(isCXXDeclarationSpecifier() == TPResult::Ambiguous());
     138                 : 
                        2: branch 1 taken
                      161: branch 2 taken
     139              163:   if (Tok.is(tok::kw_typeof))
     140                2:     TryParseTypeofSpecifier();
     141                 :   else
     142              161:     ConsumeToken();
     143                 : 
                      163: branch 1 taken
                        0: branch 2 not taken
     144              163:   assert(Tok.is(tok::l_paren) && "Expected '('");
     145                 : 
     146              163:   TPResult TPR = TryParseInitDeclaratorList();
                       37: branch 2 taken
                      126: branch 3 taken
     147              163:   if (TPR != TPResult::Ambiguous())
     148               37:     return TPR;
     149                 : 
                        4: branch 1 taken
                      122: branch 2 taken
     150              126:   if (Tok.isNot(tok::semi))
     151                4:     return TPResult::False();
     152                 : 
     153              122:   return TPResult::Ambiguous();
     154                 : }
     155                 : 
     156                 : ///       init-declarator-list:
     157                 : ///         init-declarator
     158                 : ///         init-declarator-list ',' init-declarator
     159                 : ///
     160                 : ///       init-declarator:
     161                 : ///         declarator initializer[opt]
     162                 : /// [GNU]   declarator simple-asm-expr[opt] attributes[opt] initializer[opt]
     163                 : ///
     164                 : /// initializer:
     165                 : ///   '=' initializer-clause
     166                 : ///   '(' expression-list ')'
     167                 : ///
     168                 : /// initializer-clause:
     169                 : ///   assignment-expression
     170                 : ///   '{' initializer-list ','[opt] '}'
     171                 : ///   '{' '}'
     172                 : ///
     173              164: Parser::TPResult Parser::TryParseInitDeclaratorList() {
     174                 :   // GCC only examines the first declarator for disambiguation:
     175                 :   // i.e:
     176                 :   // int(x), ++x; // GCC regards it as ill-formed declaration.
     177                 :   //
     178                 :   // Comeau and MSVC will regard the above statement as correct expression.
     179                 :   // Clang examines all of the declarators and also regards the above statement
     180                 :   // as correct expression.
     181                 : 
     182                1:   while (1) {
     183                 :     // declarator
     184              164:     TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
                       34: branch 2 taken
                      130: branch 3 taken
     185              164:     if (TPR != TPResult::Ambiguous())
     186               34:       return TPR;
     187                 : 
     188                 :     // [GNU] simple-asm-expr[opt] attributes[opt]
                      130: branch 1 taken
                        0: branch 2 not taken
                        3: branch 4 taken
                      127: branch 5 taken
                        3: branch 6 taken
                      127: branch 7 taken
     189              130:     if (Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
     190                3:       return TPResult::True();
     191                 : 
     192                 :     // initializer[opt]
                        1: branch 1 taken
                      126: branch 2 taken
     193              127:     if (Tok.is(tok::l_paren)) {
     194                 :       // Parse through the parens.
     195                1:       ConsumeParen();
                        0: branch 1 not taken
                        1: branch 2 taken
     196                1:       if (!SkipUntil(tok::r_paren))
     197                0:         return TPResult::Error();
                      111: branch 1 taken
                       15: branch 2 taken
     198              126:     } else if (Tok.is(tok::equal)) {
     199                 :       // MSVC won't examine the rest of declarators if '=' is encountered, it
     200                 :       // will conclude that it is a declaration.
     201                 :       // Comeau and Clang will examine the rest of declarators.
     202                 :       // Note that "int(x) = {0}, ++x;" will be interpreted as ill-formed
     203                 :       // expression.
     204                 :       //
     205                 :       // Parse through the initializer-clause.
     206              111:       SkipUntil(tok::comma, true/*StopAtSemi*/, true/*DontConsume*/);
     207                 :     }
     208                 : 
                        1: branch 1 taken
                      126: branch 2 taken
     209              127:     if (Tok.isNot(tok::comma))
     210              126:       break;
     211                1:     ConsumeToken(); // the comma.
     212                 :   }
     213                 : 
     214              126:   return TPResult::Ambiguous();
     215                 : }
     216                 : 
     217                 : /// isCXXConditionDeclaration - Disambiguates between a declaration or an
     218                 : /// expression for a condition of a if/switch/while/for statement.
     219                 : /// If during the disambiguation process a parsing error is encountered,
     220                 : /// the function returns true to let the declaration parsing code handle it.
     221                 : ///
     222                 : ///       condition:
     223                 : ///         expression
     224                 : ///         type-specifier-seq declarator '=' assignment-expression
     225                 : /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
     226                 : ///             '=' assignment-expression
     227                 : ///
     228              365: bool Parser::isCXXConditionDeclaration() {
     229              365:   TPResult TPR = isCXXDeclarationSpecifier();
                      352: branch 2 taken
                       13: branch 3 taken
     230              365:   if (TPR != TPResult::Ambiguous())
     231              352:     return TPR != TPResult::False(); // Returns true for TPResult::True() or
     232                 :                                      // TPResult::Error().
     233                 : 
     234                 :   // FIXME: Add statistics about the number of ambiguous statements encountered
     235                 :   // and how they were resolved (number of declarations+number of expressions).
     236                 : 
     237                 :   // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
     238                 :   // We need tentative parsing...
     239                 : 
     240               13:   TentativeParsingAction PA(*this);
     241                 : 
     242                 :   // type-specifier-seq
                        0: branch 1 not taken
                       13: branch 2 taken
     243               13:   if (Tok.is(tok::kw_typeof))
     244                0:     TryParseTypeofSpecifier();
     245                 :   else
     246               13:     ConsumeToken();
                       13: branch 1 taken
                        0: branch 2 not taken
     247               13:   assert(Tok.is(tok::l_paren) && "Expected '('");
     248                 : 
     249                 :   // declarator
     250               13:   TPR = TryParseDeclarator(false/*mayBeAbstract*/);
     251                 : 
     252                 :   // In case of an error, let the declaration parsing code handle it.
                        0: branch 2 not taken
                       13: branch 3 taken
     253               13:   if (TPR == TPResult::Error())
     254                0:     TPR = TPResult::True();
     255                 : 
                        2: branch 2 taken
                       11: branch 3 taken
     256               13:   if (TPR == TPResult::Ambiguous()) {
     257                 :     // '='
     258                 :     // [GNU] simple-asm-expr[opt] attributes[opt]
                        1: branch 1 taken
                        1: branch 2 taken
                        1: branch 4 taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                        1: branch 8 taken
                        1: branch 9 taken
                        1: branch 10 taken
     259                2:     if (Tok.is(tok::equal)  ||
     260                 :         Tok.is(tok::kw_asm) || Tok.is(tok::kw___attribute))
     261                1:       TPR = TPResult::True();
     262                 :     else
     263                1:       TPR = TPResult::False();
     264                 :   }
     265                 : 
     266               13:   PA.Revert();
     267                 : 
                       12: branch 2 taken
                        1: branch 3 taken
                        0: branch 6 not taken
                       12: branch 7 taken
     268               13:   assert(TPR == TPResult::True() || TPR == TPResult::False());
     269               13:   return TPR == TPResult::True();
     270                 : }
     271                 : 
     272                 :   /// \brief Determine whether the next set of tokens contains a type-id.
     273                 :   ///
     274                 :   /// The context parameter states what context we're parsing right
     275                 :   /// now, which affects how this routine copes with the token
     276                 :   /// following the type-id. If the context is TypeIdInParens, we have
     277                 :   /// already parsed the '(' and we will cease lookahead when we hit
     278                 :   /// the corresponding ')'. If the context is
     279                 :   /// TypeIdAsTemplateArgument, we've already parsed the '<' or ','
     280                 :   /// before this template argument, and will cease lookahead when we
     281                 :   /// hit a '>', '>>' (in C++0x), or ','. Returns true for a type-id
     282                 :   /// and false for an expression.  If during the disambiguation
     283                 :   /// process a parsing error is encountered, the function returns
     284                 :   /// true to let the declaration parsing code handle it.
     285                 :   ///
     286                 :   /// type-id:
     287                 :   ///   type-specifier-seq abstract-declarator[opt]
     288                 :   ///
     289             6392: bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
     290                 : 
     291             6392:   isAmbiguous = false;
     292                 : 
     293                 :   // C++ 8.2p2:
     294                 :   // The ambiguity arising from the similarity between a function-style cast and
     295                 :   // a type-id can occur in different contexts. The ambiguity appears as a
     296                 :   // choice between a function-style cast expression and a declaration of a
     297                 :   // type. The resolution is that any construct that could possibly be a type-id
     298                 :   // in its syntactic context shall be considered a type-id.
     299                 : 
     300             6392:   TPResult TPR = isCXXDeclarationSpecifier();
                     6209: branch 2 taken
                      183: branch 3 taken
     301             6392:   if (TPR != TPResult::Ambiguous())
     302             6209:     return TPR != TPResult::False(); // Returns true for TPResult::True() or
     303                 :                                      // TPResult::Error().
     304                 : 
     305                 :   // FIXME: Add statistics about the number of ambiguous statements encountered
     306                 :   // and how they were resolved (number of declarations+number of expressions).
     307                 : 
     308                 :   // Ok, we have a simple-type-specifier/typename-specifier followed by a '('.
     309                 :   // We need tentative parsing...
     310                 : 
     311              183:   TentativeParsingAction PA(*this);
     312                 : 
     313                 :   // type-specifier-seq
                        0: branch 1 not taken
                      183: branch 2 taken
     314              183:   if (Tok.is(tok::kw_typeof))
     315                0:     TryParseTypeofSpecifier();
     316                 :   else
     317              183:     ConsumeToken();
                      183: branch 1 taken
                        0: branch 2 not taken
     318              183:   assert(Tok.is(tok::l_paren) && "Expected '('");
     319                 : 
     320                 :   // declarator
     321              183:   TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
     322                 : 
     323                 :   // In case of an error, let the declaration parsing code handle it.
                        0: branch 2 not taken
                      183: branch 3 taken
     324              183:   if (TPR == TPResult::Error())
     325                0:     TPR = TPResult::True();
     326                 : 
                      163: branch 2 taken
                       20: branch 3 taken
     327              183:   if (TPR == TPResult::Ambiguous()) {
     328                 :     // We are supposed to be inside parens, so if after the abstract declarator
     329                 :     // we encounter a ')' this is a type-id, otherwise it's an expression.
                       84: branch 0 taken
                       79: branch 1 taken
                       75: branch 3 taken
                        9: branch 4 taken
                       75: branch 5 taken
                       88: branch 6 taken
     330              163:     if (Context == TypeIdInParens && Tok.is(tok::r_paren)) {
     331               75:       TPR = TPResult::True();
     332               75:       isAmbiguous = true;
     333                 : 
     334                 :     // We are supposed to be inside a template argument, so if after
     335                 :     // the abstract declarator we encounter a '>', '>>' (in C++0x), or
     336                 :     // ',', this is a type-id. Otherwise, it's an expression.
                       79: branch 0 taken
                        9: branch 1 taken
                        7: branch 3 taken
                       72: branch 4 taken
                        0: branch 6 not taken
                        7: branch 7 taken
                        0: branch 9 not taken
                        0: branch 10 not taken
                        0: branch 12 not taken
                        0: branch 13 not taken
                       79: branch 14 taken
                        9: branch 15 taken
     337               88:     } else if (Context == TypeIdAsTemplateArgument &&
     338                 :                (Tok.is(tok::greater) || Tok.is(tok::comma) ||
     339                 :                 (getLang().CPlusPlus0x && Tok.is(tok::greatergreater)))) {
     340               79:       TPR = TPResult::True();
     341               79:       isAmbiguous = true;
     342                 : 
     343                 :     } else
     344                9:       TPR = TPResult::False();
     345                 :   }
     346                 : 
     347              183:   PA.Revert();
     348                 : 
                       29: branch 2 taken
                      154: branch 3 taken
                        0: branch 6 not taken
                       29: branch 7 taken
     349              183:   assert(TPR == TPResult::True() || TPR == TPResult::False());
     350              183:   return TPR == TPResult::True();
     351                 : }
     352                 : 
     353                 : /// isCXX0XAttributeSpecifier - returns true if this is a C++0x
     354                 : /// attribute-specifier. By default, unless in Obj-C++, only a cursory check is
     355                 : /// performed that will simply return true if a [[ is seen. Currently C++ has no
     356                 : /// syntactical ambiguities from this check, but it may inhibit error recovery.
     357                 : /// If CheckClosing is true, a check is made for closing ]] brackets.
     358                 : ///
     359                 : /// If given, After is set to the token after the attribute-specifier so that
     360                 : /// appropriate parsing decisions can be made; it is left untouched if false is
     361                 : /// returned.
     362                 : ///
     363                 : /// FIXME: If an error is in the closing ]] brackets, the program assumes
     364                 : /// the absence of an attribute-specifier, which can cause very yucky errors
     365                 : /// to occur.
     366                 : ///
     367                 : /// [C++0x] attribute-specifier:
     368                 : ///         '[' '[' attribute-list ']' ']'
     369                 : ///
     370                 : /// [C++0x] attribute-list:
     371                 : ///         attribute[opt]
     372                 : ///         attribute-list ',' attribute[opt]
     373                 : ///
     374                 : /// [C++0x] attribute:
     375                 : ///         attribute-token attribute-argument-clause[opt]
     376                 : ///
     377                 : /// [C++0x] attribute-token:
     378                 : ///         identifier
     379                 : ///         attribute-scoped-token
     380                 : ///
     381                 : /// [C++0x] attribute-scoped-token:
     382                 : ///         attribute-namespace '::' identifier
     383                 : ///
     384                 : /// [C++0x] attribute-namespace:
     385                 : ///         identifier
     386                 : ///
     387                 : /// [C++0x] attribute-argument-clause:
     388                 : ///         '(' balanced-token-seq ')'
     389                 : ///
     390                 : /// [C++0x] balanced-token-seq:
     391                 : ///         balanced-token
     392                 : ///         balanced-token-seq balanced-token
     393                 : ///
     394                 : /// [C++0x] balanced-token:
     395                 : ///         '(' balanced-token-seq ')'
     396                 : ///         '[' balanced-token-seq ']'
     397                 : ///         '{' balanced-token-seq '}'
     398                 : ///         any token but '(', ')', '[', ']', '{', or '}'
     399                 : bool Parser::isCXX0XAttributeSpecifier (bool CheckClosing,
     400            27929:                                         tok::TokenKind *After) {
                      800: branch 1 taken
                    27129: branch 2 taken
                      749: branch 5 taken
                       51: branch 6 taken
                    27878: branch 7 taken
                       51: branch 8 taken
     401            27929:   if (Tok.isNot(tok::l_square) || NextToken().isNot(tok::l_square))
     402            27878:     return false;
     403                 :   
     404                 :   // No tentative parsing if we don't need to look for ]]
                       38: branch 0 taken
                       13: branch 1 taken
                       38: branch 3 taken
                        0: branch 4 not taken
                       38: branch 5 taken
                       13: branch 6 taken
     405               51:   if (!CheckClosing && !getLang().ObjC1)
     406               38:     return true;
     407                 :   
     408                 :   struct TentativeReverter {
     409                 :     TentativeParsingAction PA;
     410                 : 
     411               13:     TentativeReverter (Parser& P)
     412               13:       : PA(P)
     413               13:     {}
     414               13:     ~TentativeReverter () {
     415               13:       PA.Revert();
     416               13:     }
     417               13:   } R(*this);
     418                 : 
     419                 :   // Opening brackets were checked for above.
     420               13:   ConsumeBracket();
     421               13:   ConsumeBracket();
     422                 : 
     423                 :   // SkipUntil will handle balanced tokens, which are guaranteed in attributes.
     424               13:   SkipUntil(tok::r_square, false);
     425                 : 
                        0: branch 1 not taken
                       13: branch 2 taken
     426               13:   if (Tok.isNot(tok::r_square))
     427                0:     return false;
     428               13:   ConsumeBracket();
     429                 : 
                        0: branch 0 not taken
                       13: branch 1 taken
     430               13:   if (After)
     431                0:     *After = Tok.getKind();
     432                 : 
     433               13:   return true;
     434                 : }
     435                 : 
     436                 : ///         declarator:
     437                 : ///           direct-declarator
     438                 : ///           ptr-operator declarator
     439                 : ///
     440                 : ///         direct-declarator:
     441                 : ///           declarator-id
     442                 : ///           direct-declarator '(' parameter-declaration-clause ')'
     443                 : ///                 cv-qualifier-seq[opt] exception-specification[opt]
     444                 : ///           direct-declarator '[' constant-expression[opt] ']'
     445                 : ///           '(' declarator ')'
     446                 : /// [GNU]     '(' attributes declarator ')'
     447                 : ///
     448                 : ///         abstract-declarator:
     449                 : ///           ptr-operator abstract-declarator[opt]
     450                 : ///           direct-abstract-declarator
     451                 : ///
     452                 : ///         direct-abstract-declarator:
     453                 : ///           direct-abstract-declarator[opt]
     454                 : ///           '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
     455                 : ///                 exception-specification[opt]
     456                 : ///           direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
     457                 : ///           '(' abstract-declarator ')'
     458                 : ///
     459                 : ///         ptr-operator:
     460                 : ///           '*' cv-qualifier-seq[opt]
     461                 : ///           '&'
     462                 : /// [C++0x]   '&&'                                                        [TODO]
     463                 : ///           '::'[opt] nested-name-specifier '*' cv-qualifier-seq[opt]
     464                 : ///
     465                 : ///         cv-qualifier-seq:
     466                 : ///           cv-qualifier cv-qualifier-seq[opt]
     467                 : ///
     468                 : ///         cv-qualifier:
     469                 : ///           'const'
     470                 : ///           'volatile'
     471                 : ///
     472                 : ///         declarator-id:
     473                 : ///           id-expression
     474                 : ///
     475                 : ///         id-expression:
     476                 : ///           unqualified-id
     477                 : ///           qualified-id                                                [TODO]
     478                 : ///
     479                 : ///         unqualified-id:
     480                 : ///           identifier
     481                 : ///           operator-function-id                                        [TODO]
     482                 : ///           conversion-function-id                                      [TODO]
     483                 : ///           '~' class-name                                              [TODO]
     484                 : ///           template-id                                                 [TODO]
     485                 : ///
     486                 : Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
     487             1228:                                             bool mayHaveIdentifier) {
     488                 :   // declarator:
     489                 :   //   direct-declarator
     490                 :   //   ptr-operator declarator
     491                 : 
     492              381:   while (1) {
                     1225: branch 1 taken
                        3: branch 2 taken
                      243: branch 4 taken
                      982: branch 5 taken
                      246: branch 6 taken
                      982: branch 7 taken
     493             1228:     if (Tok.is(tok::coloncolon) || Tok.is(tok::identifier))
     494              246:       TryAnnotateCXXScopeToken(true);
     495                 : 
                     1000: branch 1 taken
                      228: branch 2 taken
                      965: branch 4 taken
                       35: branch 5 taken
                      927: branch 7 taken
                       38: branch 8 taken
                       89: branch 10 taken
                      838: branch 11 taken
                       80: branch 14 taken
                        9: branch 15 taken
                      381: branch 16 taken
                      847: branch 17 taken
     496             1228:     if (Tok.is(tok::star) || Tok.is(tok::amp) || Tok.is(tok::caret) ||
     497                 :         (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::star))) {
     498                 :       // ptr-operator
     499              381:       ConsumeToken();
                      381: branch 1 taken
                        2: branch 2 taken
                      381: branch 4 taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                      381: branch 8 taken
                        2: branch 9 taken
                      381: branch 10 taken
     500              764:       while (Tok.is(tok::kw_const)    ||
     501                 :              Tok.is(tok::kw_volatile) ||
     502                 :              Tok.is(tok::kw_restrict))
     503                2:         ConsumeToken();
     504                 :     } else {
     505              847:       break;
     506                 :     }
     507                 :   }
     508                 : 
     509                 :   // direct-declarator:
     510                 :   // direct-abstract-declarator:
     511                 : 
                      650: branch 1 taken
                      197: branch 2 taken
                        9: branch 4 taken
                      641: branch 5 taken
                        8: branch 8 taken
                        1: branch 9 taken
                      194: branch 10 taken
                       11: branch 11 taken
                      194: branch 12 taken
                      653: branch 13 taken
     512              847:   if ((Tok.is(tok::identifier) ||
     513                 :        (Tok.is(tok::annot_cxxscope) && NextToken().is(tok::identifier))) &&
     514                 :       mayHaveIdentifier) {
     515                 :     // declarator-id
                        7: branch 1 taken
                      187: branch 2 taken
     516              194:     if (Tok.is(tok::annot_cxxscope))
     517                7:       ConsumeToken();
     518              194:     ConsumeToken();
                      466: branch 1 taken
                      187: branch 2 taken
     519              653:   } else if (Tok.is(tok::l_paren)) {
     520              466:     ConsumeParen();
                      281: branch 0 taken
                      185: branch 1 taken
                      233: branch 3 taken
                       48: branch 4 taken
                      232: branch 6 taken
                        1: branch 7 taken
                       28: branch 9 taken
                      204: branch 10 taken
                       77: branch 11 taken
                      389: branch 12 taken
     521              466:     if (mayBeAbstract &&
     522                 :         (Tok.is(tok::r_paren) ||       // 'int()' is a function.
     523                 :          Tok.is(tok::ellipsis) ||      // 'int(...)' is a function.
     524                 :          isDeclarationSpecifier())) {   // 'int(int)' is a function.
     525                 :       // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
     526                 :       //        exception-specification[opt]
     527               77:       TPResult TPR = TryParseFunctionDeclarator();
                        0: branch 2 not taken
                       77: branch 3 taken
     528               77:       if (TPR != TPResult::Ambiguous())
     529                0:         return TPR;
     530                 :     } else {
     531                 :       // '(' declarator ')'
     532                 :       // '(' attributes declarator ')'
     533                 :       // '(' abstract-declarator ')'
                        0: branch 1 not taken
                      389: branch 2 taken
     534              389:       if (Tok.is(tok::kw___attribute))
     535                0:         return TPResult::True(); // attributes indicate declaration
     536              389:       TPResult TPR = TryParseDeclarator(mayBeAbstract, mayHaveIdentifier);
                       37: branch 2 taken
                      352: branch 3 taken
     537              389:       if (TPR != TPResult::Ambiguous())
     538               37:         return TPR;
                       27: branch 1 taken
                      325: branch 2 taken
     539              352:       if (Tok.isNot(tok::r_paren))
     540               27:         return TPResult::False();
     541              325:       ConsumeParen();
     542                 :     }
                       38: branch 0 taken
                      149: branch 1 taken
     543              187:   } else if (!mayBeAbstract) {
     544               38:     return TPResult::False();
     545                 :   }
     546                 : 
     547              298:   while (1) {
     548             1043:     TPResult TPR(TPResult::Ambiguous());
     549                 : 
                      256: branch 1 taken
                      787: branch 2 taken
     550             1043:     if (Tok.is(tok::l_paren)) {
     551                 :       // Check whether we have a function declarator or a possible ctor-style
     552                 :       // initializer that follows the declarator. Note that ctor-style
     553                 :       // initializers are not possible in contexts where abstract declarators
     554                 :       // are allowed.
                      115: branch 0 taken
                      141: branch 1 taken
                        1: branch 3 taken
                      114: branch 4 taken
                      255: branch 5 taken
                        1: branch 6 taken
     555              256:       if (!mayBeAbstract && !isCXXFunctionDeclarator(false/*warnIfAmbiguous*/))
     556                1:         break;
     557                 : 
     558                 :       // direct-declarator '(' parameter-declaration-clause ')'
     559                 :       //        cv-qualifier-seq[opt] exception-specification[opt]
     560              255:       ConsumeParen();
     561              255:       TPR = TryParseFunctionDeclarator();
                      744: branch 1 taken
                       43: branch 2 taken
     562              787:     } else if (Tok.is(tok::l_square)) {
     563                 :       // direct-declarator '[' constant-expression[opt] ']'
     564                 :       // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
     565               43:       TPR = TryParseBracketDeclarator();
     566                 :     } else {
     567              744:       break;
     568                 :     }
     569                 : 
                        0: branch 2 not taken
                      298: branch 3 taken
     570              298:     if (TPR != TPResult::Ambiguous())
     571                0:       return TPR;
     572                 :   }
     573                 : 
     574              745:   return TPResult::Ambiguous();
     575                 : }
     576                 : 
     577                 : /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a declaration
     578                 : /// specifier, TPResult::False() if it is not, TPResult::Ambiguous() if it could
     579                 : /// be either a decl-specifier or a function-style cast, and TPResult::Error()
     580                 : /// if a parsing error was found and reported.
     581                 : ///
     582                 : ///         decl-specifier:
     583                 : ///           storage-class-specifier
     584                 : ///           type-specifier
     585                 : ///           function-specifier
     586                 : ///           'friend'
     587                 : ///           'typedef'
     588                 : /// [C++0x]   'constexpr'
     589                 : /// [GNU]     attributes declaration-specifiers[opt]
     590                 : ///
     591                 : ///         storage-class-specifier:
     592                 : ///           'register'
     593                 : ///           'static'
     594                 : ///           'extern'
     595                 : ///           'mutable'
     596                 : ///           'auto'
     597                 : /// [GNU]     '__thread'
     598                 : ///
     599                 : ///         function-specifier:
     600                 : ///           'inline'
     601                 : ///           'virtual'
     602                 : ///           'explicit'
     603                 : ///
     604                 : ///         typedef-name:
     605                 : ///           identifier
     606                 : ///
     607                 : ///         type-specifier:
     608                 : ///           simple-type-specifier
     609                 : ///           class-specifier
     610                 : ///           enum-specifier
     611                 : ///           elaborated-type-specifier
     612                 : ///           typename-specifier
     613                 : ///           cv-qualifier
     614                 : ///
     615                 : ///         simple-type-specifier:
     616                 : ///           '::'[opt] nested-name-specifier[opt] type-name
     617                 : ///           '::'[opt] nested-name-specifier 'template'
     618                 : ///                 simple-template-id                              [TODO]
     619                 : ///           'char'
     620                 : ///           'wchar_t'
     621                 : ///           'bool'
     622                 : ///           'short'
     623                 : ///           'int'
     624                 : ///           'long'
     625                 : ///           'signed'
     626                 : ///           'unsigned'
     627                 : ///           'float'
     628                 : ///           'double'
     629                 : ///           'void'
     630                 : /// [GNU]     typeof-specifier
     631                 : /// [GNU]     '_Complex'
     632                 : /// [C++0x]   'auto'                                                [TODO]
     633                 : /// [C++0x]   'decltype' ( expression )
     634                 : ///
     635                 : ///         type-name:
     636                 : ///           class-name
     637                 : ///           enum-name
     638                 : ///           typedef-name
     639                 : ///
     640                 : ///         elaborated-type-specifier:
     641                 : ///           class-key '::'[opt] nested-name-specifier[opt] identifier
     642                 : ///           class-key '::'[opt] nested-name-specifier[opt] 'template'[opt]
     643                 : ///               simple-template-id
     644                 : ///           'enum' '::'[opt] nested-name-specifier[opt] identifier
     645                 : ///
     646                 : ///         enum-name:
     647                 : ///           identifier
     648                 : ///
     649                 : ///         enum-specifier:
     650                 : ///           'enum' identifier[opt] '{' enumerator-list[opt] '}'
     651                 : ///           'enum' identifier[opt] '{' enumerator-list ',' '}'
     652                 : ///
     653                 : ///         class-specifier:
     654                 : ///           class-head '{' member-specification[opt] '}'
     655                 : ///
     656                 : ///         class-head:
     657                 : ///           class-key identifier[opt] base-clause[opt]
     658                 : ///           class-key nested-name-specifier identifier base-clause[opt]
     659                 : ///           class-key nested-name-specifier[opt] simple-template-id
     660                 : ///               base-clause[opt]
     661                 : ///
     662                 : ///         class-key:
     663                 : ///           'class'
     664                 : ///           'struct'
     665                 : ///           'union'
     666                 : ///
     667                 : ///         cv-qualifier:
     668                 : ///           'const'
     669                 : ///           'volatile'
     670                 : /// [GNU]     restrict
     671                 : ///
     672            18971: Parser::TPResult Parser::isCXXDeclarationSpecifier() {
                     6721: branch 1 taken
                       33: branch 2 taken
                       16: branch 3 taken
                      737: branch 4 taken
                        1: branch 5 taken
                       10: branch 6 taken
                      163: branch 7 taken
                     9079: branch 8 taken
                       22: branch 9 taken
                        8: branch 10 taken
                     2181: branch 11 taken
     673            18971:   switch (Tok.getKind()) {
     674                 :   case tok::identifier:   // foo::bar
     675                 :     // Check for need to substitute AltiVec __vector keyword
     676                 :     // for "vector" identifier.
                        3: branch 1 taken
                     6718: branch 2 taken
     677             6721:     if (TryAltiVecVectorToken())
     678                3:       return TPResult::True();
     679                 :     // Fall through.
     680                 :   case tok::kw_typename:  // typename T::type
     681                 :     // Annotate typenames and C++ scope specifiers.  If we get one, just
     682                 :     // recurse to handle whatever we get.
                     4190: branch 1 taken
                     2561: branch 2 taken
     683             6751:     if (TryAnnotateTypeOrScopeToken())
     684             4190:       return isCXXDeclarationSpecifier();
     685                 :     // Otherwise, not a typename.
     686             2561:     return TPResult::False();
     687                 : 
     688                 :   case tok::coloncolon: {    // ::foo::bar
     689               16:     const Token &Next = NextToken();
                       16: branch 1 taken
                        0: branch 2 not taken
                        2: branch 4 taken
                       14: branch 5 taken
                        2: branch 6 taken
                       14: branch 7 taken
     690               16:     if (Next.is(tok::kw_new) ||    // ::new
     691                 :         Next.is(tok::kw_delete))   // ::delete
     692                2:       return TPResult::False();
     693                 : 
     694                 :     // Annotate typenames and C++ scope specifiers.  If we get one, just
     695                 :     // recurse to handle whatever we get.
                       14: branch 1 taken
                        0: branch 2 not taken
     696               14:     if (TryAnnotateTypeOrScopeToken())
     697               14:       return isCXXDeclarationSpecifier();
     698                 :     // Otherwise, not a typename.
     699                0:     return TPResult::False();
     700                 :   }
     701                 :       
     702                 :     // decl-specifier:
     703                 :     //   storage-class-specifier
     704                 :     //   type-specifier
     705                 :     //   function-specifier
     706                 :     //   'friend'
     707                 :     //   'typedef'
     708                 :     //   'constexpr'
     709                 :   case tok::kw_friend:
     710                 :   case tok::kw_typedef:
     711                 :   case tok::kw_constexpr:
     712                 :     // storage-class-specifier
     713                 :   case tok::kw_register:
     714                 :   case tok::kw_static:
     715                 :   case tok::kw_extern:
     716                 :   case tok::kw_mutable:
     717                 :   case tok::kw_auto:
     718                 :   case tok::kw___thread:
     719                 :     // function-specifier
     720                 :   case tok::kw_inline:
     721                 :   case tok::kw_virtual:
     722                 :   case tok::kw_explicit:
     723                 : 
     724                 :     // type-specifier:
     725                 :     //   simple-type-specifier
     726                 :     //   class-specifier
     727                 :     //   enum-specifier
     728                 :     //   elaborated-type-specifier
     729                 :     //   typename-specifier
     730                 :     //   cv-qualifier
     731                 : 
     732                 :     // class-specifier
     733                 :     // elaborated-type-specifier
     734                 :   case tok::kw_class:
     735                 :   case tok::kw_struct:
     736                 :   case tok::kw_union:
     737                 :     // enum-specifier
     738                 :   case tok::kw_enum:
     739                 :     // cv-qualifier
     740                 :   case tok::kw_const:
     741                 :   case tok::kw_volatile:
     742                 : 
     743                 :     // GNU
     744                 :   case tok::kw_restrict:
     745                 :   case tok::kw__Complex:
     746                 :   case tok::kw___attribute:
     747              737:     return TPResult::True();
     748                 : 
     749                 :     // Microsoft
     750                 :   case tok::kw___declspec:
     751                 :   case tok::kw___cdecl:
     752                 :   case tok::kw___stdcall:
     753                 :   case tok::kw___fastcall:
     754                 :   case tok::kw___w64:
     755                 :   case tok::kw___ptr64:
     756                 :   case tok::kw___forceinline:
     757                1:     return TPResult::True();
     758                 :   
     759                 :     // AltiVec
     760                 :   case tok::kw___vector:
     761               10:     return TPResult::True();
     762                 : 
     763                 :   case tok::annot_cxxscope: // foo::bar or ::foo::bar, but already parsed
     764                 :     // We've already annotated a scope; try to annotate a type.
                      163: branch 1 taken
                        0: branch 2 not taken
                      155: branch 4 taken
                        8: branch 5 taken
                      155: branch 6 taken
                        8: branch 7 taken
     765              163:     if (!(TryAnnotateTypeOrScopeToken() && Tok.is(tok::annot_typename)))
     766              155:       return TPResult::False();
     767                 :     // If that succeeded, fallthrough into the generic simple-type-id case.
     768                 : 
     769                 :     // The ambiguity resides in a simple-type-specifier/typename-specifier
     770                 :     // followed by a '('. The '(' could either be the start of:
     771                 :     //
     772                 :     //   direct-declarator:
     773                 :     //     '(' declarator ')'
     774                 :     //
     775                 :     //   direct-abstract-declarator:
     776                 :     //     '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
     777                 :     //              exception-specification[opt]
     778                 :     //     '(' abstract-declarator ')'
     779                 :     //
     780                 :     // or part of a function-style cast expression:
     781                 :     //
     782                 :     //     simple-type-specifier '(' expression-list[opt] ')'
     783                 :     //
     784                 : 
     785                 :     // simple-type-specifier:
     786                 : 
     787                 :   case tok::kw_char:
     788                 :   case tok::kw_wchar_t:
     789                 :   case tok::kw_char16_t:
     790                 :   case tok::kw_char32_t:
     791                 :   case tok::kw_bool:
     792                 :   case tok::kw_short:
     793                 :   case tok::kw_int:
     794                 :   case tok::kw_long:
     795                 :   case tok::kw_signed:
     796                 :   case tok::kw_unsigned:
     797                 :   case tok::kw_float:
     798                 :   case tok::kw_double:
     799                 :   case tok::kw_void:
     800                 :   case tok::annot_typename:
                      616: branch 2 taken
                     8471: branch 3 taken
     801             9087:     if (NextToken().is(tok::l_paren))
     802              616:       return TPResult::Ambiguous();
     803                 : 
     804             8471:     return TPResult::True();
     805                 : 
     806                 :   // GNU typeof support.
     807                 :   case tok::kw_typeof: {
                        1: branch 2 taken
                       21: branch 3 taken
     808               22:     if (NextToken().isNot(tok::l_paren))
     809                1:       return TPResult::True();
     810                 : 
     811               21:     TentativeParsingAction PA(*this);
     812                 : 
     813               21:     TPResult TPR = TryParseTypeofSpecifier();
     814               21:     bool isFollowedByParen = Tok.is(tok::l_paren);
     815                 : 
     816               21:     PA.Revert();
     817                 : 
                        0: branch 2 not taken
                       21: branch 3 taken
     818               21:     if (TPR == TPResult::Error())
     819                0:       return TPResult::Error();
     820                 : 
                        4: branch 0 taken
                       17: branch 1 taken
     821               21:     if (isFollowedByParen)
     822                4:       return TPResult::Ambiguous();
     823                 : 
     824               17:     return TPResult::True();
     825                 :   }
     826                 : 
     827                 :   // C++0x decltype support.
     828                 :   case tok::kw_decltype:
     829                8:     return TPResult::True();
     830                 : 
     831                 :   default:
     832             2181:     return TPResult::False();
     833                 :   }
     834                 : }
     835                 : 
     836                 : /// [GNU] typeof-specifier:
     837                 : ///         'typeof' '(' expressions ')'
     838                 : ///         'typeof' '(' type-name ')'
     839                 : ///
     840               23: Parser::TPResult Parser::TryParseTypeofSpecifier() {
                       23: branch 1 taken
                        0: branch 2 not taken
     841               23:   assert(Tok.is(tok::kw_typeof) && "Expected 'typeof'!");
     842               23:   ConsumeToken();
     843                 : 
                       23: branch 1 taken
                        0: branch 2 not taken
     844               23:   assert(Tok.is(tok::l_paren) && "Expected '('");
     845                 :   // Parse through the parens after 'typeof'.
     846               23:   ConsumeParen();
                        0: branch 1 not taken
                       23: branch 2 taken
     847               23:   if (!SkipUntil(tok::r_paren))
     848                0:     return TPResult::Error();
     849                 : 
     850               23:   return TPResult::Ambiguous();
     851                 : }
     852                 : 
     853             2862: Parser::TPResult Parser::TryParseDeclarationSpecifier() {
     854             2862:   TPResult TPR = isCXXDeclarationSpecifier();
                     2764: branch 2 taken
                       98: branch 3 taken
     855             2862:   if (TPR != TPResult::Ambiguous())
     856             2764:     return TPR;
     857                 : 
                        0: branch 1 not taken
                       98: branch 2 taken
     858               98:   if (Tok.is(tok::kw_typeof))
     859                0:     TryParseTypeofSpecifier();
     860                 :   else
     861               98:     ConsumeToken();
     862                 : 
                       98: branch 1 taken
                        0: branch 2 not taken
     863               98:   assert(Tok.is(tok::l_paren) && "Expected '('!");
     864               98:   return TPResult::Ambiguous();
     865                 : }
     866                 : 
     867                 : /// isCXXFunctionDeclarator - Disambiguates between a function declarator or
     868                 : /// a constructor-style initializer, when parsing declaration statements.
     869                 : /// Returns true for function declarator and false for constructor-style
     870                 : /// initializer.
     871                 : /// If during the disambiguation process a parsing error is encountered,
     872                 : /// the function returns true to let the declaration parsing code handle it.
     873                 : ///
     874                 : /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
     875                 : ///         exception-specification[opt]
     876                 : ///
     877             4190: bool Parser::isCXXFunctionDeclarator(bool warnIfAmbiguous) {
     878                 : 
     879                 :   // C++ 8.2p1:
     880                 :   // The ambiguity arising from the similarity between a function-style cast and
     881                 :   // a declaration mentioned in 6.8 can also occur in the context of a
     882                 :   // declaration. In that context, the choice is between a function declaration
     883                 :   // with a redundant set of parentheses around a parameter name and an object
     884                 :   // declaration with a function-style cast as the initializer. Just as for the
     885                 :   // ambiguities mentioned in 6.8, the resolution is to consider any construct
     886                 :   // that could possibly be a declaration a declaration.
     887                 : 
     888             4190:   TentativeParsingAction PA(*this);
     889                 : 
     890             4190:   ConsumeParen();
     891             4190:   TPResult TPR = TryParseParameterDeclarationClause();
                       88: branch 2 taken
                     4102: branch 3 taken
                        0: branch 5 not taken
                       88: branch 6 taken
                        0: branch 7 not taken
                     4190: branch 8 taken
     892             4190:   if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
     893                0:     TPR = TPResult::False();
     894                 : 
     895             4190:   SourceLocation TPLoc = Tok.getLocation();
     896             4190:   PA.Revert();
     897                 : 
     898                 :   // In case of an error, let the declaration parsing code handle it.
                        0: branch 2 not taken
                     4190: branch 3 taken
     899             4190:   if (TPR == TPResult::Error())
     900                0:     return true;
     901                 : 
                       88: branch 2 taken
                     4102: branch 3 taken
     902             4190:   if (TPR == TPResult::Ambiguous()) {
     903                 :     // Function declarator has precedence over constructor-style initializer.
     904                 :     // Emit a warning just in case the author intended a variable definition.
                       10: branch 0 taken
                       78: branch 1 taken
     905               88:     if (warnIfAmbiguous)
     906                 :       Diag(Tok, diag::warn_parens_disambiguated_as_function_decl)
     907               10:         << SourceRange(Tok.getLocation(), TPLoc);
     908               88:     return true;
     909                 :   }
     910                 : 
     911             4102:   return TPR == TPResult::True();
     912                 : }
     913                 : 
     914                 : /// parameter-declaration-clause:
     915                 : ///   parameter-declaration-list[opt] '...'[opt]
     916                 : ///   parameter-declaration-list ',' '...'
     917                 : ///
     918                 : /// parameter-declaration-list:
     919                 : ///   parameter-declaration
     920                 : ///   parameter-declaration-list ',' parameter-declaration
     921                 : ///
     922                 : /// parameter-declaration:
     923                 : ///   decl-specifier-seq declarator
     924                 : ///   decl-specifier-seq declarator '=' assignment-expression
     925                 : ///   decl-specifier-seq abstract-declarator[opt]
     926                 : ///   decl-specifier-seq abstract-declarator[opt] '=' assignment-expression
     927                 : ///
     928             4522: Parser::TPResult Parser::TryParseParameterDeclarationClause() {
     929                 : 
                     1604: branch 1 taken
                     2918: branch 2 taken
     930             4522:   if (Tok.is(tok::r_paren))
     931             1604:     return TPResult::True();
     932                 : 
     933                 :   //   parameter-declaration-list[opt] '...'[opt]
     934                 :   //   parameter-declaration-list ',' '...'
     935                 :   //
     936                 :   // parameter-declaration-list:
     937                 :   //   parameter-declaration
     938                 :   //   parameter-declaration-list ',' parameter-declaration
     939                 :   //
     940                5:   while (1) {
     941                 :     // '...'[opt]
                       61: branch 1 taken
                     2862: branch 2 taken
     942             2923:     if (Tok.is(tok::ellipsis)) {
     943               61:       ConsumeToken();
     944               61:       return TPResult::True(); // '...' is a sign of a function declarator.
     945                 :     }
     946                 : 
     947                 :     // decl-specifier-seq
     948             2862:     TPResult TPR = TryParseDeclarationSpecifier();
                     2764: branch 2 taken
                       98: branch 3 taken
     949             2862:     if (TPR != TPResult::Ambiguous())
     950             2764:       return TPR;
     951                 : 
     952                 :     // declarator
     953                 :     // abstract-declarator[opt]
     954               98:     TPR = TryParseDeclarator(true/*mayBeAbstract*/);
                        0: branch 2 not taken
                       98: branch 3 taken
     955               98:     if (TPR != TPResult::Ambiguous())
     956                0:       return TPR;
     957                 : 
                        0: branch 1 not taken
                       98: branch 2 taken
     958               98:     if (Tok.is(tok::equal)) {
     959                 :       // '=' assignment-expression
     960                 :       // Parse through assignment-expression.
     961                0:       tok::TokenKind StopToks[3] ={ tok::comma, tok::ellipsis, tok::r_paren };
                        0: branch 1 not taken
                        0: branch 2 not taken
     962                0:       if (!SkipUntil(StopToks, 3, true/*StopAtSemi*/, true/*DontConsume*/))
     963                0:         return TPResult::Error();
     964                 :     }
     965                 : 
                        0: branch 1 not taken
                       98: branch 2 taken
     966               98:     if (Tok.is(tok::ellipsis)) {
     967                0:       ConsumeToken();
     968                0:       return TPResult::True(); // '...' is a sign of a function declarator.
     969                 :     }
     970                 : 
                        5: branch 1 taken
                       93: branch 2 taken
     971               98:     if (Tok.isNot(tok::comma))
     972               93:       break;
     973                5:     ConsumeToken(); // the comma.
     974                 :   }
     975                 : 
     976               93:   return TPResult::Ambiguous();
     977                 : }
     978                 : 
     979                 : /// TryParseFunctionDeclarator - We parsed a '(' and we want to try to continue
     980                 : /// parsing as a function declarator.
     981                 : /// If TryParseFunctionDeclarator fully parsed the function declarator, it will
     982                 : /// return TPResult::Ambiguous(), otherwise it will return either False() or
     983                 : /// Error().
     984                 : ///
     985                 : /// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
     986                 : ///         exception-specification[opt]
     987                 : ///
     988                 : /// exception-specification:
     989                 : ///   'throw' '(' type-id-list[opt] ')'
     990                 : ///
     991              332: Parser::TPResult Parser::TryParseFunctionDeclarator() {
     992                 : 
     993                 :   // The '(' is already parsed.
     994                 : 
     995              332:   TPResult TPR = TryParseParameterDeclarationClause();
                        5: branch 2 taken
                      327: branch 3 taken
                        0: branch 5 not taken
                        5: branch 6 taken
                        0: branch 7 not taken
                      332: branch 8 taken
     996              332:   if (TPR == TPResult::Ambiguous() && Tok.isNot(tok::r_paren))
     997                0:     TPR = TPResult::False();
     998                 : 
                      332: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                      332: branch 7 taken
                        0: branch 8 not taken
                      332: branch 9 taken
     999              332:   if (TPR == TPResult::False() || TPR == TPResult::Error())
    1000                0:     return TPR;
    1001                 : 
    1002                 :   // Parse through the parens.
                        0: branch 1 not taken
                      332: branch 2 taken
    1003              332:   if (!SkipUntil(tok::r_paren))
    1004                0:     return TPResult::Error();
    1005                 : 
    1006                 :   // cv-qualifier-seq
                      336: branch 1 taken
                        9: branch 2 taken
                      332: branch 4 taken
                        4: branch 5 taken
                        0: branch 7 not taken
                      332: branch 8 taken
                       13: branch 9 taken
                      332: branch 10 taken
    1007              677:   while (Tok.is(tok::kw_const)    ||
    1008                 :          Tok.is(tok::kw_volatile) ||
    1009                 :          Tok.is(tok::kw_restrict)   )
    1010               13:     ConsumeToken();
    1011                 : 
    1012                 :   // exception-specification
                       22: branch 1 taken
                      310: branch 2 taken
    1013              332:   if (Tok.is(tok::kw_throw)) {
    1014               22:     ConsumeToken();
                        0: branch 1 not taken
                       22: branch 2 taken
    1015               22:     if (Tok.isNot(tok::l_paren))
    1016                0:       return TPResult::Error();
    1017                 : 
    1018                 :     // Parse through the parens after 'throw'.
    1019               22:     ConsumeParen();
                        0: branch 1 not taken
                       22: branch 2 taken
    1020               22:     if (!SkipUntil(tok::r_paren))
    1021                0:       return TPResult::Error();
    1022                 :   }
    1023                 : 
    1024              332:   return TPResult::Ambiguous();
    1025                 : }
    1026                 : 
    1027                 : /// '[' constant-expression[opt] ']'
    1028                 : ///
    1029               43: Parser::TPResult Parser::TryParseBracketDeclarator() {
    1030               43:   ConsumeBracket();
                        0: branch 1 not taken
                       43: branch 2 taken
    1031               43:   if (!SkipUntil(tok::r_square))
    1032                0:     return TPResult::Error();
    1033                 : 
    1034               43:   return TPResult::Ambiguous();
    1035                 : }

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