zcov: / lib/Parse/ParseDeclCXX.cpp


Files: 1 Branches Taken: 82.5% 498 / 604
Generated: 2010-02-10 01:31 Branches Executed: 99.7% 602 / 604
Line Coverage: 91.1% 674 / 740


Programs: 2 Runs 3018


       1                 : //===--- ParseDeclCXX.cpp - C++ Declaration 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 C++ Declaration portions of the Parser interfaces.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Basic/OperatorKinds.h"
      15                 : #include "clang/Parse/Parser.h"
      16                 : #include "clang/Parse/ParseDiagnostic.h"
      17                 : #include "clang/Parse/DeclSpec.h"
      18                 : #include "clang/Parse/Scope.h"
      19                 : #include "clang/Parse/Template.h"
      20                 : #include "RAIIObjectsForParser.h"
      21                 : using namespace clang;
      22                 : 
      23                 : /// ParseNamespace - We know that the current token is a namespace keyword. This
      24                 : /// may either be a top level namespace or a block-level namespace alias.
      25                 : ///
      26                 : ///       namespace-definition: [C++ 7.3: basic.namespace]
      27                 : ///         named-namespace-definition
      28                 : ///         unnamed-namespace-definition
      29                 : ///
      30                 : ///       unnamed-namespace-definition:
      31                 : ///         'namespace' attributes[opt] '{' namespace-body '}'
      32                 : ///
      33                 : ///       named-namespace-definition:
      34                 : ///         original-namespace-definition
      35                 : ///         extension-namespace-definition
      36                 : ///
      37                 : ///       original-namespace-definition:
      38                 : ///         'namespace' identifier attributes[opt] '{' namespace-body '}'
      39                 : ///
      40                 : ///       extension-namespace-definition:
      41                 : ///         'namespace' original-namespace-name '{' namespace-body '}'
      42                 : ///
      43                 : ///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
      44                 : ///         'namespace' identifier '=' qualified-namespace-specifier ';'
      45                 : ///
      46                 : Parser::DeclPtrTy Parser::ParseNamespace(unsigned Context,
      47              694:                                          SourceLocation &DeclEnd) {
                      694: branch 1 taken
                        0: branch 2 not taken
      48              694:   assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
      49              694:   SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.
      50                 : 
                        1: branch 1 taken
                      693: branch 2 taken
      51              694:   if (Tok.is(tok::code_completion)) {
      52                1:     Actions.CodeCompleteNamespaceDecl(CurScope);
      53                1:     ConsumeToken();
      54                 :   }
      55                 :   
      56              694:   SourceLocation IdentLoc;
      57              694:   IdentifierInfo *Ident = 0;
      58                 : 
      59              694:   Token attrTok;
      60                 : 
                      675: branch 1 taken
                       19: branch 2 taken
      61              694:   if (Tok.is(tok::identifier)) {
      62              675:     Ident = Tok.getIdentifierInfo();
      63              675:     IdentLoc = ConsumeToken();  // eat the identifier.
      64                 :   }
      65                 : 
      66                 :   // Read label attributes, if present.
      67              694:   AttributeList *AttrList = 0;
                        3: branch 1 taken
                      691: branch 2 taken
      68              694:   if (Tok.is(tok::kw___attribute)) {
      69                3:     attrTok = Tok;
      70                 : 
      71                 :     // FIXME: save these somewhere.
      72                3:     AttrList = ParseGNUAttributes();
      73                 :   }
      74                 : 
                       34: branch 1 taken
                      660: branch 2 taken
      75              694:   if (Tok.is(tok::equal)) {
                        1: branch 0 taken
                       33: branch 1 taken
      76               34:     if (AttrList)
      77                1:       Diag(attrTok, diag::err_unexpected_namespace_attributes_alias);
      78                 : 
      79               34:     return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
      80                 :   }
      81                 : 
                        1: branch 1 taken
                      659: branch 2 taken
      82              660:   if (Tok.isNot(tok::l_brace)) {
      83                 :     Diag(Tok, Ident ? diag::err_expected_lbrace :
                        0: branch 0 not taken
                        1: branch 1 taken
      84                1:          diag::err_expected_ident_lbrace);
      85                1:     return DeclPtrTy();
      86                 :   }
      87                 : 
      88              659:   SourceLocation LBrace = ConsumeBrace();
      89                 : 
      90                 :   // Enter a scope for the namespace.
      91              659:   ParseScope NamespaceScope(this, Scope::DeclScope);
      92                 : 
      93                 :   DeclPtrTy NamespcDecl =
      94              659:     Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace, AttrList);
      95                 : 
      96                 :   PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
      97                 :                                         PP.getSourceManager(),
      98              659:                                         "parsing namespace");
      99                 : 
                     1646: branch 1 taken
                      653: branch 2 taken
                     1640: branch 4 taken
                        6: branch 5 taken
                     1640: branch 6 taken
                      659: branch 7 taken
     100             2958:   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     101             1640:     CXX0XAttributeList Attr;
                      103: branch 1 taken
                     1537: branch 2 taken
                        0: branch 4 not taken
                      103: branch 5 taken
                        0: branch 6 not taken
                     1640: branch 7 taken
     102             1640:     if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
     103                0:       Attr = ParseCXX0XAttributes();
     104             1640:     ParseExternalDeclaration(Attr);
     105                 :   }
     106                 : 
     107                 :   // Leave the namespace scope.
     108              659:   NamespaceScope.Exit();
     109                 : 
     110              659:   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);
     111              659:   Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);
     112                 : 
     113              659:   DeclEnd = RBraceLoc;
     114              659:   return NamespcDecl;
     115                 : }
     116                 : 
     117                 : /// ParseNamespaceAlias - Parse the part after the '=' in a namespace
     118                 : /// alias definition.
     119                 : ///
     120                 : Parser::DeclPtrTy Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
     121                 :                                               SourceLocation AliasLoc,
     122                 :                                               IdentifierInfo *Alias,
     123               34:                                               SourceLocation &DeclEnd) {
                       34: branch 1 taken
                        0: branch 2 not taken
     124               34:   assert(Tok.is(tok::equal) && "Not equal token");
     125                 : 
     126               34:   ConsumeToken(); // eat the '='.
     127                 : 
                        1: branch 1 taken
                       33: branch 2 taken
     128               34:   if (Tok.is(tok::code_completion)) {
     129                1:     Actions.CodeCompleteNamespaceAliasDecl(CurScope);
     130                1:     ConsumeToken();
     131                 :   }
     132                 :   
     133               34:   CXXScopeSpec SS;
     134                 :   // Parse (optional) nested-name-specifier.
     135               34:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
     136                 : 
                       33: branch 1 taken
                        1: branch 2 taken
                        2: branch 4 taken
                       31: branch 5 taken
                        3: branch 6 taken
                       31: branch 7 taken
     137               34:   if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
     138                3:     Diag(Tok, diag::err_expected_namespace_name);
     139                 :     // Skip to end of the definition and eat the ';'.
     140                3:     SkipUntil(tok::semi);
     141                3:     return DeclPtrTy();
     142                 :   }
     143                 : 
     144                 :   // Parse identifier.
     145               31:   IdentifierInfo *Ident = Tok.getIdentifierInfo();
     146               31:   SourceLocation IdentLoc = ConsumeToken();
     147                 : 
     148                 :   // Eat the ';'.
     149               31:   DeclEnd = Tok.getLocation();
     150                 :   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name,
     151               31:                    "", tok::semi);
     152                 : 
     153                 :   return Actions.ActOnNamespaceAliasDef(CurScope, NamespaceLoc, AliasLoc, Alias,
     154               31:                                         SS, IdentLoc, Ident);
     155                 : }
     156                 : 
     157                 : /// ParseLinkage - We know that the current token is a string_literal
     158                 : /// and just before that, that extern was seen.
     159                 : ///
     160                 : ///       linkage-specification: [C++ 7.5p2: dcl.link]
     161                 : ///         'extern' string-literal '{' declaration-seq[opt] '}'
     162                 : ///         'extern' string-literal declaration
     163                 : ///
     164                 : Parser::DeclPtrTy Parser::ParseLinkage(ParsingDeclSpec &DS,
     165              111:                                        unsigned Context) {
                      111: branch 1 taken
                        0: branch 2 not taken
     166              111:   assert(Tok.is(tok::string_literal) && "Not a string literal!");
     167              111:   llvm::SmallVector<char, 8> LangBuffer;
     168                 :   // LangBuffer is guaranteed to be big enough.
     169              111:   LangBuffer.resize(Tok.getLength());
     170              111:   const char *LangBufPtr = &LangBuffer[0];
     171              111:   unsigned StrSize = PP.getSpelling(Tok, LangBufPtr);
     172                 : 
     173              111:   SourceLocation Loc = ConsumeStringToken();
     174                 : 
     175              111:   ParseScope LinkageScope(this, Scope::DeclScope);
     176                 :   DeclPtrTy LinkageSpec
     177                 :     = Actions.ActOnStartLinkageSpecification(CurScope,
     178                 :                                              /*FIXME: */SourceLocation(),
     179                 :                                              Loc, LangBufPtr, StrSize,
     180                 :                                        Tok.is(tok::l_brace)? Tok.getLocation()
                       40: branch 1 taken
                       71: branch 2 taken
     181              151:                                                            : SourceLocation());
     182                 : 
     183              111:   CXX0XAttributeList Attr;
                       28: branch 1 taken
                       83: branch 2 taken
                        2: branch 4 taken
                       26: branch 5 taken
                        2: branch 6 taken
                      109: branch 7 taken
     184              111:   if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) {
     185                2:     Attr = ParseCXX0XAttributes();
     186                 :   }
     187                 :   
                       70: branch 1 taken
                       41: branch 2 taken
     188              111:   if (Tok.isNot(tok::l_brace)) {
     189               70:     ParseDeclarationOrFunctionDefinition(DS, Attr.AttrList);
     190                 :     return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec,
     191               70:                                                    SourceLocation());
     192                 :   }
     193                 : 
     194               41:   DS.abort();
     195                 : 
                        1: branch 0 taken
                       40: branch 1 taken
     196               41:   if (Attr.HasAttr)
     197                 :     Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
     198                1:       << Attr.Range;
     199                 : 
     200               41:   SourceLocation LBrace = ConsumeBrace();
                      550: branch 1 taken
                       41: branch 2 taken
                      550: branch 4 taken
                        0: branch 5 not taken
                      550: branch 6 taken
                       41: branch 7 taken
     201              632:   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
     202              550:     CXX0XAttributeList Attr;
                        1: branch 1 taken
                      549: branch 2 taken
                        0: branch 4 not taken
                        1: branch 5 taken
                        0: branch 6 not taken
                      550: branch 7 taken
     203              550:     if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
     204                0:       Attr = ParseCXX0XAttributes();
     205              550:     ParseExternalDeclaration(Attr);
     206                 :   }
     207                 : 
     208               41:   SourceLocation RBrace = MatchRHSPunctuation(tok::r_brace, LBrace);
     209               41:   return Actions.ActOnFinishLinkageSpecification(CurScope, LinkageSpec, RBrace);
     210                 : }
     211                 : 
     212                 : /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
     213                 : /// using-directive. Assumes that current token is 'using'.
     214                 : Parser::DeclPtrTy Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
     215                 :                                                      SourceLocation &DeclEnd,
     216              150:                                                      CXX0XAttributeList Attr) {
                      150: branch 1 taken
                        0: branch 2 not taken
     217              150:   assert(Tok.is(tok::kw_using) && "Not using token");
     218                 : 
     219                 :   // Eat 'using'.
     220              150:   SourceLocation UsingLoc = ConsumeToken();
     221                 : 
                        1: branch 1 taken
                      149: branch 2 taken
     222              150:   if (Tok.is(tok::code_completion)) {
     223                1:     Actions.CodeCompleteUsing(CurScope);
     224                1:     ConsumeToken();
     225                 :   }
     226                 :   
                       92: branch 1 taken
                       58: branch 2 taken
     227              150:   if (Tok.is(tok::kw_namespace))
     228                 :     // Next token after 'using' is 'namespace' so it must be using-directive
     229               92:     return ParseUsingDirective(Context, UsingLoc, DeclEnd, Attr.AttrList);
     230                 : 
                        1: branch 0 taken
                       57: branch 1 taken
     231               58:   if (Attr.HasAttr)
     232                 :     Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed)
     233                1:       << Attr.Range;
     234                 : 
     235                 :   // Otherwise, it must be using-declaration.
     236                 :   // Ignore illegal attributes (the caller should already have issued an error.
     237               58:   return ParseUsingDeclaration(Context, UsingLoc, DeclEnd);
     238                 : }
     239                 : 
     240                 : /// ParseUsingDirective - Parse C++ using-directive, assumes
     241                 : /// that current token is 'namespace' and 'using' was already parsed.
     242                 : ///
     243                 : ///       using-directive: [C++ 7.3.p4: namespace.udir]
     244                 : ///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
     245                 : ///                 namespace-name ;
     246                 : /// [GNU] using-directive:
     247                 : ///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
     248                 : ///                 namespace-name attributes[opt] ;
     249                 : ///
     250                 : Parser::DeclPtrTy Parser::ParseUsingDirective(unsigned Context,
     251                 :                                               SourceLocation UsingLoc,
     252                 :                                               SourceLocation &DeclEnd,
     253               92:                                               AttributeList *Attr) {
                       92: branch 1 taken
                        0: branch 2 not taken
     254               92:   assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");
     255                 : 
     256                 :   // Eat 'namespace'.
     257               92:   SourceLocation NamespcLoc = ConsumeToken();
     258                 : 
                        1: branch 1 taken
                       91: branch 2 taken
     259               92:   if (Tok.is(tok::code_completion)) {
     260                1:     Actions.CodeCompleteUsingDirective(CurScope);
     261                1:     ConsumeToken();
     262                 :   }
     263                 :   
     264               92:   CXXScopeSpec SS;
     265                 :   // Parse (optional) nested-name-specifier.
     266               92:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
     267                 : 
     268               92:   IdentifierInfo *NamespcName = 0;
     269               92:   SourceLocation IdentLoc = SourceLocation();
     270                 : 
     271                 :   // Parse namespace-name.
                       92: branch 1 taken
                        0: branch 2 not taken
                        2: branch 4 taken
                       90: branch 5 taken
                        2: branch 6 taken
                       90: branch 7 taken
     272               92:   if (SS.isInvalid() || Tok.isNot(tok::identifier)) {
     273                2:     Diag(Tok, diag::err_expected_namespace_name);
     274                 :     // If there was invalid namespace name, skip to end of decl, and eat ';'.
     275                2:     SkipUntil(tok::semi);
     276                 :     // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
     277                2:     return DeclPtrTy();
     278                 :   }
     279                 : 
     280                 :   // Parse identifier.
     281               90:   NamespcName = Tok.getIdentifierInfo();
     282               90:   IdentLoc = ConsumeToken();
     283                 : 
     284                 :   // Parse (optional) attributes (most likely GNU strong-using extension).
     285               90:   bool GNUAttr = false;
                        0: branch 1 not taken
                       90: branch 2 taken
     286               90:   if (Tok.is(tok::kw___attribute)) {
     287                0:     GNUAttr = true;
     288                0:     Attr = addAttributeLists(Attr, ParseGNUAttributes());
     289                 :   }
     290                 : 
     291                 :   // Eat ';'.
     292               90:   DeclEnd = Tok.getLocation();
     293                 :   ExpectAndConsume(tok::semi,
     294                 :                    GNUAttr ? diag::err_expected_semi_after_attribute_list :
                        0: branch 0 not taken
                       90: branch 1 taken
     295               90:                    diag::err_expected_semi_after_namespace_name, "", tok::semi);
     296                 : 
     297                 :   return Actions.ActOnUsingDirective(CurScope, UsingLoc, NamespcLoc, SS,
     298               90:                                       IdentLoc, NamespcName, Attr);
     299                 : }
     300                 : 
     301                 : /// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that
     302                 : /// 'using' was already seen.
     303                 : ///
     304                 : ///     using-declaration: [C++ 7.3.p3: namespace.udecl]
     305                 : ///       'using' 'typename'[opt] ::[opt] nested-name-specifier
     306                 : ///               unqualified-id
     307                 : ///       'using' :: unqualified-id
     308                 : ///
     309                 : Parser::DeclPtrTy Parser::ParseUsingDeclaration(unsigned Context,
     310                 :                                                 SourceLocation UsingLoc,
     311                 :                                                 SourceLocation &DeclEnd,
     312              130:                                                 AccessSpecifier AS) {
     313              130:   CXXScopeSpec SS;
     314              130:   SourceLocation TypenameLoc;
     315                 :   bool IsTypeName;
     316                 : 
     317                 :   // Ignore optional 'typename'.
     318                 :   // FIXME: This is wrong; we should parse this as a typename-specifier.
                        8: branch 1 taken
                      122: branch 2 taken
     319              130:   if (Tok.is(tok::kw_typename)) {
     320                8:     TypenameLoc = Tok.getLocation();
     321                8:     ConsumeToken();
     322                8:     IsTypeName = true;
     323                 :   }
     324                 :   else
     325              122:     IsTypeName = false;
     326                 : 
     327                 :   // Parse nested-name-specifier.
     328              130:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
     329                 : 
     330              130:   AttributeList *AttrList = 0;
     331                 : 
     332                 :   // Check nested-name specifier.
                        0: branch 1 not taken
                      130: branch 2 taken
     333              130:   if (SS.isInvalid()) {
     334                0:     SkipUntil(tok::semi);
     335                0:     return DeclPtrTy();
     336                 :   }
     337                 : 
     338                 :   // Parse the unqualified-id. We allow parsing of both constructor and 
     339                 :   // destructor names and allow the action module to diagnose any semantic
     340                 :   // errors.
     341              130:   UnqualifiedId Name;
                        1: branch 1 taken
                      129: branch 2 taken
     342              130:   if (ParseUnqualifiedId(SS, 
     343                 :                          /*EnteringContext=*/false,
     344                 :                          /*AllowDestructorName=*/true,
     345                 :                          /*AllowConstructorName=*/true, 
     346                 :                          /*ObjectType=*/0, 
     347                 :                          Name)) {
     348                1:     SkipUntil(tok::semi);
     349                1:     return DeclPtrTy();
     350                 :   }
     351                 :   
     352                 :   // Parse (optional) attributes (most likely GNU strong-using extension).
                        0: branch 1 not taken
                      129: branch 2 taken
     353              129:   if (Tok.is(tok::kw___attribute))
     354                0:     AttrList = ParseGNUAttributes();
     355                 : 
     356                 :   // Eat ';'.
     357              129:   DeclEnd = Tok.getLocation();
     358                 :   ExpectAndConsume(tok::semi, diag::err_expected_semi_after,
     359                 :                    AttrList ? "attributes list" : "using declaration", 
                        0: branch 0 not taken
                      129: branch 1 taken
     360              129:                    tok::semi);
     361                 : 
     362                 :   return Actions.ActOnUsingDeclaration(CurScope, AS, true, UsingLoc, SS, Name,
     363              129:                                        AttrList, IsTypeName, TypenameLoc);
     364                 : }
     365                 : 
     366                 : /// ParseStaticAssertDeclaration - Parse C++0x static_assert-declaratoion.
     367                 : ///
     368                 : ///      static_assert-declaration:
     369                 : ///        static_assert ( constant-expression  ,  string-literal  ) ;
     370                 : ///
     371               61: Parser::DeclPtrTy Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
                       61: branch 1 taken
                        0: branch 2 not taken
     372               61:   assert(Tok.is(tok::kw_static_assert) && "Not a static_assert declaration");
     373               61:   SourceLocation StaticAssertLoc = ConsumeToken();
     374                 : 
                        0: branch 1 not taken
                       61: branch 2 taken
     375               61:   if (Tok.isNot(tok::l_paren)) {
     376                0:     Diag(Tok, diag::err_expected_lparen);
     377                0:     return DeclPtrTy();
     378                 :   }
     379                 : 
     380               61:   SourceLocation LParenLoc = ConsumeParen();
     381                 : 
     382               61:   OwningExprResult AssertExpr(ParseConstantExpression());
                        0: branch 1 not taken
                       61: branch 2 taken
     383               61:   if (AssertExpr.isInvalid()) {
     384                0:     SkipUntil(tok::semi);
     385                0:     return DeclPtrTy();
     386                 :   }
     387                 : 
                        0: branch 1 not taken
                       61: branch 2 taken
     388               61:   if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "", tok::semi))
     389                0:     return DeclPtrTy();
     390                 : 
                        0: branch 1 not taken
                       61: branch 2 taken
     391               61:   if (Tok.isNot(tok::string_literal)) {
     392                0:     Diag(Tok, diag::err_expected_string_literal);
     393                0:     SkipUntil(tok::semi);
     394                0:     return DeclPtrTy();
     395                 :   }
     396                 : 
     397               61:   OwningExprResult AssertMessage(ParseStringLiteralExpression());
                        0: branch 1 not taken
                       61: branch 2 taken
     398               61:   if (AssertMessage.isInvalid())
     399                0:     return DeclPtrTy();
     400                 : 
     401               61:   MatchRHSPunctuation(tok::r_paren, LParenLoc);
     402                 : 
     403               61:   DeclEnd = Tok.getLocation();
     404               61:   ExpectAndConsume(tok::semi, diag::err_expected_semi_after_static_assert);
     405                 : 
     406                 :   return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc, move(AssertExpr),
     407               61:                                               move(AssertMessage));
     408                 : }
     409                 : 
     410                 : /// ParseDecltypeSpecifier - Parse a C++0x decltype specifier.
     411                 : ///
     412                 : /// 'decltype' ( expression )
     413                 : ///
     414               16: void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
                       16: branch 1 taken
                        0: branch 2 not taken
     415               16:   assert(Tok.is(tok::kw_decltype) && "Not a decltype specifier");
     416                 : 
     417               16:   SourceLocation StartLoc = ConsumeToken();
     418               16:   SourceLocation LParenLoc = Tok.getLocation();
     419                 : 
                        0: branch 1 not taken
                       16: branch 2 taken
     420               16:   if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
     421                 :                        "decltype")) {
     422                0:     SkipUntil(tok::r_paren);
     423                0:     return;
     424                 :   }
     425                 : 
     426                 :   // Parse the expression
     427                 : 
     428                 :   // C++0x [dcl.type.simple]p4:
     429                 :   //   The operand of the decltype specifier is an unevaluated operand.
     430                 :   EnterExpressionEvaluationContext Unevaluated(Actions,
     431               16:                                                Action::Unevaluated);
     432               16:   OwningExprResult Result = ParseExpression();
                        0: branch 1 not taken
                       16: branch 2 taken
     433               16:   if (Result.isInvalid()) {
     434                0:     SkipUntil(tok::r_paren);
     435                0:     return;
     436                 :   }
     437                 : 
     438                 :   // Match the ')'
     439               16:   SourceLocation RParenLoc;
                       16: branch 1 taken
                        0: branch 2 not taken
     440               16:   if (Tok.is(tok::r_paren))
     441               16:     RParenLoc = ConsumeParen();
     442                 :   else
     443                0:     MatchRHSPunctuation(tok::r_paren, LParenLoc);
     444                 : 
                        0: branch 1 not taken
                       16: branch 2 taken
     445               16:   if (RParenLoc.isInvalid())
     446                 :     return;
     447                 : 
     448               16:   const char *PrevSpec = 0;
     449                 :   unsigned DiagID;
     450                 :   // Check for duplicate type specifiers (e.g. "int decltype(a)").
                        0: branch 2 not taken
                       16: branch 3 taken
     451               16:   if (DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
     452                 :                          DiagID, Result.release()))
                       16: branch 4 taken
                        0: branch 5 not taken
                       16: branch 7 taken
                        0: branch 8 not taken
     453                0:     Diag(StartLoc, DiagID) << PrevSpec;
     454                 : }
     455                 : 
     456                 : /// ParseClassName - Parse a C++ class-name, which names a class. Note
     457                 : /// that we only check that the result names a type; semantic analysis
     458                 : /// will need to verify that the type names a class. The result is
     459                 : /// either a type or NULL, depending on whether a type name was
     460                 : /// found.
     461                 : ///
     462                 : ///       class-name: [C++ 9.1]
     463                 : ///         identifier
     464                 : ///         simple-template-id
     465                 : ///
     466                 : Parser::TypeResult Parser::ParseClassName(SourceLocation &EndLocation,
     467                 :                                           const CXXScopeSpec *SS,
     468              901:                                           bool DestrExpected) {
     469                 :   // Check whether we have a template-id that names a type.
                       81: branch 1 taken
                      820: branch 2 taken
     470              901:   if (Tok.is(tok::annot_template_id)) {
     471                 :     TemplateIdAnnotation *TemplateId
     472               81:       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
                        2: branch 0 taken
                       79: branch 1 taken
                        2: branch 2 taken
                        0: branch 3 not taken
     473               81:     if (TemplateId->Kind == TNK_Type_template ||
     474                 :         TemplateId->Kind == TNK_Dependent_template_name) {
     475               81:       AnnotateTemplateIdTokenAsType(SS);
     476                 : 
                       81: branch 1 taken
                        0: branch 2 not taken
     477               81:       assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
     478               81:       TypeTy *Type = Tok.getAnnotationValue();
     479               81:       EndLocation = Tok.getAnnotationEndLoc();
     480               81:       ConsumeToken();
     481                 : 
                       80: branch 0 taken
                        1: branch 1 taken
     482               81:       if (Type)
     483               80:         return Type;
     484                1:       return true;
     485                 :     }
     486                 : 
     487                 :     // Fall through to produce an error below.
     488                 :   }
     489                 : 
                        0: branch 1 not taken
                      820: branch 2 taken
     490              820:   if (Tok.isNot(tok::identifier)) {
     491                0:     Diag(Tok, diag::err_expected_class_name);
     492                0:     return true;
     493                 :   }
     494                 : 
     495              820:   IdentifierInfo *Id = Tok.getIdentifierInfo();
     496              820:   SourceLocation IdLoc = ConsumeToken();
     497                 : 
                        2: branch 1 taken
                      818: branch 2 taken
     498              820:   if (Tok.is(tok::less)) {
     499                 :     // It looks the user intended to write a template-id here, but the
     500                 :     // template-name was wrong. Try to fix that.
     501                2:     TemplateNameKind TNK = TNK_Type_template;
     502                2:     TemplateTy Template;
                        1: branch 1 taken
                        1: branch 2 taken
     503                2:     if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, CurScope,
     504                 :                                              SS, Template, TNK)) {
     505                 :       Diag(IdLoc, diag::err_unknown_template_name)
     506                1:         << Id;
     507                 :     }
     508                 :     
                        1: branch 1 taken
                        1: branch 2 taken
     509                2:     if (!Template)
     510                1:       return true;
     511                 : 
     512                 :     // Form the template name 
     513                1:     UnqualifiedId TemplateName;
     514                1:     TemplateName.setIdentifier(Id, IdLoc);
     515                 :     
     516                 :     // Parse the full template-id, then turn it into a type.
                        0: branch 2 not taken
                        1: branch 3 taken
     517                1:     if (AnnotateTemplateIdToken(Template, TNK, SS, TemplateName,
     518                 :                                 SourceLocation(), true))
     519                0:       return true;
                        1: branch 0 taken
                        0: branch 1 not taken
     520                1:     if (TNK == TNK_Dependent_template_name)
     521                1:       AnnotateTemplateIdTokenAsType(SS);
     522                 :     
     523                 :     // If we didn't end up with a typename token, there's nothing more we
     524                 :     // can do.
                        0: branch 1 not taken
                        1: branch 2 taken
     525                1:     if (Tok.isNot(tok::annot_typename))
     526                0:       return true;
     527                 :     
     528                 :     // Retrieve the type from the annotation token, consume that token, and
     529                 :     // return.
     530                1:     EndLocation = Tok.getAnnotationEndLoc();
     531                1:     TypeTy *Type = Tok.getAnnotationValue();
     532                1:     ConsumeToken();
     533                1:     return Type;
     534                 :   }
     535                 : 
     536                 :   // We have an identifier; check whether it is actually a type.
     537              818:   TypeTy *Type = Actions.getTypeName(*Id, IdLoc, CurScope, SS, true);
                        0: branch 0 not taken
                      818: branch 1 taken
     538              818:   if (!Type) {    
     539                 :     Diag(IdLoc, DestrExpected ? diag::err_destructor_class_name
                        0: branch 0 not taken
                        0: branch 1 not taken
     540                0:                             : diag::err_expected_class_name);
     541                0:     return true;
     542                 :   }
     543                 : 
     544                 :   // Consume the identifier.
     545              818:   EndLocation = IdLoc;
     546              818:   return Type;
     547                 : }
     548                 : 
     549                 : /// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
     550                 : /// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
     551                 : /// until we reach the start of a definition or see a token that
     552                 : /// cannot start a definition. If SuppressDeclarations is true, we do know.
     553                 : ///
     554                 : ///       class-specifier: [C++ class]
     555                 : ///         class-head '{' member-specification[opt] '}'
     556                 : ///         class-head '{' member-specification[opt] '}' attributes[opt]
     557                 : ///       class-head:
     558                 : ///         class-key identifier[opt] base-clause[opt]
     559                 : ///         class-key nested-name-specifier identifier base-clause[opt]
     560                 : ///         class-key nested-name-specifier[opt] simple-template-id
     561                 : ///                          base-clause[opt]
     562                 : /// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
     563                 : /// [GNU]   class-key attributes[opt] nested-name-specifier
     564                 : ///                          identifier base-clause[opt]
     565                 : /// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
     566                 : ///                          simple-template-id base-clause[opt]
     567                 : ///       class-key:
     568                 : ///         'class'
     569                 : ///         'struct'
     570                 : ///         'union'
     571                 : ///
     572                 : ///       elaborated-type-specifier: [C++ dcl.type.elab]
     573                 : ///         class-key ::[opt] nested-name-specifier[opt] identifier
     574                 : ///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
     575                 : ///                          simple-template-id
     576                 : ///
     577                 : ///  Note that the C++ class-specifier and elaborated-type-specifier,
     578                 : ///  together, subsume the C99 struct-or-union-specifier:
     579                 : ///
     580                 : ///       struct-or-union-specifier: [C99 6.7.2.1]
     581                 : ///         struct-or-union identifier[opt] '{' struct-contents '}'
     582                 : ///         struct-or-union identifier
     583                 : /// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
     584                 : ///                                                         '}' attributes[opt]
     585                 : /// [GNU]   struct-or-union attributes[opt] identifier
     586                 : ///       struct-or-union:
     587                 : ///         'struct'
     588                 : ///         'union'
     589                 : void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
     590                 :                                  SourceLocation StartLoc, DeclSpec &DS,
     591                 :                                  const ParsedTemplateInfo &TemplateInfo,
     592             7114:                                  AccessSpecifier AS, bool SuppressDeclarations){
     593                 :   DeclSpec::TST TagType;
                     5928: branch 0 taken
                     1186: branch 1 taken
     594             7114:   if (TagTokKind == tok::kw_struct)
     595             5928:     TagType = DeclSpec::TST_struct;
                      885: branch 0 taken
                      301: branch 1 taken
     596             1186:   else if (TagTokKind == tok::kw_class)
     597              885:     TagType = DeclSpec::TST_class;
     598                 :   else {
                        0: branch 0 not taken
                      301: branch 1 taken
     599              301:     assert(TagTokKind == tok::kw_union && "Not a class specifier");
     600              301:     TagType = DeclSpec::TST_union;
     601                 :   }
     602                 : 
                        3: branch 1 taken
                     7111: branch 2 taken
     603             7114:   if (Tok.is(tok::code_completion)) {
     604                 :     // Code completion for a struct, class, or union name.
     605                3:     Actions.CodeCompleteTag(CurScope, TagType);
     606                3:     ConsumeToken();
     607                 :   }
     608                 :   
     609             7114:   AttributeList *AttrList = 0;
     610                 :   // If attributes exist after tag, parse them.
                       18: branch 1 taken
                     7096: branch 2 taken
     611             7114:   if (Tok.is(tok::kw___attribute))
     612               18:     AttrList = ParseGNUAttributes();
     613                 : 
     614                 :   // If declspecs exist after tag, parse them.
                        0: branch 1 not taken
                     7114: branch 2 taken
     615             7114:   if (Tok.is(tok::kw___declspec))
     616                0:     AttrList = ParseMicrosoftDeclSpec(AttrList);
     617                 :   
     618                 :   // If C++0x attributes exist here, parse them.
     619                 :   // FIXME: Are we consistent with the ordering of parsing of different
     620                 :   // styles of attributes?
                        3: branch 1 taken
                     7111: branch 2 taken
     621             7114:   if (isCXX0XAttributeSpecifier())
     622                3:     AttrList = addAttributeLists(AttrList, ParseCXX0XAttributes().AttrList);
     623                 : 
                     5928: branch 0 taken
                     1186: branch 1 taken
                        1: branch 3 taken
                     5927: branch 4 taken
                        1: branch 5 taken
                     7113: branch 6 taken
     624             7114:   if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_pod)) {
     625                 :     // GNU libstdc++ 4.2 uses __is_pod as the name of a struct template, but
     626                 :     // __is_pod is a keyword in GCC >= 4.3. Therefore, when we see the
     627                 :     // token sequence "struct __is_pod", make __is_pod into a normal
     628                 :     // identifier rather than a keyword, to allow libstdc++ 4.2 to work
     629                 :     // properly.
     630                1:     Tok.getIdentifierInfo()->setTokenID(tok::identifier);
     631                1:     Tok.setKind(tok::identifier);
     632                 :   }
     633                 : 
                     5928: branch 0 taken
                     1186: branch 1 taken
                        0: branch 3 not taken
                     5928: branch 4 taken
                        0: branch 5 not taken
                     7114: branch 6 taken
     634             7114:   if (TagType == DeclSpec::TST_struct && Tok.is(tok::kw___is_empty)) {
     635                 :     // GNU libstdc++ 4.2 uses __is_empty as the name of a struct template, but
     636                 :     // __is_empty is a keyword in GCC >= 4.3. Therefore, when we see the
     637                 :     // token sequence "struct __is_empty", make __is_empty into a normal
     638                 :     // identifier rather than a keyword, to allow libstdc++ 4.2 to work
     639                 :     // properly.
     640                0:     Tok.getIdentifierInfo()->setTokenID(tok::identifier);
     641                0:     Tok.setKind(tok::identifier);
     642                 :   }
     643                 : 
     644                 :   // Parse the (optional) nested-name-specifier.
     645             7114:   CXXScopeSpec &SS = DS.getTypeSpecScope();
                     4181: branch 1 taken
                     2933: branch 2 taken
     646             7114:   if (getLang().CPlusPlus) {
     647                 :     // "FOO : BAR" is not a potential typo for "FOO::BAR".
     648             4181:     ColonProtectionRAIIObject X(*this);
     649                 :     
                      125: branch 1 taken
                     4056: branch 2 taken
     650             4181:     if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true))
                       54: branch 1 taken
                       71: branch 2 taken
                        0: branch 4 not taken
                       54: branch 5 taken
                        0: branch 6 not taken
                      125: branch 7 taken
     651              125:       if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id))
     652                0:         Diag(Tok, diag::err_expected_ident);
     653                 :   }
     654                 : 
     655             7114:   TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
     656                 : 
     657                 :   // Parse the (optional) class name or simple-template-id.
     658             7114:   IdentifierInfo *Name = 0;
     659             7114:   SourceLocation NameLoc;
     660             7114:   TemplateIdAnnotation *TemplateId = 0;
                     6113: branch 1 taken
                     1001: branch 2 taken
     661             7114:   if (Tok.is(tok::identifier)) {
     662             6113:     Name = Tok.getIdentifierInfo();
     663             6113:     NameLoc = ConsumeToken();
     664                 :     
                        3: branch 1 taken
                     6110: branch 2 taken
     665             6113:     if (Tok.is(tok::less)) {
     666                 :       // The name was supposed to refer to a template, but didn't. 
     667                 :       // Eat the template argument list and try to continue parsing this as
     668                 :       // a class (or template thereof).
     669                3:       TemplateArgList TemplateArgs;
     670                3:       SourceLocation LAngleLoc, RAngleLoc;
                        0: branch 2 not taken
                        3: branch 3 taken
     671                3:       if (ParseTemplateIdAfterTemplateName(TemplateTy(), NameLoc, &SS, 
     672                 :                                            true, LAngleLoc,
     673                 :                                            TemplateArgs, RAngleLoc)) {
     674                 :         // We couldn't parse the template argument list at all, so don't
     675                 :         // try to give any location information for the list.
     676                0:         LAngleLoc = RAngleLoc = SourceLocation();
     677                 :       }
     678                 :       
     679                 :       Diag(NameLoc, diag::err_explicit_spec_non_template)
     680                 :         << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
     681                 :         << (TagType == DeclSpec::TST_class? 0
     682                 :             : TagType == DeclSpec::TST_struct? 1
     683                 :             : 2)
     684                 :         << Name
                        1: branch 1 taken
                        2: branch 2 taken
                        1: branch 3 taken
                        0: branch 4 not taken
     685                3:         << SourceRange(LAngleLoc, RAngleLoc);
     686                 :       
     687                 :       // Strip off the last template parameter list if it was empty, since 
     688                 :       // we've removed its template argument list.
                        2: branch 0 taken
                        1: branch 1 taken
                        2: branch 2 taken
                        0: branch 3 not taken
     689                5:       if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
                        2: branch 0 taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        2: branch 4 taken
                        0: branch 5 not taken
                        2: branch 6 taken
     690                2:         if (TemplateParams && TemplateParams->size() > 1) {
     691                0:           TemplateParams->pop_back();
     692                 :         } else {
     693                2:           TemplateParams = 0;
     694                 :           const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
     695                2:             = ParsedTemplateInfo::NonTemplate;
     696                 :         }
                        1: branch 0 taken
                        0: branch 1 not taken
     697                1:       } else if (TemplateInfo.Kind
     698                 :                                 == ParsedTemplateInfo::ExplicitInstantiation) {
     699                 :         // Pretend this is just a forward declaration.
     700                1:         TemplateParams = 0;
     701                 :         const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind 
     702                1:           = ParsedTemplateInfo::NonTemplate;
     703                 :         const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc 
     704                1:           = SourceLocation();
     705                 :         const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
     706                1:           = SourceLocation();
     707                3:       }
     708                 :         
     709                 :       
     710                 :     }
                      441: branch 1 taken
                      560: branch 2 taken
     711             1001:   } else if (Tok.is(tok::annot_template_id)) {
     712              441:     TemplateId = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
     713              441:     NameLoc = ConsumeToken();
     714                 : 
                        1: branch 0 taken
                      440: branch 1 taken
     715              441:     if (TemplateId->Kind != TNK_Type_template) {
     716                 :       // The template-name in the simple-template-id refers to
     717                 :       // something other than a class template. Give an appropriate
     718                 :       // error message and skip to the ';'.
     719                1:       SourceRange Range(NameLoc);
                        0: branch 1 not taken
                        1: branch 2 taken
     720                1:       if (SS.isNotEmpty())
     721                0:         Range.setBegin(SS.getBeginLoc());
     722                 : 
     723                 :       Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
     724                1:         << Name << static_cast<int>(TemplateId->Kind) << Range;
     725                 : 
     726                1:       DS.SetTypeSpecError();
     727                1:       SkipUntil(tok::semi, false, true);
     728                1:       TemplateId->Destroy();
     729                1:       return;
     730                 :     }
     731                 :   }
     732                 : 
     733                 :   // There are four options here.  If we have 'struct foo;', then this
     734                 :   // is either a forward declaration or a friend declaration, which
     735                 :   // have to be treated differently.  If we have 'struct foo {...' or
     736                 :   // 'struct foo :...' then this is a definition. Otherwise we have
     737                 :   // something like 'struct foo xyz', a reference.
     738                 :   // However, in some contexts, things look like declarations but are just
     739                 :   // references, e.g.
     740                 :   // new struct s;
     741                 :   // or
     742                 :   // &T::operator struct s;
     743                 :   // For these, SuppressDeclarations is true.
     744                 :   Action::TagUseKind TUK;
                        3: branch 0 taken
                     7110: branch 1 taken
     745             7113:   if (SuppressDeclarations)
     746                3:     TUK = Action::TUK_Reference;
                     2991: branch 1 taken
                     4119: branch 2 taken
                     1474: branch 4 taken
                     1517: branch 5 taken
                      701: branch 7 taken
                      773: branch 8 taken
                     4820: branch 9 taken
                     2290: branch 10 taken
     747             7110:   else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
                        1: branch 1 taken
                     4819: branch 2 taken
     748             4820:     if (DS.isFriendSpecified()) {
     749                 :       // C++ [class.friend]p2:
     750                 :       //   A class shall not be defined in a friend declaration.
     751                 :       Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
     752                1:         << SourceRange(DS.getFriendSpecLoc());
     753                 : 
     754                 :       // Skip everything up to the semicolon, so that this looks like a proper
     755                 :       // friend class (or template thereof) declaration.
     756                1:       SkipUntil(tok::semi, true, true);
     757                1:       TUK = Action::TUK_Friend;
     758                 :     } else {
     759                 :       // Okay, this is a class definition.
     760             4819:       TUK = Action::TUK_Definition;
     761                 :     }
                      711: branch 1 taken
                     1579: branch 2 taken
     762             2290:   } else if (Tok.is(tok::semi))
                       42: branch 1 taken
                      669: branch 2 taken
     763              711:     TUK = DS.isFriendSpecified() ? Action::TUK_Friend : Action::TUK_Declaration;
     764                 :   else
     765             1579:     TUK = Action::TUK_Reference;
     766                 : 
                     1000: branch 0 taken
                     6113: branch 1 taken
                      560: branch 2 taken
                      440: branch 3 taken
                        5: branch 4 taken
                      555: branch 5 taken
     767             7113:   if (!Name && !TemplateId && TUK != Action::TUK_Definition) {
     768                 :     // We have a declaration or reference to an anonymous class.
     769                 :     Diag(StartLoc, diag::err_anon_type_definition)
     770                5:       << DeclSpec::getSpecifierName(TagType);
     771                 : 
     772                5:     SkipUntil(tok::comma, true);
     773                 : 
                        0: branch 0 not taken
                        5: branch 1 taken
     774                5:     if (TemplateId)
     775                0:       TemplateId->Destroy();
     776                5:     return;
     777                 :   }
     778                 : 
     779                 :   // Create the tag portion of the class or class template.
     780             7108:   Action::DeclResult TagOrTempResult = true; // invalid
     781             7108:   Action::TypeResult TypeResult = true; // invalid
     782                 : 
     783                 :   // FIXME: When TUK == TUK_Reference and we have a template-id, we need
     784                 :   // to turn that template-id into a type.
     785                 : 
     786             7108:   bool Owned = false;
                      440: branch 0 taken
                     6668: branch 1 taken
     787             7108:   if (TemplateId) {
     788                 :     // Explicit specialization, class template partial specialization,
     789                 :     // or explicit instantiation.
     790                 :     ASTTemplateArgsPtr TemplateArgsPtr(Actions,
     791                 :                                        TemplateId->getTemplateArgs(),
     792              440:                                        TemplateId->NumArgs);
                      235: branch 0 taken
                      205: branch 1 taken
                      234: branch 2 taken
                        1: branch 3 taken
     793              674:     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
     794                 :         TUK == Action::TUK_Declaration) {
     795                 :       // This is an explicit instantiation of a class template.
     796                 :       TagOrTempResult
     797                 :         = Actions.ActOnExplicitInstantiation(CurScope,
     798                 :                                              TemplateInfo.ExternLoc,
     799                 :                                              TemplateInfo.TemplateLoc,
     800                 :                                              TagType,
     801                 :                                              StartLoc,
     802                 :                                              SS,
     803                 :                                      TemplateTy::make(TemplateId->Template),
     804                 :                                              TemplateId->TemplateNameLoc,
     805                 :                                              TemplateId->LAngleLoc,
     806                 :                                              TemplateArgsPtr,
     807                 :                                              TemplateId->RAngleLoc,
     808              234:                                              AttrList);
                        8: branch 0 taken
                      198: branch 1 taken
     809              206:     } else if (TUK == Action::TUK_Reference) {
     810                 :       TypeResult
     811                 :         = Actions.ActOnTemplateIdType(TemplateTy::make(TemplateId->Template),
     812                 :                                       TemplateId->TemplateNameLoc,
     813                 :                                       TemplateId->LAngleLoc,
     814                 :                                       TemplateArgsPtr,
     815                8:                                       TemplateId->RAngleLoc);
     816                 : 
     817                 :       TypeResult = Actions.ActOnTagTemplateIdType(TypeResult, TUK,
     818                8:                                                   TagType, StartLoc);
     819                 :     } else {
     820                 :       // This is an explicit specialization or a class template
     821                 :       // partial specialization.
     822              198:       TemplateParameterLists FakedParamLists;
     823                 : 
                        1: branch 0 taken
                      197: branch 1 taken
     824              198:       if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
     825                 :         // This looks like an explicit instantiation, because we have
     826                 :         // something like
     827                 :         //
     828                 :         //   template class Foo<X>
     829                 :         //
     830                 :         // but it actually has a definition. Most likely, this was
     831                 :         // meant to be an explicit specialization, but the user forgot
     832                 :         // the '<>' after 'template'.
                        0: branch 0 not taken
                        1: branch 1 taken
     833                1:         assert(TUK == Action::TUK_Definition && "Expected a definition here");
     834                 : 
     835                 :         SourceLocation LAngleLoc
     836                1:           = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
     837                 :         Diag(TemplateId->TemplateNameLoc,
     838                 :              diag::err_explicit_instantiation_with_definition)
     839                 :           << SourceRange(TemplateInfo.TemplateLoc)
     840                1:           << CodeModificationHint::CreateInsertion(LAngleLoc, "<>");
     841                 : 
     842                 :         // Create a fake template parameter list that contains only
     843                 :         // "template<>", so that we treat this construct as a class
     844                 :         // template specialization.
     845                 :         FakedParamLists.push_back(
     846                 :           Actions.ActOnTemplateParameterList(0, SourceLocation(),
     847                 :                                              TemplateInfo.TemplateLoc,
     848                 :                                              LAngleLoc,
     849                 :                                              0, 0,
     850                1:                                              LAngleLoc));
     851                1:         TemplateParams = &FakedParamLists;
     852                 :       }
     853                 : 
     854                 :       // Build the class template specialization.
     855                 :       TagOrTempResult
     856                 :         = Actions.ActOnClassTemplateSpecialization(CurScope, TagType, TUK,
     857                 :                        StartLoc, SS,
     858                 :                        TemplateTy::make(TemplateId->Template),
     859                 :                        TemplateId->TemplateNameLoc,
     860                 :                        TemplateId->LAngleLoc,
     861                 :                        TemplateArgsPtr,
     862                 :                        TemplateId->RAngleLoc,
     863                 :                        AttrList,
     864                 :                        Action::MultiTemplateParamsArg(Actions,
     865                 :                                     TemplateParams? &(*TemplateParams)[0] : 0,
                      193: branch 0 taken
                        5: branch 1 taken
                      193: branch 3 taken
                        5: branch 4 taken
     866              198:                                  TemplateParams? TemplateParams->size() : 0));
     867                 :     }
     868              440:     TemplateId->Destroy();
                       15: branch 0 taken
                     6653: branch 1 taken
                       15: branch 2 taken
                        0: branch 3 not taken
     869             6683:   } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
     870                 :              TUK == Action::TUK_Declaration) {
     871                 :     // Explicit instantiation of a member of a class template
     872                 :     // specialization, e.g.,
     873                 :     //
     874                 :     //   template struct Outer<int>::Inner;
     875                 :     //
     876                 :     TagOrTempResult
     877                 :       = Actions.ActOnExplicitInstantiation(CurScope,
     878                 :                                            TemplateInfo.ExternLoc,
     879                 :                                            TemplateInfo.TemplateLoc,
     880                 :                                            TagType, StartLoc, SS, Name,
     881               15:                                            NameLoc, AttrList);
     882                 :   } else {
     883             6653:     if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
     884                 :         TUK == Action::TUK_Definition) {
     885                 :       // FIXME: Diagnose this particular error.
     886                 :     }
     887                 : 
     888             6653:     bool IsDependent = false;
     889                 : 
     890                 :     // Declaration or definition of a class type
     891                 :     TagOrTempResult = Actions.ActOnTag(CurScope, TagType, TUK, StartLoc, SS,
     892                 :                                        Name, NameLoc, AttrList, AS,
     893                 :                                   Action::MultiTemplateParamsArg(Actions,
     894                 :                                     TemplateParams? &(*TemplateParams)[0] : 0,
     895                 :                                     TemplateParams? TemplateParams->size() : 0),
                      993: branch 0 taken
                     5660: branch 1 taken
                      993: branch 3 taken
                     5660: branch 4 taken
     896             6653:                                        Owned, IsDependent);
     897                 : 
     898                 :     // If ActOnTag said the type was dependent, try again with the
     899                 :     // less common call.
                        3: branch 0 taken
                     6650: branch 1 taken
     900             6653:     if (IsDependent)
     901                 :       TypeResult = Actions.ActOnDependentTag(CurScope, TagType, TUK,
     902                3:                                              SS, Name, StartLoc, NameLoc);      
     903                 :   }
     904                 : 
     905                 :   // If there is a body, parse it and inform the actions module.
                     4819: branch 0 taken
                     2289: branch 1 taken
     906             7108:   if (TUK == Action::TUK_Definition) {
     907                 :     assert(Tok.is(tok::l_brace) ||
                      701: branch 1 taken
                     4118: branch 2 taken
                      701: branch 4 taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                      701: branch 8 taken
     908             4819:            (getLang().CPlusPlus && Tok.is(tok::colon)));
                     3403: branch 1 taken
                     1416: branch 2 taken
     909             4819:     if (getLang().CPlusPlus)
     910             3403:       ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
     911                 :     else
     912             1416:       ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
     913                 :   }
     914                 : 
     915                 :   void *Result;
                       11: branch 1 taken
                     7097: branch 2 taken
     916             7108:   if (!TypeResult.isInvalid()) {
     917               11:     TagType = DeclSpec::TST_typename;
     918               11:     Result = TypeResult.get();
     919               11:     Owned = false;
                     7080: branch 1 taken
                       17: branch 2 taken
     920             7097:   } else if (!TagOrTempResult.isInvalid()) {
     921             7080:     Result = TagOrTempResult.get().getAs<void>();
     922                 :   } else {
     923               17:     DS.SetTypeSpecError();
     924               17:     return;
     925                 :   }
     926                 : 
     927             7091:   const char *PrevSpec = 0;
     928                 :   unsigned DiagID;
     929                 : 
     930                 :   // FIXME: The DeclSpec should keep the locations of both the keyword and the
     931                 :   // name (if there is one).
                     6536: branch 1 taken
                      555: branch 2 taken
     932             7091:   SourceLocation TSTLoc = NameLoc.isValid()? NameLoc : StartLoc;
     933                 :   
                        0: branch 1 not taken
                     7091: branch 2 taken
     934             7091:   if (DS.SetTypeSpecType(TagType, TSTLoc, PrevSpec, DiagID,
     935                 :                          Result, Owned))
     936                0:     Diag(StartLoc, DiagID) << PrevSpec;
     937                 :   
     938                 :   // At this point, we've successfully parsed a class-specifier in 'definition'
     939                 :   // form (e.g. "struct foo { int x; }".  While we could just return here, we're
     940                 :   // going to look at what comes after it to improve error recovery.  If an
     941                 :   // impossible token occurs next, we assume that the programmer forgot a ; at
     942                 :   // the end of the declaration and recover that way.
     943                 :   //
     944                 :   // This switch enumerates the valid "follow" set for definition.
                     4811: branch 0 taken
                     2280: branch 1 taken
     945             7091:   if (TUK == Action::TUK_Definition) {
                     4806: branch 1 taken
                        1: branch 2 taken
                        4: branch 3 taken
     946             4811:     switch (Tok.getKind()) {
     947                 :     case tok::semi:               // struct foo {...} ;
     948                 :     case tok::star:               // struct foo {...} *         P;
     949                 :     case tok::amp:                // struct foo {...} &         R = ...
     950                 :     case tok::identifier:         // struct foo {...} V         ;
     951                 :     case tok::r_paren:            //(struct foo {...} )         {4}
     952                 :     case tok::annot_cxxscope:     // struct foo {...} a::       b;
     953                 :     case tok::annot_typename:     // struct foo {...} a         ::b;
     954                 :     case tok::annot_template_id:  // struct foo {...} a<int>    ::b;
     955                 :     case tok::l_paren:            // struct foo {...} (         x);
     956                 :     case tok::comma:              // __builtin_offsetof(struct foo{...} ,
     957                 :     // Storage-class specifiers
     958                 :     case tok::kw_static:          // struct foo {...} static    x;
     959                 :     case tok::kw_extern:          // struct foo {...} extern    x;
     960                 :     case tok::kw_typedef:         // struct foo {...} typedef   x;
     961                 :     case tok::kw_register:        // struct foo {...} register  x;
     962                 :     case tok::kw_auto:            // struct foo {...} auto      x;
     963                 :     // Type qualifiers
     964                 :     case tok::kw_const:           // struct foo {...} const     x;
     965                 :     case tok::kw_volatile:        // struct foo {...} volatile  x;
     966                 :     case tok::kw_restrict:        // struct foo {...} restrict  x;
     967                 :     case tok::kw_inline:          // struct foo {...} inline    foo() {};
     968             4806:       break;
     969                 :         
     970                 :     case tok::r_brace:  // struct bar { struct foo {...} } 
     971                 :       // Missing ';' at end of struct is accepted as an extension in C mode.
                        0: branch 1 not taken
                        1: branch 2 taken
     972                1:       if (!getLang().CPlusPlus) break;
     973                 :       // FALL THROUGH.
     974                 :     default:
     975                 :       ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
     976                 :                        TagType == DeclSpec::TST_class ? "class"
                        4: branch 0 taken
                        0: branch 1 not taken
                        4: branch 2 taken
                        0: branch 3 not taken
     977                4:                        : TagType == DeclSpec::TST_struct? "struct" : "union");
     978                 :       // Push this token back into the preprocessor and change our current token
     979                 :       // to ';' so that the rest of the code recovers as though there were an
     980                 :       // ';' after the definition.
     981                4:       PP.EnterToken(Tok);
     982                4:       Tok.setKind(tok::semi);  
     983                 :       break;
     984                 :     }
     985                 :   }
     986                 : }
     987                 : 
     988                 : /// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
     989                 : ///
     990                 : ///       base-clause : [C++ class.derived]
     991                 : ///         ':' base-specifier-list
     992                 : ///       base-specifier-list:
     993                 : ///         base-specifier '...'[opt]
     994                 : ///         base-specifier-list ',' base-specifier '...'[opt]
     995              701: void Parser::ParseBaseClause(DeclPtrTy ClassDecl) {
                      701: branch 1 taken
                        0: branch 2 not taken
     996              701:   assert(Tok.is(tok::colon) && "Not a base clause");
     997              701:   ConsumeToken();
     998                 : 
     999                 :   // Build up an array of parsed base specifiers.
    1000              701:   llvm::SmallVector<BaseTy *, 8> BaseInfo;
    1001                 : 
    1002              200:   while (true) {
    1003                 :     // Parse a base-specifier.
    1004              901:     BaseResult Result = ParseBaseSpecifier(ClassDecl);
                        9: branch 1 taken
                      892: branch 2 taken
    1005              901:     if (Result.isInvalid()) {
    1006                 :       // Skip the rest of this base specifier, up until the comma or
    1007                 :       // opening brace.
    1008                9:       SkipUntil(tok::comma, tok::l_brace, true, true);
    1009                 :     } else {
    1010                 :       // Add this to our array of base specifiers.
    1011              892:       BaseInfo.push_back(Result.get());
    1012                 :     }
    1013                 : 
    1014                 :     // If the next token is a comma, consume it and keep reading
    1015                 :     // base-specifiers.
                      200: branch 1 taken
                      701: branch 2 taken
    1016              901:     if (Tok.isNot(tok::comma)) break;
    1017                 : 
    1018                 :     // Consume the comma.
    1019              200:     ConsumeToken();
    1020                 :   }
    1021                 : 
    1022                 :   // Attach the base specifiers
    1023              701:   Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size());
    1024              701: }
    1025                 : 
    1026                 : /// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
    1027                 : /// one entry in the base class list of a class specifier, for example:
    1028                 : ///    class foo : public bar, virtual private baz {
    1029                 : /// 'public bar' and 'virtual private baz' are each base-specifiers.
    1030                 : ///
    1031                 : ///       base-specifier: [C++ class.derived]
    1032                 : ///         ::[opt] nested-name-specifier[opt] class-name
    1033                 : ///         'virtual' access-specifier[opt] ::[opt] nested-name-specifier[opt]
    1034                 : ///                        class-name
    1035                 : ///         access-specifier 'virtual'[opt] ::[opt] nested-name-specifier[opt]
    1036                 : ///                        class-name
    1037              901: Parser::BaseResult Parser::ParseBaseSpecifier(DeclPtrTy ClassDecl) {
    1038              901:   bool IsVirtual = false;
    1039              901:   SourceLocation StartLoc = Tok.getLocation();
    1040                 : 
    1041                 :   // Parse the 'virtual' keyword.
                      163: branch 1 taken
                      738: branch 2 taken
    1042              901:   if (Tok.is(tok::kw_virtual))  {
    1043              163:     ConsumeToken();
    1044              163:     IsVirtual = true;
    1045                 :   }
    1046                 : 
    1047                 :   // Parse an (optional) access specifier.
    1048              901:   AccessSpecifier Access = getAccessSpecifierIfPresent();
                      294: branch 0 taken
                      607: branch 1 taken
    1049              901:   if (Access != AS_none)
    1050              294:     ConsumeToken();
    1051                 : 
    1052                 :   // Parse the 'virtual' keyword (again!), in case it came after the
    1053                 :   // access specifier.
                       36: branch 1 taken
                      865: branch 2 taken
    1054              901:   if (Tok.is(tok::kw_virtual))  {
    1055               36:     SourceLocation VirtualLoc = ConsumeToken();
                        2: branch 0 taken
                       34: branch 1 taken
    1056               36:     if (IsVirtual) {
    1057                 :       // Complain about duplicate 'virtual'
    1058                 :       Diag(VirtualLoc, diag::err_dup_virtual)
    1059                2:         << CodeModificationHint::CreateRemoval(VirtualLoc);
    1060                 :     }
    1061                 : 
    1062               36:     IsVirtual = true;
    1063                 :   }
    1064                 : 
    1065                 :   // Parse optional '::' and optional nested-name-specifier.
    1066              901:   CXXScopeSpec SS;
    1067              901:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, true);
    1068                 : 
    1069                 :   // The location of the base class itself.
    1070              901:   SourceLocation BaseLoc = Tok.getLocation();
    1071                 : 
    1072                 :   // Parse the class-name.
    1073              901:   SourceLocation EndLocation;
    1074              901:   TypeResult BaseType = ParseClassName(EndLocation, &SS);
                        2: branch 1 taken
                      899: branch 2 taken
    1075              901:   if (BaseType.isInvalid())
    1076                2:     return true;
    1077                 : 
    1078                 :   // Find the complete source range for the base-specifier.
    1079              899:   SourceRange Range(StartLoc, EndLocation);
    1080                 : 
    1081                 :   // Notify semantic analysis that we have parsed a complete
    1082                 :   // base-specifier.
    1083                 :   return Actions.ActOnBaseSpecifier(ClassDecl, Range, IsVirtual, Access,
    1084              899:                                     BaseType.get(), BaseLoc);
    1085                 : }
    1086                 : 
    1087                 : /// getAccessSpecifierIfPresent - Determine whether the next token is
    1088                 : /// a C++ access-specifier.
    1089                 : ///
    1090                 : ///       access-specifier: [C++ class.derived]
    1091                 : ///         'private'
    1092                 : ///         'protected'
    1093                 : ///         'public'
    1094             6133: AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
                     5617: branch 1 taken
                       41: branch 2 taken
                       23: branch 3 taken
                      452: branch 4 taken
    1095             6133:   switch (Tok.getKind()) {
    1096             5617:   default: return AS_none;
    1097               41:   case tok::kw_private: return AS_private;
    1098               23:   case tok::kw_protected: return AS_protected;
    1099              452:   case tok::kw_public: return AS_public;
    1100                 :   }
    1101                 : }
    1102                 : 
    1103                 : void Parser::HandleMemberFunctionDefaultArgs(Declarator& DeclaratorInfo,
    1104             2736:                                              DeclPtrTy ThisDecl) {
    1105                 :   // We just declared a member function. If this member function
    1106                 :   // has any default arguments, we'll need to parse them later.
    1107             2736:   LateParsedMethodDeclaration *LateMethod = 0;
    1108                 :   DeclaratorChunk::FunctionTypeInfo &FTI
    1109             2736:     = DeclaratorInfo.getTypeObject(0).Fun;
                     1201: branch 0 taken
                     2736: branch 1 taken
    1110             3937:   for (unsigned ParamIdx = 0; ParamIdx < FTI.NumArgs; ++ParamIdx) {
                     1187: branch 0 taken
                       14: branch 1 taken
                       68: branch 2 taken
                     1119: branch 3 taken
    1111             1201:     if (LateMethod || FTI.ArgInfo[ParamIdx].DefaultArgTokens) {
                       68: branch 0 taken
                       14: branch 1 taken
    1112               82:       if (!LateMethod) {
    1113                 :         // Push this method onto the stack of late-parsed method
    1114                 :         // declarations.
    1115                 :         getCurrentClass().MethodDecls.push_back(
    1116               68:                                 LateParsedMethodDeclaration(ThisDecl));
    1117               68:         LateMethod = &getCurrentClass().MethodDecls.back();
    1118               68:         LateMethod->TemplateScope = CurScope->isTemplateParamScope();
    1119                 : 
    1120                 :         // Add all of the parameters prior to this one (they don't
    1121                 :         // have default arguments).
    1122               68:         LateMethod->DefaultArgs.reserve(FTI.NumArgs);
                       25: branch 0 taken
                       68: branch 1 taken
    1123               93:         for (unsigned I = 0; I < ParamIdx; ++I)
    1124                 :           LateMethod->DefaultArgs.push_back(
    1125               25:                     LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param));
    1126                 :       }
    1127                 : 
    1128                 :       // Add this parameter to the list of parameters (it or may
    1129                 :       // not have a default argument).
    1130                 :       LateMethod->DefaultArgs.push_back(
    1131                 :         LateParsedDefaultArgument(FTI.ArgInfo[ParamIdx].Param,
    1132               82:                                   FTI.ArgInfo[ParamIdx].DefaultArgTokens));
    1133                 :     }
    1134                 :   }
    1135             2736: }
    1136                 : 
    1137                 : /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
    1138                 : ///
    1139                 : ///       member-declaration:
    1140                 : ///         decl-specifier-seq[opt] member-declarator-list[opt] ';'
    1141                 : ///         function-definition ';'[opt]
    1142                 : ///         ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]
    1143                 : ///         using-declaration                                            [TODO]
    1144                 : /// [C++0x] static_assert-declaration
    1145                 : ///         template-declaration
    1146                 : /// [GNU]   '__extension__' member-declaration
    1147                 : ///
    1148                 : ///       member-declarator-list:
    1149                 : ///         member-declarator
    1150                 : ///         member-declarator-list ',' member-declarator
    1151                 : ///
    1152                 : ///       member-declarator:
    1153                 : ///         declarator pure-specifier[opt]
    1154                 : ///         declarator constant-initializer[opt]
    1155                 : ///         identifier[opt] ':' constant-expression
    1156                 : ///
    1157                 : ///       pure-specifier:
    1158                 : ///         '= 0'
    1159                 : ///
    1160                 : ///       constant-initializer:
    1161                 : ///         '=' constant-expression
    1162                 : ///
    1163                 : void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
    1164             5222:                                        const ParsedTemplateInfo &TemplateInfo) {
    1165                 :   // Access declarations.
                     5021: branch 0 taken
                      201: branch 1 taken
                     4065: branch 3 taken
                      956: branch 4 taken
                        0: branch 6 not taken
                     4065: branch 7 taken
                       45: branch 9 taken
                      911: branch 10 taken
                        2: branch 12 taken
                       43: branch 13 taken
                        2: branch 14 taken
                     5220: branch 15 taken
    1166             5222:   if (!TemplateInfo.Kind &&
    1167                 :       (Tok.is(tok::identifier) || Tok.is(tok::coloncolon)) &&
    1168                 :       TryAnnotateCXXScopeToken() &&
    1169                 :       Tok.is(tok::annot_cxxscope)) {
    1170                2:     bool isAccessDecl = false;
                        2: branch 2 taken
                        0: branch 3 not taken
    1171                2:     if (NextToken().is(tok::identifier))
    1172                2:       isAccessDecl = GetLookAheadToken(2).is(tok::semi);
    1173                 :     else
    1174                0:       isAccessDecl = NextToken().is(tok::kw_operator);
    1175                 : 
                        1: branch 0 taken
                        1: branch 1 taken
    1176                2:     if (isAccessDecl) {
    1177                 :       // Collect the scope specifier token we annotated earlier.
    1178                1:       CXXScopeSpec SS;
    1179                1:       ParseOptionalCXXScopeSpecifier(SS, /*ObjectType*/ 0, false);
    1180                 : 
    1181                 :       // Try to parse an unqualified-id.
    1182                1:       UnqualifiedId Name;
                        0: branch 1 not taken
                        1: branch 2 taken
    1183                1:       if (ParseUnqualifiedId(SS, false, true, true, /*ObjectType*/ 0, Name)) {
    1184                0:         SkipUntil(tok::semi);
    1185                 :         return;
    1186                 :       }
    1187                 : 
    1188                 :       // TODO: recover from mistakenly-qualified operator declarations.
                        1: branch 1 taken
                        0: branch 2 not taken
    1189                1:       if (ExpectAndConsume(tok::semi,
    1190                 :                            diag::err_expected_semi_after,
    1191                 :                            "access declaration",
    1192                 :                            tok::semi))
    1193                 :         return;
    1194                 : 
    1195                 :       Actions.ActOnUsingDeclaration(CurScope, AS,
    1196                 :                                     false, SourceLocation(),
    1197                 :                                     SS, Name,
    1198                 :                                     /* AttrList */ 0,
    1199                 :                                     /* IsTypeName */ false,
    1200                1:                                     SourceLocation());
    1201                1:       return;
    1202                 :     }
    1203                 :   }
    1204                 : 
    1205                 :   // static_assert-declaration
                        3: branch 1 taken
                     5218: branch 2 taken
    1206             5221:   if (Tok.is(tok::kw_static_assert)) {
    1207                 :     // FIXME: Check for templates
    1208                3:     SourceLocation DeclEnd;
    1209                3:     ParseStaticAssertDeclaration(DeclEnd);
    1210                3:     return;
    1211                 :   }
    1212                 : 
                      201: branch 1 taken
                     5017: branch 2 taken
    1213             5218:   if (Tok.is(tok::kw_template)) {
    1214                 :     assert(!TemplateInfo.TemplateParams &&
                        0: branch 0 not taken
                      201: branch 1 taken
    1215              201:            "Nested template improperly parsed?");
    1216              201:     SourceLocation DeclEnd;
    1217                 :     ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd,
    1218              201:                                          AS);
    1219              201:     return;
    1220                 :   }
    1221                 : 
    1222                 :   // Handle:  member-declaration ::= '__extension__' member-declaration
                       11: branch 1 taken
                     5006: branch 2 taken
    1223             5017:   if (Tok.is(tok::kw___extension__)) {
    1224                 :     // __extension__ silences extension warnings in the subexpression.
    1225               11:     ExtensionRAIIObject O(Diags);  // Use RAII to do this.
    1226               11:     ConsumeToken();
    1227               11:     return ParseCXXClassMemberDeclaration(AS, TemplateInfo);
    1228                 :   }
    1229                 : 
    1230                 :   // Don't parse FOO:BAR as if it were a typo for FOO::BAR, in this context it
    1231                 :   // is a bitfield.
    1232             5006:   ColonProtectionRAIIObject X(*this);
    1233                 :   
    1234             5006:   CXX0XAttributeList AttrList;
    1235                 :   // Optional C++0x attribute-specifier
                      980: branch 1 taken
                     4026: branch 2 taken
                        0: branch 4 not taken
                      980: branch 5 taken
                        0: branch 6 not taken
                     5006: branch 7 taken
    1236             5006:   if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier())
    1237                0:     AttrList = ParseCXX0XAttributes();
    1238                 : 
                       75: branch 1 taken
                     4931: branch 2 taken
    1239             5006:   if (Tok.is(tok::kw_using)) {
    1240                 :     // FIXME: Check for template aliases
    1241                 :     
                        0: branch 0 not taken
                       75: branch 1 taken
    1242               75:     if (AttrList.HasAttr)
    1243                 :       Diag(AttrList.Range.getBegin(), diag::err_attributes_not_allowed)
    1244                0:         << AttrList.Range;
    1245                 : 
    1246                 :     // Eat 'using'.
    1247               75:     SourceLocation UsingLoc = ConsumeToken();
    1248                 : 
                        3: branch 1 taken
                       72: branch 2 taken
    1249               75:     if (Tok.is(tok::kw_namespace)) {
    1250                3:       Diag(UsingLoc, diag::err_using_namespace_in_class);
    1251                3:       SkipUntil(tok::semi, true, true);
    1252                 :     } else {
    1253               72:       SourceLocation DeclEnd;
    1254                 :       // Otherwise, it must be using-declaration.
    1255               72:       ParseUsingDeclaration(Declarator::MemberContext, UsingLoc, DeclEnd, AS);
    1256                 :     }
    1257             1438:     return;
    1258                 :   }
    1259                 : 
    1260             4931:   SourceLocation DSStart = Tok.getLocation();
    1261                 :   // decl-specifier-seq:
    1262                 :   // Parse the common declaration-specifiers piece.
    1263             4931:   ParsingDeclSpec DS(*this);
    1264             4931:   DS.AddAttributes(AttrList.AttrList);
    1265             4931:   ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class);
    1266                 : 
    1267                 :   Action::MultiTemplateParamsArg TemplateParams(Actions,
    1268                 :       TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() : 0,
                      201: branch 0 taken
                     4730: branch 1 taken
                      201: branch 3 taken
                     4730: branch 4 taken
    1269             4931:       TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);
    1270                 : 
                      308: branch 1 taken
                     4623: branch 2 taken
    1271             4931:   if (Tok.is(tok::semi)) {
    1272              308:     ConsumeToken();
    1273              308:     Actions.ParsedFreeStandingDeclSpec(CurScope, DS);
    1274                 :     return;
    1275                 :   }
    1276                 : 
    1277             4623:   ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
    1278                 : 
                     4615: branch 1 taken
                        8: branch 2 taken
    1279             4623:   if (Tok.isNot(tok::colon)) {
    1280                 :     // Don't parse FOO:BAR as if it were a typo for FOO::BAR.
    1281             4615:     ColonProtectionRAIIObject X(*this);
    1282                 : 
    1283                 :     // Parse the first declarator.
    1284             4615:     ParseDeclarator(DeclaratorInfo);
    1285                 :     // Error parsing the declarator?
                        2: branch 1 taken
                     4613: branch 2 taken
    1286             4615:     if (!DeclaratorInfo.hasName()) {
    1287                 :       // If so, skip until the semi-colon or a }.
    1288                2:       SkipUntil(tok::r_brace, true);
                        1: branch 1 taken
                        1: branch 2 taken
    1289                2:       if (Tok.is(tok::semi))
    1290                1:         ConsumeToken();
    1291                 :       return;
    1292                 :     }
    1293                 : 
    1294                 :     // If attributes exist after the declarator, but before an '{', parse them.
                       21: branch 1 taken
                     4592: branch 2 taken
    1295             4613:     if (Tok.is(tok::kw___attribute)) {
    1296               21:       SourceLocation Loc;
    1297               21:       AttributeList *AttrList = ParseGNUAttributes(&Loc);
    1298               21:       DeclaratorInfo.AddAttributes(AttrList, Loc);
    1299                 :     }
    1300                 : 
    1301                 :     // function-definition:
                     3724: branch 1 taken
                      889: branch 2 taken
                     1846: branch 4 taken
                     1878: branch 5 taken
                     1687: branch 7 taken
                      159: branch 8 taken
                        3: branch 10 taken
                     1684: branch 11 taken
                     1051: branch 12 taken
                     3562: branch 13 taken
    1302             4613:     if (Tok.is(tok::l_brace)
    1303                 :         || (DeclaratorInfo.isFunctionDeclarator() &&
    1304                 :             (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) {
                        0: branch 1 not taken
                     1051: branch 2 taken
    1305             1051:       if (!DeclaratorInfo.isFunctionDeclarator()) {
    1306                0:         Diag(Tok, diag::err_func_def_no_params);
    1307                0:         ConsumeBrace();
    1308                0:         SkipUntil(tok::r_brace, true);
    1309                 :         return;
    1310                 :       }
    1311                 : 
                        0: branch 1 not taken
                     1051: branch 2 taken
    1312             1051:       if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
    1313                0:         Diag(Tok, diag::err_function_declared_typedef);
    1314                 :         // This recovery skips the entire function body. It would be nice
    1315                 :         // to simply call ParseCXXInlineMethodDef() below, however Sema
    1316                 :         // assumes the declarator represents a function, not a typedef.
    1317                0:         ConsumeBrace();
    1318                0:         SkipUntil(tok::r_brace, true);
    1319                 :         return;
    1320                 :       }
    1321                 : 
    1322             1051:       ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo);
    1323                 :       return;
                     3562: branch 1 taken
                     1053: branch 2 taken
    1324             4615:     }
    1325                 :   }
    1326                 : 
    1327                 :   // member-declarator-list:
    1328                 :   //   member-declarator
    1329                 :   //   member-declarator-list ',' member-declarator
    1330                 : 
    1331             3570:   llvm::SmallVector<DeclPtrTy, 8> DeclsInGroup;
    1332             3570:   OwningExprResult BitfieldSize(Actions);
    1333             3570:   OwningExprResult Init(Actions);
    1334             3570:   bool Deleted = false;
    1335                 : 
    1336               61:   while (1) {
    1337                 :     // member-declarator:
    1338                 :     //   declarator pure-specifier[opt]
    1339                 :     //   declarator constant-initializer[opt]
    1340                 :     //   identifier[opt] ':' constant-expression
    1341                 : 
                       65: branch 1 taken
                     3566: branch 2 taken
    1342             3631:     if (Tok.is(tok::colon)) {
    1343               65:       ConsumeToken();
    1344               65:       BitfieldSize = ParseConstantExpression();
                        0: branch 1 not taken
                       65: branch 2 taken
    1345               65:       if (BitfieldSize.isInvalid())
    1346                0:         SkipUntil(tok::comma, true, true);
    1347                 :     }
    1348                 : 
    1349                 :     // pure-specifier:
    1350                 :     //   '= 0'
    1351                 :     //
    1352                 :     // constant-initializer:
    1353                 :     //   '=' constant-expression
    1354                 :     //
    1355                 :     // defaulted/deleted function-definition:
    1356                 :     //   '=' 'default'                          [TODO]
    1357                 :     //   '=' 'delete'
    1358                 : 
                      166: branch 1 taken
                     3465: branch 2 taken
    1359             3631:     if (Tok.is(tok::equal)) {
    1360              166:       ConsumeToken();
                       34: branch 1 taken
                      132: branch 2 taken
                        8: branch 4 taken
                       26: branch 5 taken
                        8: branch 6 taken
                      158: branch 7 taken
    1361              166:       if (getLang().CPlusPlus0x && Tok.is(tok::kw_delete)) {
    1362                8:         ConsumeToken();
    1363                8:         Deleted = true;
    1364                 :       } else {
    1365              158:         Init = ParseInitializer();
                        1: branch 1 taken
                      157: branch 2 taken
    1366              158:         if (Init.isInvalid())
    1367                1:           SkipUntil(tok::comma, true, true);
    1368                 :       }
    1369                 :     }
    1370                 : 
    1371                 :     // If attributes exist after the declarator, parse them.
                        0: branch 1 not taken
                     3631: branch 2 taken
    1372             3631:     if (Tok.is(tok::kw___attribute)) {
    1373                0:       SourceLocation Loc;
    1374                0:       AttributeList *AttrList = ParseGNUAttributes(&Loc);
    1375                0:       DeclaratorInfo.AddAttributes(AttrList, Loc);
    1376                 :     }
    1377                 : 
    1378                 :     // NOTE: If Sema is the Action module and declarator is an instance field,
    1379                 :     // this call will *not* return the created decl; It will return null.
    1380                 :     // See Sema::ActOnCXXMemberDeclarator for details.
    1381                 : 
    1382             3631:     DeclPtrTy ThisDecl;
                       38: branch 1 taken
                     3593: branch 2 taken
    1383             3631:     if (DS.isFriendSpecified()) {
    1384                 :       // TODO: handle initializers, bitfields, 'delete'
    1385                 :       ThisDecl = Actions.ActOnFriendFunctionDecl(CurScope, DeclaratorInfo,
    1386                 :                                                  /*IsDefinition*/ false,
    1387               38:                                                  move(TemplateParams));
    1388                 :     } else {
    1389                 :       ThisDecl = Actions.ActOnCXXMemberDeclarator(CurScope, AS,
    1390                 :                                                   DeclaratorInfo,
    1391                 :                                                   move(TemplateParams),
    1392                 :                                                   BitfieldSize.release(),
    1393                 :                                                   Init.release(),
    1394                 :                                                   /*IsDefinition*/Deleted,
    1395             3593:                                                   Deleted);
    1396                 :     }
                     2072: branch 1 taken
                     1559: branch 2 taken
    1397             3631:     if (ThisDecl)
    1398             2072:       DeclsInGroup.push_back(ThisDecl);
    1399                 : 
                     1687: branch 1 taken
                     1944: branch 2 taken
                     1685: branch 5 taken
                        2: branch 6 taken
                     1685: branch 7 taken
                     1946: branch 8 taken
    1400             3631:     if (DeclaratorInfo.isFunctionDeclarator() &&
    1401                 :         DeclaratorInfo.getDeclSpec().getStorageClassSpec()
    1402                 :           != DeclSpec::SCS_typedef) {
    1403             1685:       HandleMemberFunctionDefaultArgs(DeclaratorInfo, ThisDecl);
    1404                 :     }
    1405                 : 
    1406             3631:     DeclaratorInfo.complete(ThisDecl);
    1407                 : 
    1408                 :     // If we don't have a comma, it is either the end of the list (a ';')
    1409                 :     // or an error, bail out.
                       61: branch 1 taken
                     3570: branch 2 taken
    1410             3631:     if (Tok.isNot(tok::comma))
    1411             3570:       break;
    1412                 : 
    1413                 :     // Consume the comma.
    1414               61:     ConsumeToken();
    1415                 : 
    1416                 :     // Parse the next declarator.
    1417               61:     DeclaratorInfo.clear();
    1418               61:     BitfieldSize = 0;
    1419               61:     Init = 0;
    1420               61:     Deleted = false;
    1421                 : 
    1422                 :     // Attributes are only allowed on the second declarator.
                        0: branch 1 not taken
                       61: branch 2 taken
    1423               61:     if (Tok.is(tok::kw___attribute)) {
    1424                0:       SourceLocation Loc;
    1425                0:       AttributeList *AttrList = ParseGNUAttributes(&Loc);
    1426                0:       DeclaratorInfo.AddAttributes(AttrList, Loc);
    1427                 :     }
    1428                 : 
                       59: branch 1 taken
                        2: branch 2 taken
    1429               61:     if (Tok.isNot(tok::colon))
    1430               59:       ParseDeclarator(DeclaratorInfo);
    1431                 :   }
    1432                 : 
                        2: branch 1 taken
                     3568: branch 2 taken
    1433             3570:   if (ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
    1434                 :     // Skip to end of block or statement.
    1435                2:     SkipUntil(tok::r_brace, true, true);
    1436                 :     // If we stopped at a ';', eat it.
                        1: branch 1 taken
                        1: branch 2 taken
    1437                2:     if (Tok.is(tok::semi)) ConsumeToken();
    1438                 :     return;
    1439                 :   }
    1440                 : 
    1441                 :   Actions.FinalizeDeclaratorGroup(CurScope, DS, DeclsInGroup.data(),
                     3568: branch 4 taken
                        2: branch 5 taken
                     3568: branch 7 taken
                        2: branch 8 taken
                     3568: branch 10 taken
                        2: branch 11 taken
                     3568: branch 13 taken
                     1055: branch 14 taken
                     3568: branch 16 taken
                     1363: branch 17 taken
                     3568: branch 19 taken
                     1438: branch 20 taken
    1442             3568:                                   DeclsInGroup.size());
    1443                 : }
    1444                 : 
    1445                 : /// ParseCXXMemberSpecification - Parse the class definition.
    1446                 : ///
    1447                 : ///       member-specification:
    1448                 : ///         member-declaration member-specification[opt]
    1449                 : ///         access-specifier ':' member-specification[opt]
    1450                 : ///
    1451                 : void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
    1452             3403:                                          unsigned TagType, DeclPtrTy TagDecl) {
    1453                 :   assert((TagType == DeclSpec::TST_struct ||
    1454                 :          TagType == DeclSpec::TST_union  ||
                      773: branch 0 taken
                     2630: branch 1 taken
                      689: branch 2 taken
                       84: branch 3 taken
                        0: branch 4 not taken
                      689: branch 5 taken
    1455             3403:          TagType == DeclSpec::TST_class) && "Invalid TagType!");
    1456                 : 
    1457                 :   PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
    1458                 :                                         PP.getSourceManager(),
    1459             3403:                                         "parsing struct/union/class body");
    1460                 : 
    1461                 :   // Determine whether this is a non-nested class. Note that local
    1462                 :   // classes are *not* considered to be nested classes.
    1463             3403:   bool NonNestedClass = true;
                      228: branch 1 taken
                     3175: branch 2 taken
    1464             3403:   if (!ClassStack.empty()) {
                      282: branch 1 taken
                        0: branch 2 not taken
    1465              282:     for (const Scope *S = CurScope; S; S = S->getParent()) {
                      220: branch 1 taken
                       62: branch 2 taken
    1466              282:       if (S->isClassScope()) {
    1467                 :         // We're inside a class scope, so this is a nested class.
    1468              220:         NonNestedClass = false;
    1469              220:         break;
    1470                 :       }
    1471                 : 
                        8: branch 1 taken
                       54: branch 2 taken
    1472               62:       if ((S->getFlags() & Scope::FnScope)) {
    1473                 :         // If we're in a function or function template declared in the
    1474                 :         // body of a class, then this is a local class rather than a
    1475                 :         // nested class.
    1476                8:         const Scope *Parent = S->getParent();
                        1: branch 1 taken
                        7: branch 2 taken
    1477                8:         if (Parent->isTemplateParamScope())
    1478                1:           Parent = Parent->getParent();
                        8: branch 1 taken
                        0: branch 2 not taken
    1479                8:         if (Parent->isClassScope())
    1480                8:           break;
    1481                 :       }
    1482                 :     }
    1483                 :   }
    1484                 : 
    1485                 :   // Enter a scope for the class.
    1486             3403:   ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
    1487                 : 
    1488                 :   // Note that we are parsing a new (potentially-nested) class definition.
    1489             3403:   ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass);
    1490                 : 
                     3394: branch 1 taken
                        9: branch 2 taken
    1491             3403:   if (TagDecl)
    1492             3394:     Actions.ActOnTagStartDefinition(CurScope, TagDecl);
    1493                 : 
                      701: branch 1 taken
                     2702: branch 2 taken
    1494             3403:   if (Tok.is(tok::colon)) {
    1495              701:     ParseBaseClause(TagDecl);
    1496                 : 
                        0: branch 1 not taken
                      701: branch 2 taken
    1497              701:     if (!Tok.is(tok::l_brace)) {
    1498                0:       Diag(Tok, diag::err_expected_lbrace_after_base_specifiers);
    1499                9:       return;
    1500                 :     }
    1501                 :   }
    1502                 : 
                        0: branch 1 not taken
                     3403: branch 2 taken
    1503             3403:   assert(Tok.is(tok::l_brace));
    1504                 : 
    1505             3403:   SourceLocation LBraceLoc = ConsumeBrace();
    1506                 : 
                        9: branch 1 taken
                     3394: branch 2 taken
    1507             3403:   if (!TagDecl) {
    1508                9:     SkipUntil(tok::r_brace, false, false);
    1509                 :     return;
    1510                 :   }
    1511                 : 
    1512             3394:   Actions.ActOnStartCXXMemberDeclarations(CurScope, TagDecl, LBraceLoc);
    1513                 : 
    1514                 :   // C++ 11p3: Members of a class defined with the keyword class are private
    1515                 :   // by default. Members of a class defined with the keywords struct or union
    1516                 :   // are public by default.
    1517                 :   AccessSpecifier CurAS;
                      686: branch 0 taken
                     2708: branch 1 taken
    1518             3394:   if (TagType == DeclSpec::TST_class)
    1519              686:     CurAS = AS_private;
    1520                 :   else
    1521             2708:     CurAS = AS_public;
    1522                 : 
    1523                 :   // While we still have something to read, read the member-declarations.
                     5251: branch 1 taken
                     3393: branch 2 taken
                     5250: branch 4 taken
                        1: branch 5 taken
                     5250: branch 6 taken
                     3394: branch 7 taken
    1524            12038:   while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {
    1525                 :     // Each iteration of this loop reads one member-declaration.
    1526                 : 
    1527                 :     // Check for extraneous top-level semicolon.
                       18: branch 1 taken
                     5232: branch 2 taken
    1528             5250:     if (Tok.is(tok::semi)) {
    1529                 :       Diag(Tok, diag::ext_extra_struct_semi)
    1530               18:         << CodeModificationHint::CreateRemoval(Tok.getLocation());
    1531               18:       ConsumeToken();
    1532               18:       continue;
    1533                 :     }
    1534                 : 
    1535             5232:     AccessSpecifier AS = getAccessSpecifierIfPresent();
                      222: branch 0 taken
                     5010: branch 1 taken
    1536             5232:     if (AS != AS_none) {
    1537                 :       // Current token is a C++ access specifier.
    1538              222:       CurAS = AS;
    1539              222:       ConsumeToken();
    1540              222:       ExpectAndConsume(tok::colon, diag::err_expected_colon);
    1541              222:       continue;
    1542                 :     }
    1543                 : 
    1544                 :     // FIXME: Make sure we don't have a template here.
    1545                 : 
    1546                 :     // Parse all the comma separated declarators.
    1547             5010:     ParseCXXClassMemberDeclaration(CurAS);
    1548                 :   }
    1549                 : 
    1550             3394:   SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBraceLoc);
    1551                 : 
    1552             3394:   AttributeList *AttrList = 0;
    1553                 :   // If attributes exist after class contents, parse them.
                        0: branch 1 not taken
                     3394: branch 2 taken
    1554             3394:   if (Tok.is(tok::kw___attribute))
    1555                0:     AttrList = ParseGNUAttributes(); // FIXME: where should I put them?
    1556                 : 
    1557                 :   Actions.ActOnFinishCXXMemberSpecification(CurScope, RecordLoc, TagDecl,
    1558             3394:                                             LBraceLoc, RBraceLoc);
    1559                 : 
    1560                 :   // C++ 9.2p2: Within the class member-specification, the class is regarded as
    1561                 :   // complete within function bodies, default arguments,
    1562                 :   // exception-specifications, and constructor ctor-initializers (including
    1563                 :   // such things in nested classes).
    1564                 :   //
    1565                 :   // FIXME: Only function bodies and constructor ctor-initializers are
    1566                 :   // parsed correctly, fix the rest.
                     3174: branch 0 taken
                      220: branch 1 taken
    1567             3394:   if (NonNestedClass) {
    1568                 :     // We are not inside a nested class. This class and its nested classes
    1569                 :     // are complete and we can parse the delayed portions of method
    1570                 :     // declarations and the lexed inline method definitions.
    1571             3174:     ParseLexedMethodDeclarations(getCurrentClass());
    1572             3174:     ParseLexedMethodDefs(getCurrentClass());
    1573                 :   }
    1574                 : 
    1575                 :   // Leave the class scope.
    1576             3394:   ParsingDef.Pop();
    1577             3394:   ClassScope.Exit();
    1578                 : 
                     3394: branch 2 taken
                        9: branch 3 taken
                     3394: branch 5 taken
                        9: branch 6 taken
                     3394: branch 8 taken
                        9: branch 9 taken
    1579             3394:   Actions.ActOnTagFinishDefinition(CurScope, TagDecl, RBraceLoc);
    1580                 : }
    1581                 : 
    1582                 : /// ParseConstructorInitializer - Parse a C++ constructor initializer,
    1583                 : /// which explicitly initializes the members or base classes of a
    1584                 : /// class (C++ [class.base.init]). For example, the three initializers
    1585                 : /// after the ':' in the Derived constructor below:
    1586                 : ///
    1587                 : /// @code
    1588                 : /// class Base { };
    1589                 : /// class Derived : Base {
    1590                 : ///   int x;
    1591                 : ///   float f;
    1592                 : /// public:
    1593                 : ///   Derived(float f) : Base(), x(17), f(f) { }
    1594                 : /// };
    1595                 : /// @endcode
    1596                 : ///
    1597                 : /// [C++]  ctor-initializer:
    1598                 : ///          ':' mem-initializer-list
    1599                 : ///
    1600                 : /// [C++]  mem-initializer-list:
    1601                 : ///          mem-initializer
    1602                 : ///          mem-initializer , mem-initializer-list
    1603              165: void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) {
                      165: branch 1 taken
                        0: branch 2 not taken
    1604              165:   assert(Tok.is(tok::colon) && "Constructor initializer always starts with ':'");
    1605                 : 
    1606              165:   SourceLocation ColonLoc = ConsumeToken();
    1607                 : 
    1608              165:   llvm::SmallVector<MemInitTy*, 4> MemInitializers;
    1609              165:   bool AnyErrors = false;
    1610                 :   
    1611              142:   do {
    1612              307:     MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
                      288: branch 1 taken
                       19: branch 2 taken
    1613              307:     if (!MemInit.isInvalid())
    1614              288:       MemInitializers.push_back(MemInit.get());
    1615                 :     else
    1616               19:       AnyErrors = true;
    1617                 :     
                      142: branch 1 taken
                      165: branch 2 taken
    1618              307:     if (Tok.is(tok::comma))
    1619              142:       ConsumeToken();
                      163: branch 1 taken
                        2: branch 2 taken
    1620              165:     else if (Tok.is(tok::l_brace))
    1621              163:       break;
    1622                 :     else {
    1623                 :       // Skip over garbage, until we get to '{'.  Don't eat the '{'.
    1624                2:       Diag(Tok.getLocation(), diag::err_expected_lbrace_or_comma);
    1625                2:       SkipUntil(tok::l_brace, true, true);
    1626                2:       break;
    1627                 :     }
    1628                 :   } while (true);
    1629                 : 
    1630                 :   Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc,
    1631                 :                                MemInitializers.data(), MemInitializers.size(),
    1632              165:                                AnyErrors);
    1633              165: }
    1634                 : 
    1635                 : /// ParseMemInitializer - Parse a C++ member initializer, which is
    1636                 : /// part of a constructor initializer that explicitly initializes one
    1637                 : /// member or base class (C++ [class.base.init]). See
    1638                 : /// ParseConstructorInitializer for an example.
    1639                 : ///
    1640                 : /// [C++] mem-initializer:
    1641                 : ///         mem-initializer-id '(' expression-list[opt] ')'
    1642                 : ///
    1643                 : /// [C++] mem-initializer-id:
    1644                 : ///         '::'[opt] nested-name-specifier[opt] class-name
    1645                 : ///         identifier
    1646              307: Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) {
    1647                 :   // parse '::'[opt] nested-name-specifier[opt]
    1648              307:   CXXScopeSpec SS;
    1649              307:   ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/0, false);
    1650              307:   TypeTy *TemplateTypeTy = 0;
                       10: branch 1 taken
                      297: branch 2 taken
    1651              307:   if (Tok.is(tok::annot_template_id)) {
    1652                 :     TemplateIdAnnotation *TemplateId
    1653               10:       = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue());
                        2: branch 0 taken
                        8: branch 1 taken
                        2: branch 2 taken
                        0: branch 3 not taken
    1654               10:     if (TemplateId->Kind == TNK_Type_template ||
    1655                 :         TemplateId->Kind == TNK_Dependent_template_name) {
    1656               10:       AnnotateTemplateIdTokenAsType(&SS);
                       10: branch 1 taken
                        0: branch 2 not taken
    1657               10:       assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
    1658               10:       TemplateTypeTy = Tok.getAnnotationValue();
    1659                 :     }
    1660                 :   }
                      297: branch 0 taken
                       10: branch 1 taken
                        0: branch 3 not taken
                      297: branch 4 taken
                        0: branch 5 not taken
                      307: branch 6 taken
    1661              307:   if (!TemplateTypeTy && Tok.isNot(tok::identifier)) {
    1662                0:     Diag(Tok, diag::err_expected_member_or_base_name);
    1663                0:     return true;
    1664                 :   }
    1665                 : 
    1666                 :   // Get the identifier. This may be a member name or a class name,
    1667                 :   // but we'll let the semantic analysis determine which it is.
                      297: branch 1 taken
                       10: branch 2 taken
    1668              307:   IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0;
    1669              307:   SourceLocation IdLoc = ConsumeToken();
    1670                 : 
    1671                 :   // Parse the '('.
                        0: branch 1 not taken
                      307: branch 2 taken
    1672              307:   if (Tok.isNot(tok::l_paren)) {
    1673                0:     Diag(Tok, diag::err_expected_lparen);
    1674                0:     return true;
    1675                 :   }
    1676              307:   SourceLocation LParenLoc = ConsumeParen();
    1677                 : 
    1678                 :   // Parse the optional expression-list.
    1679              307:   ExprVector ArgExprs(Actions);
    1680              307:   CommaLocsTy CommaLocs;
                      246: branch 1 taken
                       61: branch 2 taken
                        0: branch 4 not taken
                      246: branch 5 taken
                        0: branch 6 not taken
                      307: branch 7 taken
    1681              307:   if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
    1682                0:     SkipUntil(tok::r_paren);
    1683                0:     return true;
    1684                 :   }
    1685                 : 
    1686              307:   SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1687                 : 
    1688                 :   return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II,
    1689                 :                                      TemplateTypeTy, IdLoc,
    1690                 :                                      LParenLoc, ArgExprs.take(),
    1691                 :                                      ArgExprs.size(), CommaLocs.data(),
    1692              307:                                      RParenLoc);
    1693                 : }
    1694                 : 
    1695                 : /// ParseExceptionSpecification - Parse a C++ exception-specification
    1696                 : /// (C++ [except.spec]).
    1697                 : ///
    1698                 : ///       exception-specification:
    1699                 : ///         'throw' '(' type-id-list [opt] ')'
    1700                 : /// [MS]    'throw' '(' '...' ')'
    1701                 : ///
    1702                 : ///       type-id-list:
    1703                 : ///         type-id
    1704                 : ///         type-id-list ',' type-id
    1705                 : ///
    1706                 : bool Parser::ParseExceptionSpecification(SourceLocation &EndLoc,
    1707                 :                                          llvm::SmallVector<TypeTy*, 2>
    1708                 :                                              &Exceptions,
    1709                 :                                          llvm::SmallVector<SourceRange, 2>
    1710                 :                                              &Ranges,
    1711              328:                                          bool &hasAnyExceptionSpec) {
                      328: branch 1 taken
                        0: branch 2 not taken
    1712              328:   assert(Tok.is(tok::kw_throw) && "expected throw");
    1713                 : 
    1714              328:   SourceLocation ThrowLoc = ConsumeToken();
    1715                 : 
                        0: branch 1 not taken
                      328: branch 2 taken
    1716              328:   if (!Tok.is(tok::l_paren)) {
    1717                0:     return Diag(Tok, diag::err_expected_lparen_after) << "throw";
    1718                 :   }
    1719              328:   SourceLocation LParenLoc = ConsumeParen();
    1720                 : 
    1721                 :   // Parse throw(...), a Microsoft extension that means "this function
    1722                 :   // can throw anything".
                        5: branch 1 taken
                      323: branch 2 taken
    1723              328:   if (Tok.is(tok::ellipsis)) {
    1724                5:     hasAnyExceptionSpec = true;
    1725                5:     SourceLocation EllipsisLoc = ConsumeToken();
                        0: branch 1 not taken
                        5: branch 2 taken
    1726                5:     if (!getLang().Microsoft)
    1727                0:       Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
    1728                5:     EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1729                5:     return false;
    1730                 :   }
    1731                 : 
    1732                 :   // Parse the sequence of type-ids.
    1733              323:   SourceRange Range;
                      102: branch 1 taken
                      241: branch 2 taken
    1734              666:   while (Tok.isNot(tok::r_paren)) {
    1735              102:     TypeResult Res(ParseTypeName(&Range));
                      102: branch 1 taken
                        0: branch 2 not taken
    1736              102:     if (!Res.isInvalid()) {
    1737              102:       Exceptions.push_back(Res.get());
    1738              102:       Ranges.push_back(Range);
    1739                 :     }
                       82: branch 1 taken
                       20: branch 2 taken
    1740              102:     if (Tok.is(tok::comma))
    1741               20:       ConsumeToken();
    1742                 :     else
    1743               82:       break;
    1744                 :   }
    1745                 : 
    1746              323:   EndLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
    1747              323:   return false;
    1748                 : }
    1749                 : 
    1750                 : /// \brief We have just started parsing the definition of a new class,
    1751                 : /// so push that class onto our stack of classes that is currently
    1752                 : /// being parsed.
    1753             3403: void Parser::PushParsingClass(DeclPtrTy ClassDecl, bool NonNestedClass) {
    1754                 :   assert((NonNestedClass || !ClassStack.empty()) &&
                      220: branch 0 taken
                     3183: branch 1 taken
                      220: branch 3 taken
                        0: branch 4 not taken
    1755             3403:          "Nested class without outer class");
    1756             3403:   ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass));
    1757             3403: }
    1758                 : 
    1759                 : /// \brief Deallocate the given parsed class and all of its nested
    1760                 : /// classes.
    1761             3208: void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
                       25: branch 1 taken
                     3208: branch 2 taken
    1762             3233:   for (unsigned I = 0, N = Class->NestedClasses.size(); I != N; ++I)
    1763               25:     DeallocateParsedClasses(Class->NestedClasses[I]);
                     3208: branch 0 taken
                        0: branch 1 not taken
    1764             3208:   delete Class;
    1765             3208: }
    1766                 : 
    1767                 : /// \brief Pop the top class of the stack of classes that are
    1768                 : /// currently being parsed.
    1769                 : ///
    1770                 : /// This routine should be called when we have finished parsing the
    1771                 : /// definition of a class, but have not yet popped the Scope
    1772                 : /// associated with the class's definition.
    1773                 : ///
    1774                 : /// \returns true if the class we've popped is a top-level class,
    1775                 : /// false otherwise.
    1776             3403: void Parser::PopParsingClass() {
                     3403: branch 1 taken
                        0: branch 2 not taken
    1777             3403:   assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");
    1778                 : 
    1779             3403:   ParsingClass *Victim = ClassStack.top();
    1780             3403:   ClassStack.pop();
                     3183: branch 0 taken
                      220: branch 1 taken
    1781             3403:   if (Victim->TopLevelClass) {
    1782                 :     // Deallocate all of the nested classes of this class,
    1783                 :     // recursively: we don't need to keep any of this information.
    1784             3183:     DeallocateParsedClasses(Victim);
    1785             3183:     return;
    1786                 :   }
                      220: branch 1 taken
                        0: branch 2 not taken
    1787              220:   assert(!ClassStack.empty() && "Missing top-level class?");
    1788                 : 
                      219: branch 1 taken
                        1: branch 2 taken
                      200: branch 4 taken
                       19: branch 5 taken
                      195: branch 7 taken
                        5: branch 8 taken
                      195: branch 9 taken
                       25: branch 10 taken
    1789              439:   if (Victim->MethodDecls.empty() && Victim->MethodDefs.empty() &&
    1790                 :       Victim->NestedClasses.empty()) {
    1791                 :     // The victim is a nested class, but we will not need to perform
    1792                 :     // any processing after the definition of this class since it has
    1793                 :     // no members whose handling was delayed. Therefore, we can just
    1794                 :     // remove this nested class.
                      195: branch 0 taken
                        0: branch 1 not taken
    1795              195:     delete Victim;
    1796              195:     return;
    1797                 :   }
    1798                 : 
    1799                 :   // This nested class has some members that will need to be processed
    1800                 :   // after the top-level class is completely defined. Therefore, add
    1801                 :   // it to the list of nested classes within its parent.
                       25: branch 1 taken
                        0: branch 2 not taken
    1802               25:   assert(CurScope->isClassScope() && "Nested class outside of class scope?");
    1803               25:   ClassStack.top()->NestedClasses.push_back(Victim);
    1804               25:   Victim->TemplateScope = CurScope->getParent()->isTemplateParamScope();
    1805                 : }
    1806                 : 
    1807                 : /// ParseCXX0XAttributes - Parse a C++0x attribute-specifier. Currently only
    1808                 : /// parses standard attributes.
    1809                 : ///
    1810                 : /// [C++0x] attribute-specifier:
    1811                 : ///         '[' '[' attribute-list ']' ']'
    1812                 : ///
    1813                 : /// [C++0x] attribute-list:
    1814                 : ///         attribute[opt]
    1815                 : ///         attribute-list ',' attribute[opt]
    1816                 : ///
    1817                 : /// [C++0x] attribute:
    1818                 : ///         attribute-token attribute-argument-clause[opt]
    1819                 : ///
    1820                 : /// [C++0x] attribute-token:
    1821                 : ///         identifier
    1822                 : ///         attribute-scoped-token
    1823                 : ///
    1824                 : /// [C++0x] attribute-scoped-token:
    1825                 : ///         attribute-namespace '::' identifier
    1826                 : ///
    1827                 : /// [C++0x] attribute-namespace:
    1828                 : ///         identifier
    1829                 : ///
    1830                 : /// [C++0x] attribute-argument-clause:
    1831                 : ///         '(' balanced-token-seq ')'
    1832                 : ///
    1833                 : /// [C++0x] balanced-token-seq:
    1834                 : ///         balanced-token
    1835                 : ///         balanced-token-seq balanced-token
    1836                 : ///
    1837                 : /// [C++0x] balanced-token:
    1838                 : ///         '(' balanced-token-seq ')'
    1839                 : ///         '[' balanced-token-seq ']'
    1840                 : ///         '{' balanced-token-seq '}'
    1841                 : ///         any token but '(', ')', '[', ']', '{', or '}'
    1842               51: CXX0XAttributeList Parser::ParseCXX0XAttributes(SourceLocation *EndLoc) {
    1843                 :   assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
                       51: branch 1 taken
                        0: branch 2 not taken
                       51: branch 5 taken
                        0: branch 6 not taken
    1844               51:       && "Not a C++0x attribute list");
    1845                 : 
    1846               51:   SourceLocation StartLoc = Tok.getLocation(), Loc;
    1847               51:   AttributeList *CurrAttr = 0;
    1848                 : 
    1849               51:   ConsumeBracket();
    1850               51:   ConsumeBracket();
    1851                 :   
                        1: branch 1 taken
                       50: branch 2 taken
    1852               51:   if (Tok.is(tok::comma)) {
    1853                1:     Diag(Tok.getLocation(), diag::err_expected_ident);
    1854                1:     ConsumeToken();
    1855                 :   }
    1856                 : 
                       54: branch 1 taken
                       21: branch 2 taken
                        3: branch 4 taken
                       51: branch 5 taken
                       24: branch 6 taken
                       51: branch 7 taken
    1857              126:   while (Tok.is(tok::identifier) || Tok.is(tok::comma)) {
    1858                 :     // attribute not present
                        3: branch 1 taken
                       21: branch 2 taken
    1859               24:     if (Tok.is(tok::comma)) {
    1860                3:       ConsumeToken();
    1861                3:       continue;
    1862                 :     }
    1863                 : 
    1864               21:     IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
    1865               21:     SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
    1866                 :     
    1867                 :     // scoped attribute
                        2: branch 1 taken
                       19: branch 2 taken
    1868               21:     if (Tok.is(tok::coloncolon)) {
    1869                2:       ConsumeToken();
    1870                 : 
                        1: branch 1 taken
                        1: branch 2 taken
    1871                2:       if (!Tok.is(tok::identifier)) {
    1872                1:         Diag(Tok.getLocation(), diag::err_expected_ident);
    1873                1:         SkipUntil(tok::r_square, tok::comma, true, true);
    1874                1:         continue;
    1875                 :       }
    1876                 :       
    1877                1:       ScopeName = AttrName;
    1878                1:       ScopeLoc = AttrLoc;
    1879                 : 
    1880                1:       AttrName = Tok.getIdentifierInfo();
    1881                1:       AttrLoc = ConsumeToken();
    1882                 :     }
    1883                 : 
    1884               20:     bool AttrParsed = false;
    1885                 :     // No scoped names are supported; ideally we could put all non-standard
    1886                 :     // attributes into namespaces.
                       19: branch 0 taken
                        1: branch 1 taken
    1887               20:     if (!ScopeName) {
                        9: branch 1 taken
                       10: branch 2 taken
                        0: branch 3 not taken
    1888               19:       switch(AttributeList::getKind(AttrName))
    1889                 :       {
    1890                 :       // No arguments
    1891                 :       case AttributeList::AT_base_check:
    1892                 :       case AttributeList::AT_carries_dependency:
    1893                 :       case AttributeList::AT_final:
    1894                 :       case AttributeList::AT_hiding:
    1895                 :       case AttributeList::AT_noreturn:
    1896                 :       case AttributeList::AT_override: {
                        1: branch 1 taken
                        8: branch 2 taken
    1897                9:         if (Tok.is(tok::l_paren)) {
    1898                 :           Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
    1899                1:             << AttrName->getName();
    1900                1:           break;
    1901                 :         }
    1902                 : 
    1903                 :         CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc, 0,
    1904                 :                                      SourceLocation(), 0, 0, CurrAttr, false,
    1905                8:                                      true);
    1906                8:         AttrParsed = true;
    1907                8:         break;
    1908                 :       }
    1909                 : 
    1910                 :       // One argument; must be a type-id or assignment-expression
    1911                 :       case AttributeList::AT_aligned: {
                        1: branch 1 taken
                        9: branch 2 taken
    1912               10:         if (Tok.isNot(tok::l_paren)) {
    1913                 :           Diag(Tok.getLocation(), diag::err_cxx0x_attribute_requires_arguments)
    1914                1:             << AttrName->getName();
    1915                1:           break;
    1916                 :         }
    1917                9:         SourceLocation ParamLoc = ConsumeParen();
    1918                 : 
    1919                9:         OwningExprResult ArgExpr = ParseCXX0XAlignArgument(ParamLoc);
    1920                 : 
    1921                9:         MatchRHSPunctuation(tok::r_paren, ParamLoc);
    1922                 : 
    1923                9:         ExprVector ArgExprs(Actions);
    1924                9:         ArgExprs.push_back(ArgExpr.release());
    1925                 :         CurrAttr = new AttributeList(AttrName, AttrLoc, 0, AttrLoc,
    1926                 :                                      0, ParamLoc, ArgExprs.take(), 1, CurrAttr,
    1927                9:                                      false, true);
    1928                 : 
    1929                9:         AttrParsed = true;
    1930                9:         break;
    1931                 :       }
    1932                 : 
    1933                 :       // Silence warnings
    1934                 :       default: break;
    1935                 :       }
    1936                 :     }
    1937                 : 
    1938                 :     // Skip the entire parameter clause, if any
                        3: branch 0 taken
                       17: branch 1 taken
                        2: branch 3 taken
                        1: branch 4 taken
                        2: branch 5 taken
                       18: branch 6 taken
    1939               20:     if (!AttrParsed && Tok.is(tok::l_paren)) {
    1940                2:       ConsumeParen();
    1941                 :       // SkipUntil maintains the balancedness of tokens.
    1942                2:       SkipUntil(tok::r_paren, false);
    1943                 :     }
    1944                 :   }
    1945                 : 
                        0: branch 1 not taken
                       51: branch 2 taken
    1946               51:   if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
    1947                0:     SkipUntil(tok::r_square, false);
    1948               51:   Loc = Tok.getLocation();
                        0: branch 1 not taken
                       51: branch 2 taken
    1949               51:   if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
    1950                0:     SkipUntil(tok::r_square, false);
    1951                 : 
    1952               51:   CXX0XAttributeList Attr (CurrAttr, SourceRange(StartLoc, Loc), true);
    1953                 :   return Attr;
    1954                 : }
    1955                 : 
    1956                 : /// ParseCXX0XAlignArgument - Parse the argument to C++0x's [[align]]
    1957                 : /// attribute.
    1958                 : ///
    1959                 : /// FIXME: Simply returns an alignof() expression if the argument is a
    1960                 : /// type. Ideally, the type should be propagated directly into Sema.
    1961                 : ///
    1962                 : /// [C++0x] 'align' '(' type-id ')'
    1963                 : /// [C++0x] 'align' '(' assignment-expression ')'
    1964                9: Parser::OwningExprResult Parser::ParseCXX0XAlignArgument(SourceLocation Start) {
                        1: branch 1 taken
                        8: branch 2 taken
    1965                9:   if (isTypeIdInParens()) {
    1966                 :     EnterExpressionEvaluationContext Unevaluated(Actions,
    1967                1:                                                   Action::Unevaluated);
    1968                1:     SourceLocation TypeLoc = Tok.getLocation();
    1969                1:     TypeTy *Ty = ParseTypeName().get();
    1970                1:     SourceRange TypeRange(Start, Tok.getLocation());
    1971                 :     return Actions.ActOnSizeOfAlignOfExpr(TypeLoc, false, true, Ty,
    1972                1:                                               TypeRange);
    1973                 :   } else
    1974                8:     return ParseConstantExpression();
    1975                 : }

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