zcov: / lib/Parse/ParseExprCXX.cpp


Files: 1 Branches Taken: 73.6% 338 / 459
Generated: 2010-02-10 01:31 Branches Executed: 97.4% 447 / 459
Line Coverage: 85.5% 519 / 607


Programs: 2 Runs 3018


       1                 : //===--- ParseExprCXX.cpp - C++ Expression 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 Expression parsing implementation for C++.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Parse/ParseDiagnostic.h"
      15                 : #include "clang/Parse/Parser.h"
      16                 : #include "clang/Parse/DeclSpec.h"
      17                 : #include "clang/Parse/Template.h"
      18                 : #include "llvm/Support/ErrorHandling.h"
      19                 : 
      20                 : using namespace clang;
      21                 : 
      22                 : /// \brief Parse global scope or nested-name-specifier if present.
      23                 : ///
      24                 : /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which
      25                 : /// may be preceded by '::'). Note that this routine will not parse ::new or
      26                 : /// ::delete; it will just leave them in the token stream.
      27                 : ///
      28                 : ///       '::'[opt] nested-name-specifier
      29                 : ///       '::'
      30                 : ///
      31                 : ///       nested-name-specifier:
      32                 : ///         type-name '::'
      33                 : ///         namespace-name '::'
      34                 : ///         nested-name-specifier identifier '::'
      35                 : ///         nested-name-specifier 'template'[opt] simple-template-id '::'
      36                 : ///
      37                 : ///
      38                 : /// \param SS the scope specifier that will be set to the parsed
      39                 : /// nested-name-specifier (or empty)
      40                 : ///
      41                 : /// \param ObjectType if this nested-name-specifier is being parsed following
      42                 : /// the "." or "->" of a member access expression, this parameter provides the
      43                 : /// type of the object whose members are being accessed.
      44                 : ///
      45                 : /// \param EnteringContext whether we will be entering into the context of
      46                 : /// the nested-name-specifier after parsing it.
      47                 : ///
      48                 : /// \returns true if a scope specifier was parsed.
      49                 : bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS,
      50                 :                                             Action::TypeTy *ObjectType,
      51            71336:                                             bool EnteringContext) {
      52                 :   assert(getLang().CPlusPlus &&
                    71336: branch 1 taken
                        0: branch 2 not taken
      53            71336:          "Call sites of this function should be guarded by checking for C++");
      54                 : 
                     1425: branch 1 taken
                    69911: branch 2 taken
      55            71336:   if (Tok.is(tok::annot_cxxscope)) {
      56             1425:     SS.setScopeRep(Tok.getAnnotationValue());
      57             1425:     SS.setRange(Tok.getAnnotationRange());
      58             1425:     ConsumeToken();
      59             1425:     return true;
      60                 :   }
      61                 : 
      62            69911:   bool HasScopeSpecifier = false;
      63                 : 
                       89: branch 1 taken
                    69822: branch 2 taken
      64            69911:   if (Tok.is(tok::coloncolon)) {
      65                 :     // ::new and ::delete aren't nested-name-specifiers.
      66               89:     tok::TokenKind NextKind = NextToken().getKind();
                       87: branch 0 taken
                        2: branch 1 taken
                        2: branch 2 taken
                       85: branch 3 taken
      67               89:     if (NextKind == tok::kw_new || NextKind == tok::kw_delete)
      68                4:       return false;
      69                 : 
      70                 :     // '::' - Global scope qualifier.
      71               85:     SourceLocation CCLoc = ConsumeToken();
      72               85:     SS.setBeginLoc(CCLoc);
      73               85:     SS.setScopeRep(Actions.ActOnCXXGlobalScopeSpecifier(CurScope, CCLoc));
      74               85:     SS.setEndLoc(CCLoc);
      75               85:     HasScopeSpecifier = true;
      76                 :   }
      77                 : 
      78             4953:   while (true) {
                     2819: branch 0 taken
                    72041: branch 1 taken
      79            74860:     if (HasScopeSpecifier) {
      80                 :       // C++ [basic.lookup.classref]p5:
      81                 :       //   If the qualified-id has the form
      82                 :       //
      83                 :       //       ::class-name-or-namespace-name::...
      84                 :       //
      85                 :       //   the class-name-or-namespace-name is looked up in global scope as a
      86                 :       //   class-name or namespace-name.
      87                 :       //
      88                 :       // To implement this, we clear out the object type as soon as we've
      89                 :       // seen a leading '::' or part of a nested-name-specifier.
      90             2819:       ObjectType = 0;
      91                 :       
                        4: branch 1 taken
                     2815: branch 2 taken
      92             2819:       if (Tok.is(tok::code_completion)) {
      93                 :         // Code completion for a nested-name-specifier, where the code
      94                 :         // code completion token follows the '::'.
      95                4:         Actions.CodeCompleteQualifiedId(CurScope, SS, EnteringContext);
      96                4:         ConsumeToken();
      97                 :       }
      98                 :     }
      99                 : 
     100                 :     // nested-name-specifier:
     101                 :     //   nested-name-specifier 'template'[opt] simple-template-id '::'
     102                 : 
     103                 :     // Parse the optional 'template' keyword, then make sure we have
     104                 :     // 'identifier <' after it.
                       52: branch 1 taken
                    74808: branch 2 taken
     105            74860:     if (Tok.is(tok::kw_template)) {
     106                 :       // If we don't have a scope specifier or an object type, this isn't a
     107                 :       // nested-name-specifier, since they aren't allowed to start with
     108                 :       // 'template'.
                        5: branch 0 taken
                       47: branch 1 taken
                        4: branch 2 taken
                        1: branch 3 taken
     109               52:       if (!HasScopeSpecifier && !ObjectType)
     110                1:         break;
     111                 : 
     112               51:       TentativeParsingAction TPA(*this);
     113               51:       SourceLocation TemplateKWLoc = ConsumeToken();
     114                 :       
     115               51:       UnqualifiedId TemplateName;
                       48: branch 1 taken
                        3: branch 2 taken
     116               51:       if (Tok.is(tok::identifier)) {
     117                 :         // Consume the identifier.
     118               48:         TemplateName.setIdentifier(Tok.getIdentifierInfo(), Tok.getLocation());
     119               48:         ConsumeToken();
                        2: branch 1 taken
                        1: branch 2 taken
     120                3:       } else if (Tok.is(tok::kw_operator)) {
                        0: branch 1 not taken
                        2: branch 2 taken
     121                2:         if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, 
     122                 :                                        TemplateName)) {
     123                0:           TPA.Commit();
     124                7:           break;
     125                 :         }
     126                 :         
                        0: branch 1 not taken
                        2: branch 2 taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        2: branch 7 taken
     127                2:         if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId &&
     128                 :             TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) {
     129                 :           Diag(TemplateName.getSourceRange().getBegin(),
     130                 :                diag::err_id_after_template_in_nested_name_spec)
     131                0:             << TemplateName.getSourceRange();
     132                0:           TPA.Commit();
     133                 :           break;
     134                 :         }
     135                 :       } else {
     136                1:         TPA.Revert();
     137                 :         break;
     138                 :       }
     139                 : 
     140                 :       // If the next token is not '<', we have a qualified-id that refers
     141                 :       // to a template name, such as T::template apply, but is not a 
     142                 :       // template-id.
                        2: branch 1 taken
                       48: branch 2 taken
     143               50:       if (Tok.isNot(tok::less)) {
     144                2:         TPA.Revert();
     145                 :         break;
     146                 :       }        
     147                 :       
     148                 :       // Commit to parsing the template-id.
     149               48:       TPA.Commit();
     150                 :       TemplateTy Template
     151                 :         = Actions.ActOnDependentTemplateName(TemplateKWLoc, SS, TemplateName,
     152               48:                                              ObjectType, EnteringContext);
                        4: branch 1 taken
                       44: branch 2 taken
     153               48:       if (!Template)
     154                 :         break;
                        0: branch 1 not taken
                       44: branch 2 taken
     155               44:       if (AnnotateTemplateIdToken(Template, TNK_Dependent_template_name,
     156                 :                                   &SS, TemplateName, TemplateKWLoc, false))
     157                 :         break;
     158                 : 
                        7: branch 1 taken
                       44: branch 2 taken
                        7: branch 4 taken
                       44: branch 5 taken
     159               95:       continue;
     160                 :     }
     161                 : 
                     2735: branch 1 taken
                    72073: branch 2 taken
                      795: branch 5 taken
                     1940: branch 6 taken
                      795: branch 7 taken
                    74013: branch 8 taken
     162            74808:     if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) {
     163                 :       // We have
     164                 :       //
     165                 :       //   simple-template-id '::'
     166                 :       //
     167                 :       // So we need to check whether the simple-template-id is of the
     168                 :       // right kind (it should name a type or be dependent), and then
     169                 :       // convert it into a type within the nested-name-specifier.
     170                 :       TemplateIdAnnotation *TemplateId
     171              795:         = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     172                 : 
                       12: branch 0 taken
                      783: branch 1 taken
                       12: branch 2 taken
                        0: branch 3 not taken
     173              795:       if (TemplateId->Kind == TNK_Type_template ||
     174                 :           TemplateId->Kind == TNK_Dependent_template_name) {
     175              795:         AnnotateTemplateIdTokenAsType(&SS);
     176                 : 
     177                 :         assert(Tok.is(tok::annot_typename) &&
                      795: branch 1 taken
                        0: branch 2 not taken
     178              795:                "AnnotateTemplateIdTokenAsType isn't working");
     179              795:         Token TypeToken = Tok;
     180              795:         ConsumeToken();
                      795: branch 1 taken
                        0: branch 2 not taken
     181              795:         assert(Tok.is(tok::coloncolon) && "NextToken() not working properly!");
     182              795:         SourceLocation CCLoc = ConsumeToken();
     183                 : 
                      670: branch 0 taken
                      125: branch 1 taken
     184              795:         if (!HasScopeSpecifier) {
     185              670:           SS.setBeginLoc(TypeToken.getLocation());
     186              670:           HasScopeSpecifier = true;
     187                 :         }
     188                 : 
                      795: branch 1 taken
                        0: branch 2 not taken
     189              795:         if (TypeToken.getAnnotationValue())
     190                 :           SS.setScopeRep(
     191                 :             Actions.ActOnCXXNestedNameSpecifier(CurScope, SS,
     192                 :                                                 TypeToken.getAnnotationValue(),
     193                 :                                                 TypeToken.getAnnotationRange(),
     194              795:                                                 CCLoc));
     195                 :         else
     196                0:           SS.setScopeRep(0);
     197              795:         SS.setEndLoc(CCLoc);
     198              795:         continue;
     199                 :       }
     200                 : 
     201                0:       assert(false && "FIXME: Only type template names supported here");
     202                 :     }
     203                 : 
     204                 : 
     205                 :     // The rest of the nested-name-specifier possibilities start with
     206                 :     // tok::identifier.
                     5929: branch 1 taken
                    68084: branch 2 taken
     207            74013:     if (Tok.isNot(tok::identifier))
     208             5929:       break;
     209                 : 
     210            68084:     IdentifierInfo &II = *Tok.getIdentifierInfo();
     211                 : 
     212                 :     // nested-name-specifier:
     213                 :     //   type-name '::'
     214                 :     //   namespace-name '::'
     215                 :     //   nested-name-specifier identifier '::'
     216            68084:     Token Next = NextToken();
     217                 :     
     218                 :     // If we get foo:bar, this is almost certainly a typo for foo::bar.  Recover
     219                 :     // and emit a fixit hint for it.
                      879: branch 1 taken
                    67205: branch 2 taken
                        8: branch 3 taken
                      871: branch 4 taken
                        4: branch 6 taken
                        4: branch 7 taken
                        4: branch 10 taken
                        0: branch 11 not taken
                        4: branch 12 taken
                    68080: branch 13 taken
     220            68084:     if (Next.is(tok::colon) && !ColonIsSacred &&
     221                 :         Actions.IsInvalidUnlessNestedName(CurScope, SS, II, ObjectType,
     222                 :                                           EnteringContext) &&
     223                 :         // If the token after the colon isn't an identifier, it's still an
     224                 :         // error, but they probably meant something else strange so don't
     225                 :         // recover like this.
     226                 :         PP.LookAhead(1).is(tok::identifier)) {
     227                 :       Diag(Next, diag::err_unexected_colon_in_nested_name_spec)
     228                4:         << CodeModificationHint::CreateReplacement(Next.getLocation(), "::");
     229                 :       
     230                 :       // Recover as if the user wrote '::'.
     231                4:       Next.setKind(tok::coloncolon);
     232                 :     }
     233                 :     
                     1623: branch 1 taken
                    66461: branch 2 taken
     234            68084:     if (Next.is(tok::coloncolon)) {
     235                 :       // We have an identifier followed by a '::'. Lookup this name
     236                 :       // as the name in a nested-name-specifier.
     237             1623:       SourceLocation IdLoc = ConsumeToken();
     238                 :       assert((Tok.is(tok::coloncolon) || Tok.is(tok::colon)) &&
                        4: branch 1 taken
                     1619: branch 2 taken
                        4: branch 4 taken
                        0: branch 5 not taken
     239             1623:              "NextToken() not working properly!");
     240             1623:       SourceLocation CCLoc = ConsumeToken();
     241                 : 
                     1436: branch 0 taken
                      187: branch 1 taken
     242             1623:       if (!HasScopeSpecifier) {
     243             1436:         SS.setBeginLoc(IdLoc);
     244             1436:         HasScopeSpecifier = true;
     245                 :       }
     246                 : 
                        2: branch 1 taken
                     1621: branch 2 taken
     247             1623:       if (SS.isInvalid())
     248                2:         continue;
     249                 : 
     250                 :       SS.setScopeRep(
     251                 :         Actions.ActOnCXXNestedNameSpecifier(CurScope, SS, IdLoc, CCLoc, II,
     252             1621:                                             ObjectType, EnteringContext));
     253             1621:       SS.setEndLoc(CCLoc);
     254             1621:       continue;
     255                 :     }
     256                 : 
     257                 :     // nested-name-specifier:
     258                 :     //   type-name '<'
                     2713: branch 1 taken
                    63748: branch 2 taken
     259            66461:     if (Next.is(tok::less)) {
     260             2713:       TemplateTy Template;
     261             2713:       UnqualifiedId TemplateName;
     262             2713:       TemplateName.setIdentifier(&II, Tok.getLocation());
                     2496: branch 0 taken
                      217: branch 1 taken
     263             2713:       if (TemplateNameKind TNK = Actions.isTemplateName(CurScope, SS, 
     264                 :                                                         TemplateName,
     265                 :                                                         ObjectType,
     266                 :                                                         EnteringContext,
     267             2713:                                                         Template)) {
     268                 :         // We have found a template name, so annotate this this token
     269                 :         // with a template-id annotation. We do not permit the
     270                 :         // template-id to be translated into a type annotation,
     271                 :         // because some clients (e.g., the parsing of class template
     272                 :         // specializations) still want to see the original template-id
     273                 :         // token.
     274             2496:         ConsumeToken();
                        5: branch 2 taken
                     2491: branch 3 taken
     275             2496:         if (AnnotateTemplateIdToken(Template, TNK, &SS, TemplateName, 
     276                 :                                     SourceLocation(), false))
     277                5:           break;
     278             2491:         continue;
                      217: branch 1 taken
                        5: branch 2 taken
                     2491: branch 3 taken
     279             2713:       }
     280                 :     }
     281                 : 
     282                 :     // We don't have any tokens that form the beginning of a
     283                 :     // nested-name-specifier, so we're done.
     284            63965:     break;
     285                 :   }
     286                 : 
     287            69907:   return HasScopeSpecifier;
     288                 : }
     289                 : 
     290                 : /// ParseCXXIdExpression - Handle id-expression.
     291                 : ///
     292                 : ///       id-expression:
     293                 : ///         unqualified-id
     294                 : ///         qualified-id
     295                 : ///
     296                 : ///       qualified-id:
     297                 : ///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
     298                 : ///         '::' identifier
     299                 : ///         '::' operator-function-id
     300                 : ///         '::' template-id
     301                 : ///
     302                 : /// NOTE: The standard specifies that, for qualified-id, the parser does not
     303                 : /// expect:
     304                 : ///
     305                 : ///   '::' conversion-function-id
     306                 : ///   '::' '~' class-name
     307                 : ///
     308                 : /// This may cause a slight inconsistency on diagnostics:
     309                 : ///
     310                 : /// class C {};
     311                 : /// namespace A {}
     312                 : /// void f() {
     313                 : ///   :: A :: ~ C(); // Some Sema error about using destructor with a
     314                 : ///                  // namespace.
     315                 : ///   :: ~ C(); // Some Parser error like 'unexpected ~'.
     316                 : /// }
     317                 : ///
     318                 : /// We simplify the parser a bit and make it work like:
     319                 : ///
     320                 : ///       qualified-id:
     321                 : ///         '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
     322                 : ///         '::' unqualified-id
     323                 : ///
     324                 : /// That way Sema can handle and report similar errors for namespaces and the
     325                 : /// global scope.
     326                 : ///
     327                 : /// The isAddressOfOperand parameter indicates that this id-expression is a
     328                 : /// direct operand of the address-of operator. This is, besides member contexts,
     329                 : /// the only place where a qualified-id naming a non-static class member may
     330                 : /// appear.
     331                 : ///
     332              661: Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {
     333                 :   // qualified-id:
     334                 :   //   '::'[opt] nested-name-specifier 'template'[opt] unqualified-id
     335                 :   //   '::' unqualified-id
     336                 :   //
     337              661:   CXXScopeSpec SS;
     338              661:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
     339                 :   
     340              661:   UnqualifiedId Name;
                        8: branch 1 taken
                      653: branch 2 taken
     341              661:   if (ParseUnqualifiedId(SS, 
     342                 :                          /*EnteringContext=*/false, 
     343                 :                          /*AllowDestructorName=*/false, 
     344                 :                          /*AllowConstructorName=*/false, 
     345                 :                          /*ObjectType=*/0,
     346                 :                          Name))
     347                8:     return ExprError();
     348                 : 
     349                 :   // This is only the direct operand of an & operator if it is not
     350                 :   // followed by a postfix-expression suffix.
                      130: branch 0 taken
                      523: branch 1 taken
     351              653:   if (isAddressOfOperand) {
                        6: branch 1 taken
                      124: branch 2 taken
     352              130:     switch (Tok.getKind()) {
     353                 :     case tok::l_square:
     354                 :     case tok::l_paren:
     355                 :     case tok::arrow:
     356                 :     case tok::period:
     357                 :     case tok::plusplus:
     358                 :     case tok::minusminus:
     359                6:       isAddressOfOperand = false;
     360                 :       break;
     361                 : 
     362                 :     default:
     363                 :       break;
     364                 :     }
     365                 :   }
     366                 :   
     367                 :   return Actions.ActOnIdExpression(CurScope, SS, Name, Tok.is(tok::l_paren),
     368              653:                                    isAddressOfOperand);
     369                 :   
     370                 : }
     371                 : 
     372                 : /// ParseCXXCasts - This handles the various ways to cast expressions to another
     373                 : /// type.
     374                 : ///
     375                 : ///       postfix-expression: [C++ 5.2p1]
     376                 : ///         'dynamic_cast' '<' type-name '>' '(' expression ')'
     377                 : ///         'static_cast' '<' type-name '>' '(' expression ')'
     378                 : ///         'reinterpret_cast' '<' type-name '>' '(' expression ')'
     379                 : ///         'const_cast' '<' type-name '>' '(' expression ')'
     380                 : ///
     381              252: Parser::OwningExprResult Parser::ParseCXXCasts() {
     382              252:   tok::TokenKind Kind = Tok.getKind();
     383              252:   const char *CastName = 0;     // For error messages
     384                 : 
                        0: branch 0 not taken
                       21: branch 1 taken
                       41: branch 2 taken
                       68: branch 3 taken
                      122: branch 4 taken
     385              252:   switch (Kind) {
     386                0:   default: assert(0 && "Unknown C++ cast!"); abort();
     387               21:   case tok::kw_const_cast:       CastName = "const_cast";       break;
     388               41:   case tok::kw_dynamic_cast:     CastName = "dynamic_cast";     break;
     389               68:   case tok::kw_reinterpret_cast: CastName = "reinterpret_cast"; break;
     390              122:   case tok::kw_static_cast:      CastName = "static_cast";      break;
     391                 :   }
     392                 : 
     393              252:   SourceLocation OpLoc = ConsumeToken();
     394              252:   SourceLocation LAngleBracketLoc = Tok.getLocation();
     395                 : 
                        0: branch 1 not taken
                      252: branch 2 taken
     396              252:   if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
     397                0:     return ExprError();
     398                 : 
     399              252:   TypeResult CastTy = ParseTypeName();
     400              252:   SourceLocation RAngleBracketLoc = Tok.getLocation();
     401                 : 
                        0: branch 1 not taken
                      252: branch 2 taken
     402              252:   if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
     403                0:     return ExprError(Diag(LAngleBracketLoc, diag::note_matching) << "<");
     404                 : 
     405              252:   SourceLocation LParenLoc = Tok.getLocation(), RParenLoc;
     406                 : 
                        0: branch 1 not taken
                      252: branch 2 taken
     407              252:   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, CastName))
     408                0:     return ExprError();
     409                 : 
     410              252:   OwningExprResult Result = ParseExpression();
     411                 : 
     412                 :   // Match the ')'.
     413              252:   RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
     414                 : 
                      251: branch 1 taken
                        1: branch 2 taken
                      251: branch 4 taken
                        0: branch 5 not taken
                      251: branch 6 taken
                        1: branch 7 taken
     415              252:   if (!Result.isInvalid() && !CastTy.isInvalid())
     416                 :     Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
     417                 :                                        LAngleBracketLoc, CastTy.get(),
     418                 :                                        RAngleBracketLoc,
     419              251:                                        LParenLoc, move(Result), RParenLoc);
     420                 : 
     421              252:   return move(Result);
     422                 : }
     423                 : 
     424                 : /// ParseCXXTypeid - This handles the C++ typeid expression.
     425                 : ///
     426                 : ///       postfix-expression: [C++ 5.2p1]
     427                 : ///         'typeid' '(' expression ')'
     428                 : ///         'typeid' '(' type-id ')'
     429                 : ///
     430               83: Parser::OwningExprResult Parser::ParseCXXTypeid() {
                       83: branch 1 taken
                        0: branch 2 not taken
     431               83:   assert(Tok.is(tok::kw_typeid) && "Not 'typeid'!");
     432                 : 
     433               83:   SourceLocation OpLoc = ConsumeToken();
     434               83:   SourceLocation LParenLoc = Tok.getLocation();
     435               83:   SourceLocation RParenLoc;
     436                 : 
     437                 :   // typeid expressions are always parenthesized.
                        1: branch 1 taken
                       82: branch 2 taken
     438               83:   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
     439                 :       "typeid"))
     440                1:     return ExprError();
     441                 : 
     442               82:   OwningExprResult Result(Actions);
     443                 : 
                       73: branch 1 taken
                        9: branch 2 taken
     444               82:   if (isTypeIdInParens()) {
     445               73:     TypeResult Ty = ParseTypeName();
     446                 : 
     447                 :     // Match the ')'.
     448               73:     MatchRHSPunctuation(tok::r_paren, LParenLoc);
     449                 : 
                        0: branch 1 not taken
                       73: branch 2 taken
     450               73:     if (Ty.isInvalid())
     451                0:       return ExprError();
     452                 : 
     453                 :     Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
     454               73:                                     Ty.get(), RParenLoc);
     455                 :   } else {
     456                 :     // C++0x [expr.typeid]p3:
     457                 :     //   When typeid is applied to an expression other than an lvalue of a
     458                 :     //   polymorphic class type [...] The expression is an unevaluated
     459                 :     //   operand (Clause 5).
     460                 :     //
     461                 :     // Note that we can't tell whether the expression is an lvalue of a
     462                 :     // polymorphic class type until after we've parsed the expression, so
     463                 :     // we the expression is potentially potentially evaluated.
     464                 :     EnterExpressionEvaluationContext Unevaluated(Actions,
     465                9:                                        Action::PotentiallyPotentiallyEvaluated);
     466                9:     Result = ParseExpression();
     467                 : 
     468                 :     // Match the ')'.
                        0: branch 1 not taken
                        9: branch 2 taken
     469                9:     if (Result.isInvalid())
     470                0:       SkipUntil(tok::r_paren);
     471                 :     else {
     472                9:       MatchRHSPunctuation(tok::r_paren, LParenLoc);
     473                 : 
     474                 :       Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false,
     475                9:                                       Result.release(), RParenLoc);
     476                9:     }
     477                 :   }
     478                 : 
     479               82:   return move(Result);
     480                 : }
     481                 : 
     482                 : /// ParseCXXBoolLiteral - This handles the C++ Boolean literals.
     483                 : ///
     484                 : ///       boolean-literal: [C++ 2.13.5]
     485                 : ///         'true'
     486                 : ///         'false'
     487              141: Parser::OwningExprResult Parser::ParseCXXBoolLiteral() {
     488              141:   tok::TokenKind Kind = Tok.getKind();
     489              141:   return Actions.ActOnCXXBoolLiteral(ConsumeToken(), Kind);
     490                 : }
     491                 : 
     492                 : /// ParseThrowExpression - This handles the C++ throw expression.
     493                 : ///
     494                 : ///       throw-expression: [C++ 15]
     495                 : ///         'throw' assignment-expression[opt]
     496               40: Parser::OwningExprResult Parser::ParseThrowExpression() {
                       40: branch 1 taken
                        0: branch 2 not taken
     497               40:   assert(Tok.is(tok::kw_throw) && "Not throw!");
     498               40:   SourceLocation ThrowLoc = ConsumeToken();           // Eat the throw token.
     499                 : 
     500                 :   // If the current token isn't the start of an assignment-expression,
     501                 :   // then the expression is not present.  This handles things like:
     502                 :   //   "C ? throw : (void)42", which is crazy but legal.
                       10: branch 1 taken
                       30: branch 2 taken
     503               40:   switch (Tok.getKind()) {  // FIXME: move this predicate somewhere common.
     504                 :   case tok::semi:
     505                 :   case tok::r_paren:
     506                 :   case tok::r_square:
     507                 :   case tok::r_brace:
     508                 :   case tok::colon:
     509                 :   case tok::comma:
     510               10:     return Actions.ActOnCXXThrow(ThrowLoc, ExprArg(Actions));
     511                 : 
     512                 :   default:
     513               30:     OwningExprResult Expr(ParseAssignmentExpression());
                        0: branch 1 not taken
                       30: branch 2 taken
     514               30:     if (Expr.isInvalid()) return move(Expr);
     515               30:     return Actions.ActOnCXXThrow(ThrowLoc, move(Expr));
     516                 :   }
     517                 : }
     518                 : 
     519                 : /// ParseCXXThis - This handles the C++ 'this' pointer.
     520                 : ///
     521                 : /// C++ 9.3.2: In the body of a non-static member function, the keyword this is
     522                 : /// a non-lvalue expression whose value is the address of the object for which
     523                 : /// the function is called.
     524               80: Parser::OwningExprResult Parser::ParseCXXThis() {
                       80: branch 1 taken
                        0: branch 2 not taken
     525               80:   assert(Tok.is(tok::kw_this) && "Not 'this'!");
     526               80:   SourceLocation ThisLoc = ConsumeToken();
     527               80:   return Actions.ActOnCXXThis(ThisLoc);
     528                 : }
     529                 : 
     530                 : /// ParseCXXTypeConstructExpression - Parse construction of a specified type.
     531                 : /// Can be interpreted either as function-style casting ("int(x)")
     532                 : /// or class type construction ("ClassType(x,y,z)")
     533                 : /// or creation of a value-initialized type ("int()").
     534                 : ///
     535                 : ///       postfix-expression: [C++ 5.2p1]
     536                 : ///         simple-type-specifier '(' expression-list[opt] ')'      [C++ 5.2.3]
     537                 : ///         typename-specifier '(' expression-list[opt] ')'         [TODO]
     538                 : ///
     539                 : Parser::OwningExprResult
     540              515: Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) {
     541              515:   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
     542              515:   TypeTy *TypeRep = Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
     543                 : 
                      515: branch 1 taken
                        0: branch 2 not taken
     544              515:   assert(Tok.is(tok::l_paren) && "Expected '('!");
     545              515:   SourceLocation LParenLoc = ConsumeParen();
     546                 : 
     547              515:   ExprVector Exprs(Actions);
     548              515:   CommaLocsTy CommaLocs;
     549                 : 
                      189: branch 1 taken
                      326: branch 2 taken
     550              515:   if (Tok.isNot(tok::r_paren)) {
                        0: branch 1 not taken
                      189: branch 2 taken
     551              189:     if (ParseExpressionList(Exprs, CommaLocs)) {
     552                0:       SkipUntil(tok::r_paren);
     553                0:       return ExprError();
     554                 :     }
     555                 :   }
     556                 : 
     557                 :   // Match the ')'.
     558              515:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
     559                 : 
     560                 :   // TypeRep could be null, if it references an invalid typedef.
                        0: branch 0 not taken
                      515: branch 1 taken
     561              515:   if (!TypeRep)
     562                0:     return ExprError();
     563                 : 
     564                 :   assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&&
                      189: branch 1 taken
                      326: branch 2 taken
                      189: branch 5 taken
                        0: branch 6 not taken
     565              515:          "Unexpected number of commas!");
     566                 :   return Actions.ActOnCXXTypeConstructExpr(DS.getSourceRange(), TypeRep,
     567                 :                                            LParenLoc, move_arg(Exprs),
     568             1030:                                            CommaLocs.data(), RParenLoc);
     569                 : }
     570                 : 
     571                 : /// ParseCXXCondition - if/switch/while condition expression.
     572                 : ///
     573                 : ///       condition:
     574                 : ///         expression
     575                 : ///         type-specifier-seq declarator '=' assignment-expression
     576                 : /// [GNU]   type-specifier-seq declarator simple-asm-expr[opt] attributes[opt]
     577                 : ///             '=' assignment-expression
     578                 : ///
     579                 : /// \param ExprResult if the condition was parsed as an expression, the
     580                 : /// parsed expression.
     581                 : ///
     582                 : /// \param DeclResult if the condition was parsed as a declaration, the
     583                 : /// parsed declaration.
     584                 : ///
     585                 : /// \returns true if there was a parsing, false otherwise.
     586                 : bool Parser::ParseCXXCondition(OwningExprResult &ExprResult,
     587              365:                                DeclPtrTy &DeclResult) {
                        0: branch 1 not taken
                      365: branch 2 taken
     588              365:   if (Tok.is(tok::code_completion)) {
     589                0:     Actions.CodeCompleteOrdinaryName(CurScope, Action::CCC_Condition);
     590                0:     ConsumeToken();
     591                 :   }
     592                 : 
                      305: branch 1 taken
                       60: branch 2 taken
     593              365:   if (!isCXXConditionDeclaration()) {
     594              305:     ExprResult = ParseExpression(); // expression
     595              305:     DeclResult = DeclPtrTy();
     596              305:     return ExprResult.isInvalid();
     597                 :   }
     598                 : 
     599                 :   // type-specifier-seq
     600               60:   DeclSpec DS;
     601               60:   ParseSpecifierQualifierList(DS);
     602                 : 
     603                 :   // declarator
     604               60:   Declarator DeclaratorInfo(DS, Declarator::ConditionContext);
     605               60:   ParseDeclarator(DeclaratorInfo);
     606                 : 
     607                 :   // simple-asm-expr[opt]
                        0: branch 1 not taken
                       60: branch 2 taken
     608               60:   if (Tok.is(tok::kw_asm)) {
     609                0:     SourceLocation Loc;
     610                0:     OwningExprResult AsmLabel(ParseSimpleAsm(&Loc));
                        0: branch 1 not taken
                        0: branch 2 not taken
     611                0:     if (AsmLabel.isInvalid()) {
     612                0:       SkipUntil(tok::semi);
     613                0:       return true;
     614                 :     }
     615                0:     DeclaratorInfo.setAsmLabel(AsmLabel.release());
                        0: branch 2 not taken
                        0: branch 3 not taken
     616                0:     DeclaratorInfo.SetRangeEnd(Loc);
     617                 :   }
     618                 : 
     619                 :   // If attributes are present, parse them.
                        0: branch 1 not taken
                       60: branch 2 taken
     620               60:   if (Tok.is(tok::kw___attribute)) {
     621                0:     SourceLocation Loc;
     622                0:     AttributeList *AttrList = ParseGNUAttributes(&Loc);
     623                0:     DeclaratorInfo.AddAttributes(AttrList, Loc);
     624                 :   }
     625                 : 
     626                 :   // Type-check the declaration itself.
     627                 :   Action::DeclResult Dcl = Actions.ActOnCXXConditionDeclaration(CurScope, 
     628               60:                                                                 DeclaratorInfo);
     629               60:   DeclResult = Dcl.get();
     630               60:   ExprResult = ExprError();
     631                 :   
     632                 :   // '=' assignment-expression
                       59: branch 1 taken
                        1: branch 2 taken
     633               60:   if (Tok.is(tok::equal)) {
     634               59:     SourceLocation EqualLoc = ConsumeToken();
     635               59:     OwningExprResult AssignExpr(ParseAssignmentExpression());
                       59: branch 1 taken
                        0: branch 2 not taken
     636               59:     if (!AssignExpr.isInvalid()) 
     637               59:       Actions.AddInitializerToDecl(DeclResult, move(AssignExpr));
     638                 :   } else {
     639                 :     // FIXME: C++0x allows a braced-init-list
     640                1:     Diag(Tok, diag::err_expected_equal_after_declarator);
     641                 :   }
     642                 :   
     643               60:   return false;
     644                 : }
     645                 : 
     646                 : /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers.
     647                 : /// This should only be called when the current token is known to be part of
     648                 : /// simple-type-specifier.
     649                 : ///
     650                 : ///       simple-type-specifier:
     651                 : ///         '::'[opt] nested-name-specifier[opt] type-name
     652                 : ///         '::'[opt] nested-name-specifier 'template' simple-template-id [TODO]
     653                 : ///         char
     654                 : ///         wchar_t
     655                 : ///         bool
     656                 : ///         short
     657                 : ///         int
     658                 : ///         long
     659                 : ///         signed
     660                 : ///         unsigned
     661                 : ///         float
     662                 : ///         double
     663                 : ///         void
     664                 : /// [GNU]   typeof-specifier
     665                 : /// [C++0x] auto               [TODO]
     666                 : ///
     667                 : ///       type-name:
     668                 : ///         class-name
     669                 : ///         enum-name
     670                 : ///         typedef-name
     671                 : ///
     672              517: void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) {
     673              517:   DS.SetRangeStart(Tok.getLocation());
     674                 :   const char *PrevSpec;
     675                 :   unsigned DiagID;
     676              517:   SourceLocation Loc = Tok.getLocation();
     677                 : 
                        0: branch 1 not taken
                        0: branch 2 not taken
                      461: branch 3 taken
                        0: branch 4 not taken
                        2: branch 5 taken
                        0: branch 6 not taken
                        2: branch 7 taken
                        5: branch 8 taken
                        3: branch 9 taken
                       29: branch 10 taken
                        7: branch 11 taken
                        3: branch 12 taken
                        0: branch 13 not taken
                        0: branch 14 not taken
                        0: branch 15 not taken
                        1: branch 16 taken
                        4: branch 17 taken
     678              517:   switch (Tok.getKind()) {
     679                 :   case tok::identifier:   // foo::bar
     680                 :   case tok::coloncolon:   // ::foo::bar
     681                0:     assert(0 && "Annotation token should already be formed!");
     682                 :   default:
     683                0:     assert(0 && "Not a simple-type-specifier token!");
     684                 :     abort();
     685                 : 
     686                 :   // type-name
     687                 :   case tok::annot_typename: {
     688                 :     DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID,
     689              461:                        Tok.getAnnotationValue());
     690              461:     break;
     691                 :   }
     692                 : 
     693                 :   // builtin types
     694                 :   case tok::kw_short:
     695                0:     DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, DiagID);
     696                0:     break;
     697                 :   case tok::kw_long:
     698                2:     DS.SetTypeSpecWidth(DeclSpec::TSW_long, Loc, PrevSpec, DiagID);
     699                2:     break;
     700                 :   case tok::kw_signed:
     701                0:     DS.SetTypeSpecSign(DeclSpec::TSS_signed, Loc, PrevSpec, DiagID);
     702                0:     break;
     703                 :   case tok::kw_unsigned:
     704                2:     DS.SetTypeSpecSign(DeclSpec::TSS_unsigned, Loc, PrevSpec, DiagID);
     705                2:     break;
     706                 :   case tok::kw_void:
     707                5:     DS.SetTypeSpecType(DeclSpec::TST_void, Loc, PrevSpec, DiagID);
     708                5:     break;
     709                 :   case tok::kw_char:
     710                3:     DS.SetTypeSpecType(DeclSpec::TST_char, Loc, PrevSpec, DiagID);
     711                3:     break;
     712                 :   case tok::kw_int:
     713               29:     DS.SetTypeSpecType(DeclSpec::TST_int, Loc, PrevSpec, DiagID);
     714               29:     break;
     715                 :   case tok::kw_float:
     716                7:     DS.SetTypeSpecType(DeclSpec::TST_float, Loc, PrevSpec, DiagID);
     717                7:     break;
     718                 :   case tok::kw_double:
     719                3:     DS.SetTypeSpecType(DeclSpec::TST_double, Loc, PrevSpec, DiagID);
     720                3:     break;
     721                 :   case tok::kw_wchar_t:
     722                0:     DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID);
     723                0:     break;
     724                 :   case tok::kw_char16_t:
     725                0:     DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID);
     726                0:     break;
     727                 :   case tok::kw_char32_t:
     728                0:     DS.SetTypeSpecType(DeclSpec::TST_char32, Loc, PrevSpec, DiagID);
     729                0:     break;
     730                 :   case tok::kw_bool:
     731                1:     DS.SetTypeSpecType(DeclSpec::TST_bool, Loc, PrevSpec, DiagID);
     732                1:     break;
     733                 : 
     734                 :   // GNU typeof support.
     735                 :   case tok::kw_typeof:
     736                4:     ParseTypeofSpecifier(DS);
     737                4:     DS.Finish(Diags, PP);
     738                4:     return;
     739                 :   }
                      461: branch 1 taken
                       52: branch 2 taken
     740              513:   if (Tok.is(tok::annot_typename))
     741              461:     DS.SetRangeEnd(Tok.getAnnotationEndLoc());
     742                 :   else
     743               52:     DS.SetRangeEnd(Tok.getLocation());
     744              513:   ConsumeToken();
     745              513:   DS.Finish(Diags, PP);
     746                 : }
     747                 : 
     748                 : /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++
     749                 : /// [dcl.name]), which is a non-empty sequence of type-specifiers,
     750                 : /// e.g., "const short int". Note that the DeclSpec is *not* finished
     751                 : /// by parsing the type-specifier-seq, because these sequences are
     752                 : /// typically followed by some form of declarator. Returns true and
     753                 : /// emits diagnostics if this is not a type-specifier-seq, false
     754                 : /// otherwise.
     755                 : ///
     756                 : ///   type-specifier-seq: [C++ 8.1]
     757                 : ///     type-specifier type-specifier-seq[opt]
     758                 : ///
     759              417: bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) {
     760              417:   DS.SetRangeStart(Tok.getLocation());
     761              417:   const char *PrevSpec = 0;
     762                 :   unsigned DiagID;
     763              417:   bool isInvalid = 0;
     764                 : 
     765                 :   // Parse one or more of the type specifiers.
                        8: branch 2 taken
                      409: branch 3 taken
     766              417:   if (!ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
     767                 :       ParsedTemplateInfo(), /*SuppressDeclarations*/true)) {
     768                8:     Diag(Tok, diag::err_operator_missing_type_specifier);
     769                8:     return true;
     770                 :   }
     771                 : 
                       31: branch 2 taken
                      409: branch 3 taken
     772              440:   while (ParseOptionalTypeSpecifier(DS, isInvalid, PrevSpec, DiagID,
     773                 :          ParsedTemplateInfo(), /*SuppressDeclarations*/true))
     774                 :   {}
     775                 : 
     776              409:   return false;
     777                 : }
     778                 : 
     779                 : /// \brief Finish parsing a C++ unqualified-id that is a template-id of
     780                 : /// some form. 
     781                 : ///
     782                 : /// This routine is invoked when a '<' is encountered after an identifier or
     783                 : /// operator-function-id is parsed by \c ParseUnqualifiedId() to determine
     784                 : /// whether the unqualified-id is actually a template-id. This routine will
     785                 : /// then parse the template arguments and form the appropriate template-id to
     786                 : /// return to the caller.
     787                 : ///
     788                 : /// \param SS the nested-name-specifier that precedes this template-id, if
     789                 : /// we're actually parsing a qualified-id.
     790                 : ///
     791                 : /// \param Name for constructor and destructor names, this is the actual
     792                 : /// identifier that may be a template-name.
     793                 : ///
     794                 : /// \param NameLoc the location of the class-name in a constructor or 
     795                 : /// destructor.
     796                 : ///
     797                 : /// \param EnteringContext whether we're entering the scope of the 
     798                 : /// nested-name-specifier.
     799                 : ///
     800                 : /// \param ObjectType if this unqualified-id occurs within a member access
     801                 : /// expression, the type of the base object whose member is being accessed.
     802                 : ///
     803                 : /// \param Id as input, describes the template-name or operator-function-id
     804                 : /// that precedes the '<'. If template arguments were parsed successfully,
     805                 : /// will be updated with the template-id.
     806                 : /// 
     807                 : /// \returns true if a parse error occurred, false otherwise.
     808                 : bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS,
     809                 :                                           IdentifierInfo *Name,
     810                 :                                           SourceLocation NameLoc,
     811                 :                                           bool EnteringContext,
     812                 :                                           TypeTy *ObjectType,
     813                7:                                           UnqualifiedId &Id) {
                        7: branch 1 taken
                        0: branch 2 not taken
     814                7:   assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id");
     815                 :   
     816                7:   TemplateTy Template;
     817                7:   TemplateNameKind TNK = TNK_Non_template;
                        6: branch 1 taken
                        0: branch 2 not taken
                        1: branch 3 taken
                        0: branch 4 not taken
     818                7:   switch (Id.getKind()) {
     819                 :   case UnqualifiedId::IK_Identifier:
     820                 :   case UnqualifiedId::IK_OperatorFunctionId:
     821                 :   case UnqualifiedId::IK_LiteralOperatorId:
     822                 :     TNK = Actions.isTemplateName(CurScope, SS, Id, ObjectType, EnteringContext, 
     823                6:                                  Template);
     824                6:     break;
     825                 :       
     826                 :   case UnqualifiedId::IK_ConstructorName: {
     827                0:     UnqualifiedId TemplateName;
     828                0:     TemplateName.setIdentifier(Name, NameLoc);
     829                 :     TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
     830                0:                                  EnteringContext, Template);
     831                0:     break;
     832                 :   }
     833                 :       
     834                 :   case UnqualifiedId::IK_DestructorName: {
     835                1:     UnqualifiedId TemplateName;
     836                1:     TemplateName.setIdentifier(Name, NameLoc);
                        1: branch 0 taken
                        0: branch 1 not taken
     837                1:     if (ObjectType) {
     838                 :       Template = Actions.ActOnDependentTemplateName(SourceLocation(), SS, 
     839                 :                                                     TemplateName, ObjectType,
     840                1:                                                     EnteringContext);
     841                1:       TNK = TNK_Dependent_template_name;
                        0: branch 1 not taken
                        1: branch 2 taken
     842                1:       if (!Template.get())
     843                0:         return true;
     844                 :     } else {
     845                 :       TNK = Actions.isTemplateName(CurScope, SS, TemplateName, ObjectType, 
     846                0:                                    EnteringContext, Template);
     847                 :       
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
     848                0:       if (TNK == TNK_Non_template && Id.DestructorName == 0) {
     849                 :         // The identifier following the destructor did not refer to a template
     850                 :         // or to a type. Complain.
                        0: branch 0 not taken
                        0: branch 1 not taken
     851                0:         if (ObjectType)
     852                 :           Diag(NameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
     853                0:             << Name;        
     854                 :         else
     855                0:           Diag(NameLoc, diag::err_destructor_class_name);
     856                0:         return true;        
     857                 :       }
     858                 :     }
                        0: branch 1 not taken
                        1: branch 2 taken
     859                2:     break;
     860                 :   }
     861                 :       
     862                 :   default:
     863                0:     return false;
     864                 :   }
     865                 :   
                        3: branch 0 taken
                        4: branch 1 taken
     866                7:   if (TNK == TNK_Non_template)
     867                3:     return false;
     868                 :   
     869                 :   // Parse the enclosed template argument list.
     870                4:   SourceLocation LAngleLoc, RAngleLoc;
     871                4:   TemplateArgList TemplateArgs;
                        0: branch 1 not taken
                        4: branch 2 taken
     872                4:   if (ParseTemplateIdAfterTemplateName(Template, Id.StartLocation,
     873                 :                                        &SS, true, LAngleLoc,
     874                 :                                        TemplateArgs,
     875                 :                                        RAngleLoc))
     876                0:     return true;
     877                 :   
                        4: branch 1 taken
                        0: branch 2 not taken
                        1: branch 4 taken
                        3: branch 5 taken
                        0: branch 7 not taken
                        1: branch 8 taken
                        3: branch 9 taken
                        1: branch 10 taken
     878                4:   if (Id.getKind() == UnqualifiedId::IK_Identifier ||
     879                 :       Id.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
     880                 :       Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) {
     881                 :     // Form a parsed representation of the template-id to be stored in the
     882                 :     // UnqualifiedId.
     883                 :     TemplateIdAnnotation *TemplateId
     884                3:       = TemplateIdAnnotation::Allocate(TemplateArgs.size());
     885                 : 
                        0: branch 1 not taken
                        3: branch 2 taken
     886                3:     if (Id.getKind() == UnqualifiedId::IK_Identifier) {
     887                0:       TemplateId->Name = Id.Identifier;
     888                0:       TemplateId->Operator = OO_None;
     889                0:       TemplateId->TemplateNameLoc = Id.StartLocation;
     890                 :     } else {
     891                3:       TemplateId->Name = 0;
     892                3:       TemplateId->Operator = Id.OperatorFunctionId.Operator;
     893                3:       TemplateId->TemplateNameLoc = Id.StartLocation;
     894                 :     }
     895                 : 
     896                3:     TemplateId->Template = Template.getAs<void*>();
     897                3:     TemplateId->Kind = TNK;
     898                3:     TemplateId->LAngleLoc = LAngleLoc;
     899                3:     TemplateId->RAngleLoc = RAngleLoc;
     900                3:     ParsedTemplateArgument *Args = TemplateId->getTemplateArgs();
                        4: branch 1 taken
                        3: branch 2 taken
     901                7:     for (unsigned Arg = 0, ArgEnd = TemplateArgs.size(); 
     902                 :          Arg != ArgEnd; ++Arg)
     903                4:       Args[Arg] = TemplateArgs[Arg];
     904                 :     
     905                3:     Id.setTemplateId(TemplateId);
     906                3:     return false;
     907                 :   }
     908                 : 
     909                 :   // Bundle the template arguments together.
     910                 :   ASTTemplateArgsPtr TemplateArgsPtr(Actions, TemplateArgs.data(),
     911                1:                                      TemplateArgs.size());
     912                 :   
     913                 :   // Constructor and destructor names.
     914                 :   Action::TypeResult Type
     915                 :     = Actions.ActOnTemplateIdType(Template, NameLoc,
     916                 :                                   LAngleLoc, TemplateArgsPtr,
     917                1:                                   RAngleLoc);
                        0: branch 1 not taken
                        1: branch 2 taken
     918                1:   if (Type.isInvalid())
     919                0:     return true;
     920                 :   
                        0: branch 1 not taken
                        1: branch 2 taken
     921                1:   if (Id.getKind() == UnqualifiedId::IK_ConstructorName)
     922                0:     Id.setConstructorName(Type.get(), NameLoc, RAngleLoc);
     923                 :   else
     924                1:     Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc);
     925                 :   
     926                1:   return false;
     927                 : }
     928                 : 
     929                 : /// \brief Parse an operator-function-id or conversion-function-id as part
     930                 : /// of a C++ unqualified-id.
     931                 : ///
     932                 : /// This routine is responsible only for parsing the operator-function-id or
     933                 : /// conversion-function-id; it does not handle template arguments in any way.
     934                 : ///
     935                 : /// \code
     936                 : ///       operator-function-id: [C++ 13.5]
     937                 : ///         'operator' operator
     938                 : ///
     939                 : ///       operator: one of
     940                 : ///            new   delete  new[]   delete[]
     941                 : ///            +     -    *  /    %  ^    &   |   ~
     942                 : ///            !     =    <  >    += -=   *=  /=  %=
     943                 : ///            ^=    &=   |= <<   >> >>= <<=  ==  !=
     944                 : ///            <=    >=   && ||   ++ --   ,   ->* ->
     945                 : ///            ()    []
     946                 : ///
     947                 : ///       conversion-function-id: [C++ 12.3.2]
     948                 : ///         operator conversion-type-id
     949                 : ///
     950                 : ///       conversion-type-id:
     951                 : ///         type-specifier-seq conversion-declarator[opt]
     952                 : ///
     953                 : ///       conversion-declarator:
     954                 : ///         ptr-operator conversion-declarator[opt]
     955                 : /// \endcode
     956                 : ///
     957                 : /// \param The nested-name-specifier that preceded this unqualified-id. If
     958                 : /// non-empty, then we are parsing the unqualified-id of a qualified-id.
     959                 : ///
     960                 : /// \param EnteringContext whether we are entering the scope of the 
     961                 : /// nested-name-specifier.
     962                 : ///
     963                 : /// \param ObjectType if this unqualified-id occurs within a member access
     964                 : /// expression, the type of the base object whose member is being accessed.
     965                 : ///
     966                 : /// \param Result on a successful parse, contains the parsed unqualified-id.
     967                 : ///
     968                 : /// \returns true if parsing fails, false otherwise.
     969                 : bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext,
     970                 :                                         TypeTy *ObjectType,
     971              608:                                         UnqualifiedId &Result) {
                      608: branch 1 taken
                        0: branch 2 not taken
     972              608:   assert(Tok.is(tok::kw_operator) && "Expected 'operator' keyword");
     973                 :   
     974                 :   // Consume the 'operator' keyword.
     975              608:   SourceLocation KeywordLoc = ConsumeToken();
     976                 :   
     977                 :   // Determine what kind of operator name we have.
     978              608:   unsigned SymbolIdx = 0;
                     1824: branch 1 taken
                      608: branch 2 taken
     979             2432:   SourceLocation SymbolLocations[3];
     980              608:   OverloadedOperatorKind Op = OO_None;
                       59: branch 1 taken
                       52: branch 2 taken
                       11: branch 3 taken
                        8: branch 4 taken
                        2: branch 5 taken
                        1: branch 6 taken
                        0: branch 7 not taken
                        3: branch 8 taken
                        2: branch 9 taken
                        0: branch 10 not taken
                        3: branch 11 taken
                       38: branch 12 taken
                        0: branch 13 not taken
                        0: branch 14 not taken
                        8: branch 15 taken
                        0: branch 16 not taken
                        0: branch 17 not taken
                        0: branch 18 not taken
                        0: branch 19 not taken
                        0: branch 20 not taken
                        0: branch 21 not taken
                        0: branch 22 not taken
                        3: branch 23 taken
                        0: branch 24 not taken
                        0: branch 25 not taken
                        0: branch 26 not taken
                       27: branch 27 taken
                        7: branch 28 taken
                        0: branch 29 not taken
                        0: branch 30 not taken
                        0: branch 31 not taken
                        0: branch 32 not taken
                       12: branch 33 taken
                        5: branch 34 taken
                        1: branch 35 taken
                        1: branch 36 taken
                       14: branch 37 taken
                       28: branch 38 taken
                       14: branch 39 taken
                        1: branch 40 taken
                      308: branch 41 taken
     981              608:   switch (Tok.getKind()) {
     982                 :     case tok::kw_new:
     983                 :     case tok::kw_delete: {
     984               59:       bool isNew = Tok.getKind() == tok::kw_new;
     985                 :       // Consume the 'new' or 'delete'.
     986               59:       SymbolLocations[SymbolIdx++] = ConsumeToken();
                        6: branch 1 taken
                       53: branch 2 taken
     987               59:       if (Tok.is(tok::l_square)) {
     988                 :         // Consume the '['.
     989                6:         SourceLocation LBracketLoc = ConsumeBracket();
     990                 :         // Consume the ']'.
     991                 :         SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
     992                6:                                                          LBracketLoc);
                        0: branch 1 not taken
                        6: branch 2 taken
     993                6:         if (RBracketLoc.isInvalid())
     994                0:           return true;
     995                 :         
     996                6:         SymbolLocations[SymbolIdx++] = LBracketLoc;
     997                6:         SymbolLocations[SymbolIdx++] = RBracketLoc;
                        4: branch 0 taken
                        2: branch 1 taken
     998                6:         Op = isNew? OO_Array_New : OO_Array_Delete;
     999                 :       } else {
                       32: branch 0 taken
                       21: branch 1 taken
    1000               53:         Op = isNew? OO_New : OO_Delete;
    1001                 :       }
    1002               59:       break;
    1003                 :     }
    1004                 :       
    1005                 : #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
    1006                 :     case tok::Token:                                                     \
    1007                 :       SymbolLocations[SymbolIdx++] = ConsumeToken();                     \
    1008                 :       Op = OO_##Name;                                                    \
    1009                 :       break;
    1010                 : #define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
    1011                 : #include "clang/Basic/OperatorKinds.def"
    1012                 :       
    1013                 :     case tok::l_paren: {
    1014                 :       // Consume the '('.
    1015               28:       SourceLocation LParenLoc = ConsumeParen();
    1016                 :       // Consume the ')'.
    1017                 :       SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren,
    1018               28:                                                      LParenLoc);
                        0: branch 1 not taken
                       28: branch 2 taken
    1019               28:       if (RParenLoc.isInvalid())
    1020                0:         return true;
    1021                 :       
    1022               28:       SymbolLocations[SymbolIdx++] = LParenLoc;
    1023               28:       SymbolLocations[SymbolIdx++] = RParenLoc;
    1024               28:       Op = OO_Call;
    1025               28:       break;
    1026                 :     }
    1027                 :       
    1028                 :     case tok::l_square: {
    1029                 :       // Consume the '['.
    1030               14:       SourceLocation LBracketLoc = ConsumeBracket();
    1031                 :       // Consume the ']'.
    1032                 :       SourceLocation RBracketLoc = MatchRHSPunctuation(tok::r_square,
    1033               14:                                                        LBracketLoc);
                        0: branch 1 not taken
                       14: branch 2 taken
    1034               14:       if (RBracketLoc.isInvalid())
    1035                0:         return true;
    1036                 :       
    1037               14:       SymbolLocations[SymbolIdx++] = LBracketLoc;
    1038               14:       SymbolLocations[SymbolIdx++] = RBracketLoc;
    1039               14:       Op = OO_Subscript;
    1040               14:       break;
    1041                 :     }
    1042                 :       
    1043                 :     case tok::code_completion: {
    1044                 :       // Code completion for the operator name.
    1045                1:       Actions.CodeCompleteOperatorName(CurScope);
    1046                 :       
    1047                 :       // Consume the operator token.
    1048                1:       ConsumeToken();
    1049                 :       
    1050                 :       // Don't try to parse any further.
    1051                1:       return true;
    1052                 :     }
    1053                 :       
    1054                 :     default:
    1055                 :       break;
    1056                 :   }
    1057                 :   
                      299: branch 0 taken
                      308: branch 1 taken
    1058              607:   if (Op != OO_None) {
    1059                 :     // We have parsed an operator-function-id.
    1060              299:     Result.setOperatorFunctionId(KeywordLoc, Op, SymbolLocations);
    1061              299:     return false;
    1062                 :   }
    1063                 : 
    1064                 :   // Parse a literal-operator-id.
    1065                 :   //
    1066                 :   //   literal-operator-id: [C++0x 13.5.8]
    1067                 :   //     operator "" identifier
    1068                 : 
                      113: branch 1 taken
                      195: branch 2 taken
                       22: branch 4 taken
                       91: branch 5 taken
                       22: branch 6 taken
                      286: branch 7 taken
    1069              308:   if (getLang().CPlusPlus0x && Tok.is(tok::string_literal)) {
                        1: branch 1 taken
                       21: branch 2 taken
    1070               22:     if (Tok.getLength() != 2)
    1071                1:       Diag(Tok.getLocation(), diag::err_operator_string_not_empty);
    1072               22:     ConsumeStringToken();
    1073                 : 
                        1: branch 1 taken
                       21: branch 2 taken
    1074               22:     if (Tok.isNot(tok::identifier)) {
    1075                1:       Diag(Tok.getLocation(), diag::err_expected_ident);
    1076                1:       return true;
    1077                 :     }
    1078                 : 
    1079               21:     IdentifierInfo *II = Tok.getIdentifierInfo();
    1080               21:     Result.setLiteralOperatorId(II, KeywordLoc, ConsumeToken());
    1081               21:     return false;
    1082                 :   }
    1083                 :   
    1084                 :   // Parse a conversion-function-id.
    1085                 :   //
    1086                 :   //   conversion-function-id: [C++ 12.3.2]
    1087                 :   //     operator conversion-type-id
    1088                 :   //
    1089                 :   //   conversion-type-id:
    1090                 :   //     type-specifier-seq conversion-declarator[opt]
    1091                 :   //
    1092                 :   //   conversion-declarator:
    1093                 :   //     ptr-operator conversion-declarator[opt]
    1094                 :   
    1095                 :   // Parse the type-specifier-seq.
    1096              286:   DeclSpec DS;
                        6: branch 1 taken
                      280: branch 2 taken
    1097              286:   if (ParseCXXTypeSpecifierSeq(DS)) // FIXME: ObjectType?
    1098                6:     return true;
    1099                 :   
    1100                 :   // Parse the conversion-declarator, which is merely a sequence of
    1101                 :   // ptr-operators.
    1102              280:   Declarator D(DS, Declarator::TypeNameContext);
    1103              280:   ParseDeclaratorInternal(D, /*DirectDeclParser=*/0);
    1104                 :   
    1105                 :   // Finish up the type.
    1106              280:   Action::TypeResult Ty = Actions.ActOnTypeName(CurScope, D);
                        0: branch 1 not taken
                      280: branch 2 taken
    1107              280:   if (Ty.isInvalid())
    1108                0:     return true;
    1109                 :   
    1110                 :   // Note that this is a conversion-function-id.
    1111                 :   Result.setConversionFunctionId(KeywordLoc, Ty.get(), 
    1112              280:                                  D.getSourceRange().getEnd());
    1113              280:   return false;  
    1114                 : }
    1115                 : 
    1116                 : /// \brief Parse a C++ unqualified-id (or a C identifier), which describes the
    1117                 : /// name of an entity.
    1118                 : ///
    1119                 : /// \code
    1120                 : ///       unqualified-id: [C++ expr.prim.general]
    1121                 : ///         identifier
    1122                 : ///         operator-function-id
    1123                 : ///         conversion-function-id
    1124                 : /// [C++0x] literal-operator-id [TODO]
    1125                 : ///         ~ class-name
    1126                 : ///         template-id
    1127                 : ///
    1128                 : /// \endcode
    1129                 : ///
    1130                 : /// \param The nested-name-specifier that preceded this unqualified-id. If
    1131                 : /// non-empty, then we are parsing the unqualified-id of a qualified-id.
    1132                 : ///
    1133                 : /// \param EnteringContext whether we are entering the scope of the 
    1134                 : /// nested-name-specifier.
    1135                 : ///
    1136                 : /// \param AllowDestructorName whether we allow parsing of a destructor name.
    1137                 : ///
    1138                 : /// \param AllowConstructorName whether we allow parsing a constructor name.
    1139                 : ///
    1140                 : /// \param ObjectType if this unqualified-id occurs within a member access
    1141                 : /// expression, the type of the base object whose member is being accessed.
    1142                 : ///
    1143                 : /// \param Result on a successful parse, contains the parsed unqualified-id.
    1144                 : ///
    1145                 : /// \returns true if parsing fails, false otherwise.
    1146                 : bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext,
    1147                 :                                 bool AllowDestructorName,
    1148                 :                                 bool AllowConstructorName,
    1149                 :                                 TypeTy *ObjectType,
    1150            19930:                                 UnqualifiedId &Result) {
    1151                 :   // unqualified-id:
    1152                 :   //   identifier
    1153                 :   //   template-id (when it hasn't already been annotated)
                    18858: branch 1 taken
                     1072: branch 2 taken
    1154            19930:   if (Tok.is(tok::identifier)) {
    1155                 :     // Consume the identifier.
    1156            18858:     IdentifierInfo *Id = Tok.getIdentifierInfo();
    1157            18858:     SourceLocation IdLoc = ConsumeToken();
    1158                 : 
                     1310: branch 1 taken
                    17548: branch 2 taken
    1159            18858:     if (!getLang().CPlusPlus) {
    1160                 :       // If we're not in C++, only identifiers matter. Record the
    1161                 :       // identifier and return.
    1162             1310:       Result.setIdentifier(Id, IdLoc);
    1163             1310:       return false;
    1164                 :     }
    1165                 : 
                      774: branch 0 taken
                    16774: branch 1 taken
                      649: branch 3 taken
                      125: branch 4 taken
                      649: branch 5 taken
                    16899: branch 6 taken
    1166            17548:     if (AllowConstructorName && 
    1167                 :         Actions.isCurrentClassName(*Id, CurScope, &SS)) {
    1168                 :       // We have parsed a constructor name.
    1169                 :       Result.setConstructorName(Actions.getTypeName(*Id, IdLoc, CurScope,
    1170                 :                                                     &SS, false),
    1171              649:                                 IdLoc, IdLoc);
    1172                 :     } else {
    1173                 :       // We have parsed an identifier.
    1174            16899:       Result.setIdentifier(Id, IdLoc);      
    1175                 :     }
    1176                 : 
    1177                 :     // If the next token is a '<', we may have a template.
                        3: branch 1 taken
                    17545: branch 2 taken
    1178            17548:     if (Tok.is(tok::less))
    1179                 :       return ParseUnqualifiedIdTemplateId(SS, Id, IdLoc, EnteringContext, 
    1180                3:                                           ObjectType, Result);
    1181                 :     
    1182            17545:     return false;
    1183                 :   }
    1184                 :   
    1185                 :   // unqualified-id:
    1186                 :   //   template-id (already parsed and annotated)
                      234: branch 1 taken
                      838: branch 2 taken
    1187             1072:   if (Tok.is(tok::annot_template_id)) {
    1188                 :     TemplateIdAnnotation *TemplateId
    1189              234:       = static_cast<TemplateIdAnnotation*>(Tok.getAnnotationValue());
    1190                 : 
    1191                 :     // If the template-name names the current class, then this is a constructor 
                       10: branch 0 taken
                      224: branch 1 taken
                       10: branch 2 taken
                        0: branch 3 not taken
                        7: branch 5 taken
                        3: branch 6 taken
                        7: branch 7 taken
                      227: branch 8 taken
    1192              234:     if (AllowConstructorName && TemplateId->Name &&
    1193                 :         Actions.isCurrentClassName(*TemplateId->Name, CurScope, &SS)) {
                        2: branch 1 taken
                        5: branch 2 taken
    1194                7:       if (SS.isSet()) {
    1195                 :         // C++ [class.qual]p2 specifies that a qualified template-name
    1196                 :         // is taken as the constructor name where a constructor can be
    1197                 :         // declared. Thus, the template arguments are extraneous, so
    1198                 :         // complain about them and remove them entirely.
    1199                 :         Diag(TemplateId->TemplateNameLoc, 
    1200                 :              diag::err_out_of_line_constructor_template_id)
    1201                 :           << TemplateId->Name
    1202                 :           << CodeModificationHint::CreateRemoval(
    1203                2:                     SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc));
    1204                 :         Result.setConstructorName(Actions.getTypeName(*TemplateId->Name,
    1205                 :                                                   TemplateId->TemplateNameLoc, 
    1206                 :                                                       CurScope,
    1207                 :                                                       &SS, false),
    1208                 :                                   TemplateId->TemplateNameLoc, 
    1209                2:                                   TemplateId->RAngleLoc);
    1210                2:         TemplateId->Destroy();
    1211                2:         ConsumeToken();
    1212                2:         return false;
    1213                 :       }
    1214                 : 
    1215                5:       Result.setConstructorTemplateId(TemplateId);
    1216                5:       ConsumeToken();
    1217                5:       return false;
    1218                 :     }
    1219                 : 
    1220                 :     // We have already parsed a template-id; consume the annotation token as
    1221                 :     // our unqualified-id.
    1222              227:     Result.setTemplateId(TemplateId);
    1223              227:     ConsumeToken();
    1224              227:     return false;
    1225                 :   }
    1226                 :   
    1227                 :   // unqualified-id:
    1228                 :   //   operator-function-id
    1229                 :   //   conversion-function-id
                      606: branch 1 taken
                      232: branch 2 taken
    1230              838:   if (Tok.is(tok::kw_operator)) {
                        8: branch 1 taken
                      598: branch 2 taken
    1231              606:     if (ParseUnqualifiedIdOperator(SS, EnteringContext, ObjectType, Result))
    1232                8:       return true;
    1233                 :     
    1234                 :     // If we have an operator-function-id or a literal-operator-id and the next
    1235                 :     // token is a '<', we may have a
    1236                 :     // 
    1237                 :     //   template-id:
    1238                 :     //     operator-function-id < template-argument-list[opt] >
                      301: branch 1 taken
                      297: branch 2 taken
                       21: branch 4 taken
                      280: branch 5 taken
                        3: branch 7 taken
                      315: branch 8 taken
                        3: branch 9 taken
                      595: branch 10 taken
    1239              598:     if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId ||
    1240                 :          Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) &&
    1241                 :         Tok.is(tok::less))
    1242                 :       return ParseUnqualifiedIdTemplateId(SS, 0, SourceLocation(), 
    1243                 :                                           EnteringContext, ObjectType, 
    1244                3:                                           Result);
    1245                 :     
    1246              595:     return false;
    1247                 :   }
    1248                 :   
                      226: branch 1 taken
                        6: branch 2 taken
                        7: branch 3 taken
                      219: branch 4 taken
                        7: branch 6 taken
                        0: branch 7 not taken
                      211: branch 9 taken
                       15: branch 10 taken
                      211: branch 11 taken
                       21: branch 12 taken
    1249              232:   if (getLang().CPlusPlus && 
    1250                 :       (AllowDestructorName || SS.isSet()) && Tok.is(tok::tilde)) {
    1251                 :     // C++ [expr.unary.op]p10:
    1252                 :     //   There is an ambiguity in the unary-expression ~X(), where X is a 
    1253                 :     //   class-name. The ambiguity is resolved in favor of treating ~ as a 
    1254                 :     //    unary complement rather than treating ~X as referring to a destructor.
    1255                 :     
    1256                 :     // Parse the '~'.
    1257              211:     SourceLocation TildeLoc = ConsumeToken();
    1258                 :     
    1259                 :     // Parse the class-name.
                        4: branch 1 taken
                      207: branch 2 taken
    1260              211:     if (Tok.isNot(tok::identifier)) {
    1261                4:       Diag(Tok, diag::err_destructor_class_name);
    1262                4:       return true;
    1263                 :     }
    1264                 : 
    1265                 :     // Parse the class-name (or template-name in a simple-template-id).
    1266              207:     IdentifierInfo *ClassName = Tok.getIdentifierInfo();
    1267              207:     SourceLocation ClassNameLoc = ConsumeToken();
    1268                 :     
                        1: branch 1 taken
                      206: branch 2 taken
    1269              207:     if (Tok.is(tok::less)) {
    1270                1:       Result.setDestructorName(TildeLoc, 0, ClassNameLoc);
    1271                 :       return ParseUnqualifiedIdTemplateId(SS, ClassName, ClassNameLoc,
    1272                1:                                           EnteringContext, ObjectType, Result);
    1273                 :     }
    1274                 :     
    1275                 :     // Note that this is a destructor name.
    1276                 :     Action::TypeTy *Ty = Actions.getTypeName(*ClassName, ClassNameLoc,
    1277              206:                                              CurScope, &SS, false, ObjectType);
                        2: branch 0 taken
                      204: branch 1 taken
    1278              206:     if (!Ty) {
                        1: branch 0 taken
                        1: branch 1 taken
    1279                2:       if (ObjectType)
    1280                 :         Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)
    1281                1:           << ClassName;        
    1282                 :       else
    1283                1:         Diag(ClassNameLoc, diag::err_destructor_class_name);
    1284                2:       return true;
    1285                 :     }
    1286                 :     
    1287              204:     Result.setDestructorName(TildeLoc, Ty, ClassNameLoc);
    1288              204:     return false;
    1289                 :   }
    1290                 :   
    1291                 :   Diag(Tok, diag::err_expected_unqualified_id)
    1292               21:     << getLang().CPlusPlus;
    1293               21:   return true;
    1294                 : }
    1295                 : 
    1296                 : /// ParseCXXNewExpression - Parse a C++ new-expression. New is used to allocate
    1297                 : /// memory in a typesafe manner and call constructors.
    1298                 : ///
    1299                 : /// This method is called to parse the new expression after the optional :: has
    1300                 : /// been already parsed.  If the :: was present, "UseGlobal" is true and "Start"
    1301                 : /// is its location.  Otherwise, "Start" is the location of the 'new' token.
    1302                 : ///
    1303                 : ///        new-expression:
    1304                 : ///                   '::'[opt] 'new' new-placement[opt] new-type-id
    1305                 : ///                                     new-initializer[opt]
    1306                 : ///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
    1307                 : ///                                     new-initializer[opt]
    1308                 : ///
    1309                 : ///        new-placement:
    1310                 : ///                   '(' expression-list ')'
    1311                 : ///
    1312                 : ///        new-type-id:
    1313                 : ///                   type-specifier-seq new-declarator[opt]
    1314                 : ///
    1315                 : ///        new-declarator:
    1316                 : ///                   ptr-operator new-declarator[opt]
    1317                 : ///                   direct-new-declarator
    1318                 : ///
    1319                 : ///        new-initializer:
    1320                 : ///                   '(' expression-list[opt] ')'
    1321                 : /// [C++0x]           braced-init-list                                   [TODO]
    1322                 : ///
    1323                 : Parser::OwningExprResult
    1324              115: Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) {
                      115: branch 1 taken
                        0: branch 2 not taken
    1325              115:   assert(Tok.is(tok::kw_new) && "expected 'new' token");
    1326              115:   ConsumeToken();   // Consume 'new'
    1327                 : 
    1328                 :   // A '(' now can be a new-placement or the '(' wrapping the type-id in the
    1329                 :   // second form of new-expression. It can't be a new-type-id.
    1330                 : 
    1331              115:   ExprVector PlacementArgs(Actions);
    1332              115:   SourceLocation PlacementLParen, PlacementRParen;
    1333                 : 
    1334                 :   bool ParenTypeId;
    1335              115:   DeclSpec DS;
    1336              115:   Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
                       32: branch 1 taken
                       83: branch 2 taken
    1337              115:   if (Tok.is(tok::l_paren)) {
    1338                 :     // If it turns out to be a placement, we change the type location.
    1339               32:     PlacementLParen = ConsumeParen();
                        1: branch 1 taken
                       31: branch 2 taken
    1340               32:     if (ParseExpressionListOrTypeId(PlacementArgs, DeclaratorInfo)) {
    1341                1:       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
    1342                1:       return ExprError();
    1343                 :     }
    1344                 : 
    1345               31:     PlacementRParen = MatchRHSPunctuation(tok::r_paren, PlacementLParen);
                        0: branch 1 not taken
                       31: branch 2 taken
    1346               31:     if (PlacementRParen.isInvalid()) {
    1347                0:       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
    1348                0:       return ExprError();
    1349                 :     }
    1350                 : 
                        6: branch 1 taken
                       25: branch 2 taken
    1351               31:     if (PlacementArgs.empty()) {
    1352                 :       // Reset the placement locations. There was no placement.
    1353                6:       PlacementLParen = PlacementRParen = SourceLocation();
    1354                6:       ParenTypeId = true;
    1355                 :     } else {
    1356                 :       // We still need the type.
                        1: branch 1 taken
                       24: branch 2 taken
    1357               25:       if (Tok.is(tok::l_paren)) {
    1358                1:         SourceLocation LParen = ConsumeParen();
    1359                1:         ParseSpecifierQualifierList(DS);
    1360                1:         DeclaratorInfo.SetSourceRange(DS.getSourceRange());
    1361                1:         ParseDeclarator(DeclaratorInfo);
    1362                1:         MatchRHSPunctuation(tok::r_paren, LParen);
    1363                1:         ParenTypeId = true;
    1364                 :       } else {
                        0: branch 1 not taken
                       24: branch 2 taken
    1365               24:         if (ParseCXXTypeSpecifierSeq(DS))
    1366                0:           DeclaratorInfo.setInvalidType(true);
    1367                 :         else {
    1368               24:           DeclaratorInfo.SetSourceRange(DS.getSourceRange());
    1369                 :           ParseDeclaratorInternal(DeclaratorInfo,
    1370               24:                                   &Parser::ParseDirectNewDeclarator);
    1371                 :         }
    1372               24:         ParenTypeId = false;
    1373                 :       }
    1374                 :     }
    1375                 :   } else {
    1376                 :     // A new-type-id is a simplified type-id, where essentially the
    1377                 :     // direct-declarator is replaced by a direct-new-declarator.
                        2: branch 1 taken
                       81: branch 2 taken
    1378               83:     if (ParseCXXTypeSpecifierSeq(DS))
    1379                2:       DeclaratorInfo.setInvalidType(true);
    1380                 :     else {
    1381               81:       DeclaratorInfo.SetSourceRange(DS.getSourceRange());
    1382                 :       ParseDeclaratorInternal(DeclaratorInfo,
    1383               81:                               &Parser::ParseDirectNewDeclarator);
    1384                 :     }
    1385               83:     ParenTypeId = false;
    1386                 :   }
                        2: branch 1 taken
                      112: branch 2 taken
    1387              114:   if (DeclaratorInfo.isInvalidType()) {
    1388                2:     SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
    1389                2:     return ExprError();
    1390                 :   }
    1391                 : 
    1392              112:   ExprVector ConstructorArgs(Actions);
    1393              112:   SourceLocation ConstructorLParen, ConstructorRParen;
    1394                 : 
                       45: branch 1 taken
                       67: branch 2 taken
    1395              112:   if (Tok.is(tok::l_paren)) {
    1396               45:     ConstructorLParen = ConsumeParen();
                       35: branch 1 taken
                       10: branch 2 taken
    1397               45:     if (Tok.isNot(tok::r_paren)) {
    1398               35:       CommaLocsTy CommaLocs;
                        0: branch 1 not taken
                       35: branch 2 taken
    1399               35:       if (ParseExpressionList(ConstructorArgs, CommaLocs)) {
    1400                0:         SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
    1401                0:         return ExprError();
                       35: branch 1 taken
                        0: branch 2 not taken
    1402               35:       }
    1403                 :     }
    1404               45:     ConstructorRParen = MatchRHSPunctuation(tok::r_paren, ConstructorLParen);
                        0: branch 1 not taken
                       45: branch 2 taken
    1405               45:     if (ConstructorRParen.isInvalid()) {
    1406                0:       SkipUntil(tok::semi, /*StopAtSemi=*/true, /*DontConsume=*/true);
    1407                0:       return ExprError();
    1408                 :     }
    1409                 :   }
    1410                 : 
    1411                 :   return Actions.ActOnCXXNew(Start, UseGlobal, PlacementLParen,
    1412                 :                              move_arg(PlacementArgs), PlacementRParen,
    1413                 :                              ParenTypeId, DeclaratorInfo, ConstructorLParen,
    1414              112:                              move_arg(ConstructorArgs), ConstructorRParen);
    1415                 : }
    1416                 : 
    1417                 : /// ParseDirectNewDeclarator - Parses a direct-new-declarator. Intended to be
    1418                 : /// passed to ParseDeclaratorInternal.
    1419                 : ///
    1420                 : ///        direct-new-declarator:
    1421                 : ///                   '[' expression ']'
    1422                 : ///                   direct-new-declarator '[' constant-expression ']'
    1423                 : ///
    1424              105: void Parser::ParseDirectNewDeclarator(Declarator &D) {
    1425                 :   // Parse the array dimensions.
    1426              105:   bool first = true;
                       23: branch 1 taken
                        0: branch 2 not taken
                       23: branch 4 taken
                      105: branch 5 taken
    1427              256:   while (Tok.is(tok::l_square)) {
    1428               23:     SourceLocation LLoc = ConsumeBracket();
    1429                 :     OwningExprResult Size(first ? ParseExpression()
                       21: branch 0 taken
                        2: branch 1 taken
    1430               23:                                 : ParseConstantExpression());
                        0: branch 1 not taken
                       23: branch 2 taken
    1431               23:     if (Size.isInvalid()) {
    1432                 :       // Recover
    1433                0:       SkipUntil(tok::r_square);
    1434                0:       return;
    1435                 :     }
    1436               23:     first = false;
    1437                 : 
    1438               23:     SourceLocation RLoc = MatchRHSPunctuation(tok::r_square, LLoc);
    1439                 :     D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false,
    1440                 :                                             Size.release(), LLoc, RLoc),
    1441               23:                   RLoc);
    1442                 : 
                        0: branch 1 not taken
                       23: branch 2 taken
    1443               23:     if (RLoc.isInvalid())
    1444                 :       return;
    1445                 :   }
    1446                 : }
    1447                 : 
    1448                 : /// ParseExpressionListOrTypeId - Parse either an expression-list or a type-id.
    1449                 : /// This ambiguity appears in the syntax of the C++ new operator.
    1450                 : ///
    1451                 : ///        new-expression:
    1452                 : ///                   '::'[opt] 'new' new-placement[opt] '(' type-id ')'
    1453                 : ///                                     new-initializer[opt]
    1454                 : ///
    1455                 : ///        new-placement:
    1456                 : ///                   '(' expression-list ')'
    1457                 : ///
    1458                 : bool Parser::ParseExpressionListOrTypeId(ExprListTy &PlacementArgs,
    1459               32:                                          Declarator &D) {
    1460                 :   // The '(' was already consumed.
                        6: branch 1 taken
                       26: branch 2 taken
    1461               32:   if (isTypeIdInParens()) {
    1462                6:     ParseSpecifierQualifierList(D.getMutableDeclSpec());
    1463                6:     D.SetSourceRange(D.getDeclSpec().getSourceRange());
    1464                6:     ParseDeclarator(D);
    1465                6:     return D.isInvalidType();
    1466                 :   }
    1467                 : 
    1468                 :   // It's not a type, it has to be an expression list.
    1469                 :   // Discard the comma locations - ActOnCXXNew has enough parameters.
    1470               26:   CommaLocsTy CommaLocs;
    1471               26:   return ParseExpressionList(PlacementArgs, CommaLocs);
    1472                 : }
    1473                 : 
    1474                 : /// ParseCXXDeleteExpression - Parse a C++ delete-expression. Delete is used
    1475                 : /// to free memory allocated by new.
    1476                 : ///
    1477                 : /// This method is called to parse the 'delete' expression after the optional
    1478                 : /// '::' has been already parsed.  If the '::' was present, "UseGlobal" is true
    1479                 : /// and "Start" is its location.  Otherwise, "Start" is the location of the
    1480                 : /// 'delete' token.
    1481                 : ///
    1482                 : ///        delete-expression:
    1483                 : ///                   '::'[opt] 'delete' cast-expression
    1484                 : ///                   '::'[opt] 'delete' '[' ']' cast-expression
    1485                 : Parser::OwningExprResult
    1486               50: Parser::ParseCXXDeleteExpression(bool UseGlobal, SourceLocation Start) {
                       50: branch 1 taken
                        0: branch 2 not taken
    1487               50:   assert(Tok.is(tok::kw_delete) && "Expected 'delete' keyword");
    1488               50:   ConsumeToken(); // Consume 'delete'
    1489                 : 
    1490                 :   // Array delete?
    1491               50:   bool ArrayDelete = false;
                       11: branch 1 taken
                       39: branch 2 taken
    1492               50:   if (Tok.is(tok::l_square)) {
    1493               11:     ArrayDelete = true;
    1494               11:     SourceLocation LHS = ConsumeBracket();
    1495               11:     SourceLocation RHS = MatchRHSPunctuation(tok::r_square, LHS);
                        0: branch 1 not taken
                       11: branch 2 taken
    1496               11:     if (RHS.isInvalid())
    1497                0:       return ExprError();
    1498                 :   }
    1499                 : 
    1500               50:   OwningExprResult Operand(ParseCastExpression(false));
                        0: branch 1 not taken
                       50: branch 2 taken
    1501               50:   if (Operand.isInvalid())
    1502                0:     return move(Operand);
    1503                 : 
    1504               50:   return Actions.ActOnCXXDelete(Start, UseGlobal, ArrayDelete, move(Operand));
    1505                 : }
    1506                 : 
    1507              180: static UnaryTypeTrait UnaryTypeTraitFromTokKind(tok::TokenKind kind) {
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                       18: branch 4 taken
                       18: branch 5 taken
                       26: branch 6 taken
                       28: branch 7 taken
                        0: branch 8 not taken
                        4: branch 9 taken
                        9: branch 10 taken
                       18: branch 11 taken
                        9: branch 12 taken
                       27: branch 13 taken
                       11: branch 14 taken
                        7: branch 15 taken
                        5: branch 16 taken
    1508              180:   switch(kind) {
    1509                0:   default: assert(false && "Not a known unary type trait.");
    1510                0:   case tok::kw___has_nothrow_assign:      return UTT_HasNothrowAssign;
    1511                0:   case tok::kw___has_nothrow_copy:        return UTT_HasNothrowCopy;
    1512                0:   case tok::kw___has_nothrow_constructor: return UTT_HasNothrowConstructor;
    1513               18:   case tok::kw___has_trivial_assign:      return UTT_HasTrivialAssign;
    1514               18:   case tok::kw___has_trivial_copy:        return UTT_HasTrivialCopy;
    1515               26:   case tok::kw___has_trivial_constructor: return UTT_HasTrivialConstructor;
    1516               28:   case tok::kw___has_trivial_destructor:  return UTT_HasTrivialDestructor;
    1517                0:   case tok::kw___has_virtual_destructor:  return UTT_HasVirtualDestructor;
    1518                4:   case tok::kw___is_abstract:             return UTT_IsAbstract;
    1519                9:   case tok::kw___is_class:                return UTT_IsClass;
    1520               18:   case tok::kw___is_empty:                return UTT_IsEmpty;
    1521                9:   case tok::kw___is_enum:                 return UTT_IsEnum;
    1522               27:   case tok::kw___is_pod:                  return UTT_IsPOD;
    1523               11:   case tok::kw___is_polymorphic:          return UTT_IsPolymorphic;
    1524                7:   case tok::kw___is_union:                return UTT_IsUnion;
    1525                5:   case tok::kw___is_literal:              return UTT_IsLiteral;
    1526                 :   }
    1527                 : }
    1528                 : 
    1529                 : /// ParseUnaryTypeTrait - Parse the built-in unary type-trait
    1530                 : /// pseudo-functions that allow implementation of the TR1/C++0x type traits
    1531                 : /// templates.
    1532                 : ///
    1533                 : ///       primary-expression:
    1534                 : /// [GNU]             unary-type-trait '(' type-id ')'
    1535                 : ///
    1536              180: Parser::OwningExprResult Parser::ParseUnaryTypeTrait() {
    1537              180:   UnaryTypeTrait UTT = UnaryTypeTraitFromTokKind(Tok.getKind());
    1538              180:   SourceLocation Loc = ConsumeToken();
    1539                 : 
    1540              180:   SourceLocation LParen = Tok.getLocation();
                        0: branch 1 not taken
                      180: branch 2 taken
    1541              180:   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen))
    1542                0:     return ExprError();
    1543                 : 
    1544                 :   // FIXME: Error reporting absolutely sucks! If the this fails to parse a type
    1545                 :   // there will be cryptic errors about mismatched parentheses and missing
    1546                 :   // specifiers.
    1547              180:   TypeResult Ty = ParseTypeName();
    1548                 : 
    1549              180:   SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
    1550                 : 
                        0: branch 1 not taken
                      180: branch 2 taken
    1551              180:   if (Ty.isInvalid())
    1552                0:     return ExprError();
    1553                 : 
    1554              180:   return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
    1555                 : }
    1556                 : 
    1557                 : /// ParseCXXAmbiguousParenExpression - We have parsed the left paren of a
    1558                 : /// parenthesized ambiguous type-id. This uses tentative parsing to disambiguate
    1559                 : /// based on the context past the parens.
    1560                 : Parser::OwningExprResult
    1561                 : Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType,
    1562                 :                                          TypeTy *&CastTy,
    1563                 :                                          SourceLocation LParenLoc,
    1564               35:                                          SourceLocation &RParenLoc) {
                       35: branch 1 taken
                        0: branch 2 not taken
    1565               35:   assert(getLang().CPlusPlus && "Should only be called for C++!");
                        0: branch 0 not taken
                       35: branch 1 taken
    1566               35:   assert(ExprType == CastExpr && "Compound literals are not ambiguous!");
                       35: branch 1 taken
                        0: branch 2 not taken
    1567               35:   assert(isTypeIdInParens() && "Not a type-id!");
    1568                 : 
    1569               35:   OwningExprResult Result(Actions, true);
    1570               35:   CastTy = 0;
    1571                 : 
    1572                 :   // We need to disambiguate a very ugly part of the C++ syntax:
    1573                 :   //
    1574                 :   // (T())x;  - type-id
    1575                 :   // (T())*x; - type-id
    1576                 :   // (T())/x; - expression
    1577                 :   // (T());   - expression
    1578                 :   //
    1579                 :   // The bad news is that we cannot use the specialized tentative parser, since
    1580                 :   // it can only verify that the thing inside the parens can be parsed as
    1581                 :   // type-id, it is not useful for determining the context past the parens.
    1582                 :   //
    1583                 :   // The good news is that the parser can disambiguate this part without
    1584                 :   // making any unnecessary Action calls.
    1585                 :   //
    1586                 :   // It uses a scheme similar to parsing inline methods. The parenthesized
    1587                 :   // tokens are cached, the context that follows is determined (possibly by
    1588                 :   // parsing a cast-expression), and then we re-introduce the cached tokens
    1589                 :   // into the token stream and parse them appropriately.
    1590                 : 
    1591                 :   ParenParseOption ParseAs;
    1592               35:   CachedTokens Toks;
    1593                 : 
    1594                 :   // Store the tokens of the parentheses. We will parse them after we determine
    1595                 :   // the context that follows them.
                        0: branch 1 not taken
                       35: branch 2 taken
    1596               35:   if (!ConsumeAndStoreUntil(tok::r_paren, tok::unknown, Toks, tok::semi)) {
    1597                 :     // We didn't find the ')' we expected.
    1598                0:     MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1599                0:     return ExprError();
    1600                 :   }
    1601                 : 
                        0: branch 1 not taken
                       35: branch 2 taken
    1602               35:   if (Tok.is(tok::l_brace)) {
    1603                0:     ParseAs = CompoundLiteral;
    1604                 :   } else {
    1605                 :     bool NotCastExpr;
    1606                 :     // FIXME: Special-case ++ and --: "(S())++;" is not a cast-expression
                        7: branch 1 taken
                       28: branch 2 taken
                        1: branch 5 taken
                        6: branch 6 taken
                        1: branch 7 taken
                       34: branch 8 taken
    1607               35:     if (Tok.is(tok::l_paren) && NextToken().is(tok::r_paren)) {
    1608                1:       NotCastExpr = true;
    1609                 :     } else {
    1610                 :       // Try parsing the cast-expression that may follow.
    1611                 :       // If it is not a cast-expression, NotCastExpr will be true and no token
    1612                 :       // will be consumed.
    1613                 :       Result = ParseCastExpression(false/*isUnaryExpression*/,
    1614                 :                                    false/*isAddressofOperand*/,
    1615               34:                                    NotCastExpr, false);
    1616                 :     }
    1617                 : 
    1618                 :     // If we parsed a cast-expression, it's really a type-id, otherwise it's
    1619                 :     // an expression.
                       10: branch 0 taken
                       25: branch 1 taken
    1620               35:     ParseAs = NotCastExpr ? SimpleExpr : CastExpr;
    1621                 :   }
    1622                 : 
    1623                 :   // The current token should go after the cached tokens.
    1624               35:   Toks.push_back(Tok);
    1625                 :   // Re-enter the stored parenthesized tokens into the token stream, so we may
    1626                 :   // parse them now.
    1627                 :   PP.EnterTokenStream(Toks.data(), Toks.size(),
    1628               35:                       true/*DisableMacroExpansion*/, false/*OwnsTokens*/);
    1629                 :   // Drop the current token and bring the first cached one. It's the same token
    1630                 :   // as when we entered this function.
    1631               35:   ConsumeAnyToken();
    1632                 : 
                       25: branch 0 taken
                       10: branch 1 taken
    1633               35:   if (ParseAs >= CompoundLiteral) {
    1634               25:     TypeResult Ty = ParseTypeName();
    1635                 : 
    1636                 :     // Match the ')'.
                       25: branch 1 taken
                        0: branch 2 not taken
    1637               25:     if (Tok.is(tok::r_paren))
    1638               25:       RParenLoc = ConsumeParen();
    1639                 :     else
    1640                0:       MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1641                 : 
                        0: branch 0 not taken
                       25: branch 1 taken
    1642               25:     if (ParseAs == CompoundLiteral) {
    1643                0:       ExprType = CompoundLiteral;
    1644                0:       return ParseCompoundLiteralExpression(Ty.get(), LParenLoc, RParenLoc);
    1645                 :     }
    1646                 : 
    1647                 :     // We parsed '(' type-id ')' and the thing after it wasn't a '{'.
                        0: branch 0 not taken
                       25: branch 1 taken
    1648               25:     assert(ParseAs == CastExpr);
    1649                 : 
                        0: branch 1 not taken
                       25: branch 2 taken
    1650               25:     if (Ty.isInvalid())
    1651                0:       return ExprError();
    1652                 : 
    1653               25:     CastTy = Ty.get();
    1654                 : 
    1655                 :     // Result is what ParseCastExpression returned earlier.
                       25: branch 1 taken
                        0: branch 2 not taken
    1656               25:     if (!Result.isInvalid())
    1657                 :       Result = Actions.ActOnCastExpr(CurScope, LParenLoc, CastTy, RParenLoc,
    1658               25:                                      move(Result));
    1659               25:     return move(Result);
    1660                 :   }
    1661                 : 
    1662                 :   // Not a compound literal, and not followed by a cast-expression.
                        0: branch 0 not taken
                       10: branch 1 taken
    1663               10:   assert(ParseAs == SimpleExpr);
    1664                 : 
    1665               10:   ExprType = SimpleExpr;
    1666               10:   Result = ParseExpression();
                       10: branch 1 taken
                        0: branch 2 not taken
                       10: branch 4 taken
                        0: branch 5 not taken
                       10: branch 6 taken
                        0: branch 7 not taken
    1667               10:   if (!Result.isInvalid() && Tok.is(tok::r_paren))
    1668               10:     Result = Actions.ActOnParenExpr(LParenLoc, Tok.getLocation(), move(Result));
    1669                 : 
    1670                 :   // Match the ')'.
                        0: branch 1 not taken
                       10: branch 2 taken
    1671               10:   if (Result.isInvalid()) {
    1672                0:     SkipUntil(tok::r_paren);
    1673                0:     return ExprError();
    1674                 :   }
    1675                 : 
                       10: branch 1 taken
                        0: branch 2 not taken
    1676               10:   if (Tok.is(tok::r_paren))
    1677               10:     RParenLoc = ConsumeParen();
    1678                 :   else
    1679                0:     MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1680                 : 
    1681               10:   return move(Result);
    1682                 : }

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