diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp')
| -rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp | 487 | 
1 files changed, 404 insertions, 83 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp index 8c0aa1ba694c..51aa01091e73 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/ParseDeclCXX.cpp @@ -60,12 +60,20 @@ Decl *Parser::ParseNamespace(unsigned Context,    SourceLocation IdentLoc;    IdentifierInfo *Ident = 0; +  std::vector<SourceLocation> ExtraIdentLoc; +  std::vector<IdentifierInfo*> ExtraIdent; +  std::vector<SourceLocation> ExtraNamespaceLoc;    Token attrTok;    if (Tok.is(tok::identifier)) {      Ident = Tok.getIdentifierInfo();      IdentLoc = ConsumeToken();  // eat the identifier. +    while (Tok.is(tok::coloncolon) && NextToken().is(tok::identifier)) { +      ExtraNamespaceLoc.push_back(ConsumeToken()); +      ExtraIdent.push_back(Tok.getIdentifierInfo()); +      ExtraIdentLoc.push_back(ConsumeToken()); +    }    }    // Read label attributes, if present. @@ -85,7 +93,12 @@ Decl *Parser::ParseNamespace(unsigned Context,      return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);    } +    if (Tok.isNot(tok::l_brace)) { +    if (!ExtraIdent.empty()) { +      Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) +          << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); +    }      Diag(Tok, Ident ? diag::err_expected_lbrace :           diag::err_expected_ident_lbrace);      return 0; @@ -96,11 +109,44 @@ Decl *Parser::ParseNamespace(unsigned Context,    if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() ||         getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() ||         getCurScope()->getFnParent()) { +    if (!ExtraIdent.empty()) { +      Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) +          << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); +    }      Diag(LBrace, diag::err_namespace_nonnamespace_scope);      SkipUntil(tok::r_brace, false);      return 0;    } +  if (!ExtraIdent.empty()) { +    TentativeParsingAction TPA(*this); +    SkipUntil(tok::r_brace, /*StopAtSemi*/false, /*DontConsume*/true); +    Token rBraceToken = Tok; +    TPA.Revert(); + +    if (!rBraceToken.is(tok::r_brace)) { +      Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) +          << SourceRange(ExtraNamespaceLoc.front(), ExtraIdentLoc.back()); +    } else { +      std::string NamespaceFix; +      for (std::vector<IdentifierInfo*>::iterator I = ExtraIdent.begin(), +           E = ExtraIdent.end(); I != E; ++I) { +        NamespaceFix += " { namespace "; +        NamespaceFix += (*I)->getName(); +      } + +      std::string RBraces; +      for (unsigned i = 0, e = ExtraIdent.size(); i != e; ++i) +        RBraces +=  "} "; + +      Diag(ExtraNamespaceLoc[0], diag::err_nested_namespaces_with_double_colon) +          << FixItHint::CreateReplacement(SourceRange(ExtraNamespaceLoc.front(), +                                                      ExtraIdentLoc.back()), +                                          NamespaceFix) +          << FixItHint::CreateInsertion(rBraceToken.getLocation(), RBraces); +    } +  } +    // If we're still good, complain about inline namespaces in non-C++0x now.    if (!getLang().CPlusPlus0x && InlineLoc.isValid())      Diag(InlineLoc, diag::ext_inline_namespace); @@ -115,23 +161,56 @@ Decl *Parser::ParseNamespace(unsigned Context,    PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,                                        "parsing namespace"); -  while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { -    ParsedAttributesWithRange attrs(AttrFactory); -    MaybeParseCXX0XAttributes(attrs); -    MaybeParseMicrosoftAttributes(attrs); -    ParseExternalDeclaration(attrs); -  } +  SourceLocation RBraceLoc; +  // Parse the contents of the namespace.  This includes parsing recovery on  +  // any improperly nested namespaces. +  ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0, +                      InlineLoc, LBrace, attrs, RBraceLoc);    // Leave the namespace scope.    NamespaceScope.Exit(); -  SourceLocation RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace);    Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc);    DeclEnd = RBraceLoc;    return NamespcDecl;  } +/// ParseInnerNamespace - Parse the contents of a namespace. +void Parser::ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, +                                 std::vector<IdentifierInfo*>& Ident, +                                 std::vector<SourceLocation>& NamespaceLoc, +                                 unsigned int index, SourceLocation& InlineLoc, +                                 SourceLocation& LBrace, +                                 ParsedAttributes& attrs, +                                 SourceLocation& RBraceLoc) { +  if (index == Ident.size()) { +    while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { +      ParsedAttributesWithRange attrs(AttrFactory); +      MaybeParseCXX0XAttributes(attrs); +      MaybeParseMicrosoftAttributes(attrs); +      ParseExternalDeclaration(attrs); +    } +    RBraceLoc = MatchRHSPunctuation(tok::r_brace, LBrace); + +    return; +  } + +  // Parse improperly nested namespaces. +  ParseScope NamespaceScope(this, Scope::DeclScope); +  Decl *NamespcDecl = +    Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), +                                   NamespaceLoc[index], IdentLoc[index], +                                   Ident[index], LBrace, attrs.getList()); + +  ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc, +                      LBrace, attrs, RBraceLoc); + +  NamespaceScope.Exit(); + +  Actions.ActOnFinishNamespaceDef(NamespcDecl, RBraceLoc); +} +  /// ParseNamespaceAlias - Parse the part after the '=' in a namespace  /// alias definition.  /// @@ -387,13 +466,35 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,    bool IsAliasDecl = Tok.is(tok::equal);    TypeResult TypeAlias;    if (IsAliasDecl) { -    // TODO: Do we want to support attributes somewhere in an alias declaration? -    // Can't follow GCC since it doesn't support them yet! +    // TODO: Attribute support. C++0x attributes may appear before the equals. +    // Where can GNU attributes appear?      ConsumeToken();      if (!getLang().CPlusPlus0x)        Diag(Tok.getLocation(), diag::ext_alias_declaration); +    // Type alias templates cannot be specialized. +    int SpecKind = -1; +    if (TemplateInfo.Kind == ParsedTemplateInfo::Template && +        Name.getKind() == UnqualifiedId::IK_TemplateId) +      SpecKind = 0; +    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) +      SpecKind = 1; +    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) +      SpecKind = 2; +    if (SpecKind != -1) { +      SourceRange Range; +      if (SpecKind == 0) +        Range = SourceRange(Name.TemplateId->LAngleLoc, +                            Name.TemplateId->RAngleLoc); +      else +        Range = TemplateInfo.getSourceRange(); +      Diag(Range.getBegin(), diag::err_alias_declaration_specialization) +        << SpecKind << Range; +      SkipUntil(tok::semi); +      return 0; +    } +      // Name must be an identifier.      if (Name.getKind() != UnqualifiedId::IK_Identifier) {        Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); @@ -408,7 +509,9 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,        Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)          << FixItHint::CreateRemoval(SS.getRange()); -    TypeAlias = ParseTypeName(0, Declarator::AliasDeclContext); +    TypeAlias = ParseTypeName(0, TemplateInfo.Kind ? +                              Declarator::AliasTemplateContext : +                              Declarator::AliasDeclContext);    } else      // Parse (optional) attributes (most likely GNU strong-using extension).      MaybeParseGNUAttributes(attrs); @@ -421,9 +524,9 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,                     tok::semi);    // Diagnose an attempt to declare a templated using-declaration. -  // TODO: in C++0x, alias-declarations can be templates: +  // In C++0x, alias-declarations can be templates:    //   template <...> using id = type; -  if (TemplateInfo.Kind) { +  if (TemplateInfo.Kind && !IsAliasDecl) {      SourceRange R = TemplateInfo.getSourceRange();      Diag(UsingLoc, diag::err_templated_using_declaration)        << R << FixItHint::CreateRemoval(R); @@ -434,9 +537,14 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,      return 0;    } -  if (IsAliasDecl) -    return Actions.ActOnAliasDeclaration(getCurScope(), AS, UsingLoc, Name, -                                         TypeAlias); +  if (IsAliasDecl) { +    TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams; +    MultiTemplateParamsArg TemplateParamsArg(Actions, +      TemplateParams ? TemplateParams->data() : 0, +      TemplateParams ? TemplateParams->size() : 0); +    return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, +                                         UsingLoc, Name, TypeAlias); +  }    return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,                                         Name, attrs.getList(), @@ -543,6 +651,42 @@ void Parser::ParseDecltypeSpecifier(DeclSpec &DS) {      Diag(StartLoc, DiagID) << PrevSpec;  } +void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) { +  assert(Tok.is(tok::kw___underlying_type) && +         "Not an underlying type specifier"); + +  SourceLocation StartLoc = ConsumeToken(); +  SourceLocation LParenLoc = Tok.getLocation(); + +  if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, +                       "__underlying_type")) { +    SkipUntil(tok::r_paren); +    return; +  } + +  TypeResult Result = ParseTypeName(); +  if (Result.isInvalid()) { +    SkipUntil(tok::r_paren); +    return; +  } + +  // Match the ')' +  SourceLocation RParenLoc; +  if (Tok.is(tok::r_paren)) +    RParenLoc = ConsumeParen(); +  else +    MatchRHSPunctuation(tok::r_paren, LParenLoc); + +  if (RParenLoc.isInvalid()) +    return; + +  const char *PrevSpec = 0; +  unsigned DiagID; +  if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec, +                         DiagID, Result.release())) +    Diag(StartLoc, DiagID) << PrevSpec; +} +  /// ParseClassName - Parse a C++ class-name, which names a class. Note  /// that we only check that the result names a type; semantic analysis  /// will need to verify that the type names a class. The result is @@ -1409,6 +1553,7 @@ bool Parser::isCXX0XFinalKeyword() const {  ///       member-declarator:  ///         declarator virt-specifier-seq[opt] pure-specifier[opt]  ///         declarator constant-initializer[opt] +/// [C++11] declarator brace-or-equal-initializer[opt]  ///         identifier[opt] ':' constant-expression  ///  ///       virt-specifier-seq: @@ -1515,8 +1660,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,    MaybeParseMicrosoftAttributes(attrs);    if (Tok.is(tok::kw_using)) { -    // FIXME: Check for template aliases -      ProhibitAttributes(attrs);      // Eat 'using'. @@ -1527,7 +1670,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,        SkipUntil(tok::semi, true, true);      } else {        SourceLocation DeclEnd; -      // Otherwise, it must be using-declaration. +      // Otherwise, it must be a using-declaration or an alias-declaration.        ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,                              UsingLoc, DeclEnd, AS);      } @@ -1547,13 +1690,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,    if (Tok.is(tok::semi)) {      ConsumeToken();      Decl *TheDecl = -      Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS); +      Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams);      DS.complete(TheDecl);      return;    }    ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);    VirtSpecifiers VS; +  ExprResult Init;    if (Tok.isNot(tok::colon)) {      // Don't parse FOO:BAR as if it were a typo for FOO::BAR. @@ -1575,10 +1719,36 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      // If attributes exist after the declarator, but before an '{', parse them.      MaybeParseGNUAttributes(DeclaratorInfo); +    // MSVC permits pure specifier on inline functions declared at class scope. +    // Hence check for =0 before checking for function definition. +    if (getLang().Microsoft && Tok.is(tok::equal) && +        DeclaratorInfo.isFunctionDeclarator() &&  +        NextToken().is(tok::numeric_constant)) { +      ConsumeToken(); +      Init = ParseInitializer(); +      if (Init.isInvalid()) +        SkipUntil(tok::comma, true, true); +    } + +    bool IsDefinition = false;      // function-definition: -    if (Tok.is(tok::l_brace) -        || (DeclaratorInfo.isFunctionDeclarator() && -            (Tok.is(tok::colon) || Tok.is(tok::kw_try)))) { +    // +    // In C++11, a non-function declarator followed by an open brace is a +    // braced-init-list for an in-class member initialization, not an +    // erroneous function definition. +    if (Tok.is(tok::l_brace) && !getLang().CPlusPlus0x) { +      IsDefinition = true; +    } else if (DeclaratorInfo.isFunctionDeclarator()) { +      if (Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) { +        IsDefinition = true; +      } else if (Tok.is(tok::equal)) { +        const Token &KW = NextToken(); +        if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) +          IsDefinition = true; +      } +    } + +    if (IsDefinition) {        if (!DeclaratorInfo.isFunctionDeclarator()) {          Diag(Tok, diag::err_func_def_no_params);          ConsumeBrace(); @@ -1604,10 +1774,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,          return;        } -      ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS); -      // Consume the optional ';' -      if (Tok.is(tok::semi)) +      ParseCXXInlineMethodDef(AS, DeclaratorInfo, TemplateInfo, VS, Init); + +      // Consume the ';' - it's optional unless we have a delete or default +      if (Tok.is(tok::semi)) {          ConsumeToken(); +      }        return;      } @@ -1619,13 +1791,11 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,    llvm::SmallVector<Decl *, 8> DeclsInGroup;    ExprResult BitfieldSize; -  ExprResult Init; -  bool Deleted = false;    while (1) {      // member-declarator:      //   declarator pure-specifier[opt] -    //   declarator constant-initializer[opt] +    //   declarator brace-or-equal-initializer[opt]      //   identifier[opt] ':' constant-expression      if (Tok.is(tok::colon)) {        ConsumeToken(); @@ -1634,31 +1804,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,          SkipUntil(tok::comma, true, true);      } -    ParseOptionalCXX0XVirtSpecifierSeq(VS); - -    // pure-specifier: -    //   '= 0' -    // -    // constant-initializer: -    //   '=' constant-expression -    // -    // defaulted/deleted function-definition: -    //   '=' 'default'                          [TODO] -    //   '=' 'delete' -    if (Tok.is(tok::equal)) { -      ConsumeToken(); -      if (Tok.is(tok::kw_delete)) { -        if (!getLang().CPlusPlus0x) -          Diag(Tok, diag::warn_deleted_function_accepted_as_extension); -        ConsumeToken(); -        Deleted = true; -      } else { -        Init = ParseInitializer(); -        if (Init.isInvalid()) -          SkipUntil(tok::comma, true, true); -      } -    } -      // If a simple-asm-expr is present, parse it.      if (Tok.is(tok::kw_asm)) {        SourceLocation Loc; @@ -1673,6 +1818,30 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      // If attributes exist after the declarator, parse them.      MaybeParseGNUAttributes(DeclaratorInfo); +    // FIXME: When g++ adds support for this, we'll need to check whether it +    // goes before or after the GNU attributes and __asm__. +    ParseOptionalCXX0XVirtSpecifierSeq(VS); + +    bool HasDeferredInitializer = false; +    if (Tok.is(tok::equal) || Tok.is(tok::l_brace)) { +      if (BitfieldSize.get()) { +        Diag(Tok, diag::err_bitfield_member_init); +        SkipUntil(tok::comma, true, true); +      } else { +        HasDeferredInitializer = !DeclaratorInfo.isFunctionDeclarator() && +          DeclaratorInfo.getDeclSpec().getStorageClassSpec() +            != DeclSpec::SCS_static; + +        if (!HasDeferredInitializer) { +          SourceLocation EqualLoc; +          Init = ParseCXXMemberInitializer( +            DeclaratorInfo.isFunctionDeclarator(), EqualLoc); +          if (Init.isInvalid()) +            SkipUntil(tok::comma, true, true); +        } +      } +    } +      // NOTE: If Sema is the Action module and declarator is an instance field,      // this call will *not* return the created decl; It will return null.      // See Sema::ActOnCXXMemberDeclarator for details. @@ -1689,8 +1858,8 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,                                                    move(TemplateParams),                                                    BitfieldSize.release(),                                                    VS, Init.release(), -                                                  /*IsDefinition*/Deleted, -                                                  Deleted); +                                                  HasDeferredInitializer, +                                                  /*IsDefinition*/ false);      }      if (ThisDecl)        DeclsInGroup.push_back(ThisDecl); @@ -1703,6 +1872,24 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      DeclaratorInfo.complete(ThisDecl); +    if (HasDeferredInitializer) { +      if (!getLang().CPlusPlus0x) +        Diag(Tok, diag::warn_nonstatic_member_init_accepted_as_extension); + +      if (DeclaratorInfo.isArrayOfUnknownBound()) { +        // C++0x [dcl.array]p3: An array bound may also be omitted when the +        // declarator is followed by an initializer.  +        // +        // A brace-or-equal-initializer for a member-declarator is not an +        // initializer in the gramamr, so this is ill-formed. +        Diag(Tok, diag::err_incomplete_array_member_init); +        SkipUntil(tok::comma, true, true); +        // Avoid later warnings about a class member of incomplete type. +        ThisDecl->setInvalidDecl(); +      } else +        ParseCXXNonStaticMemberInitializer(ThisDecl); +    } +      // If we don't have a comma, it is either the end of the list (a ';')      // or an error, bail out.      if (Tok.isNot(tok::comma)) @@ -1716,7 +1903,6 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,      VS.clear();      BitfieldSize = 0;      Init = 0; -    Deleted = false;      // Attributes are only allowed on the second declarator.      MaybeParseGNUAttributes(DeclaratorInfo); @@ -1737,6 +1923,66 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,                                    DeclsInGroup.size());  } +/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer or +/// pure-specifier. Also detect and reject any attempted defaulted/deleted +/// function definition. The location of the '=', if any, will be placed in +/// EqualLoc. +/// +///   pure-specifier: +///     '= 0' +///   +///   brace-or-equal-initializer: +///     '=' initializer-expression +///     braced-init-list                       [TODO] +///   +///   initializer-clause: +///     assignment-expression +///     braced-init-list                       [TODO] +///   +///   defaulted/deleted function-definition:                                                                                                                                                                                                +///     '=' 'default' +///     '=' 'delete' +/// +/// Prior to C++0x, the assignment-expression in an initializer-clause must +/// be a constant-expression. +ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction, +                                             SourceLocation &EqualLoc) { +  assert((Tok.is(tok::equal) || Tok.is(tok::l_brace)) +         && "Data member initializer not starting with '=' or '{'"); + +  if (Tok.is(tok::equal)) { +    EqualLoc = ConsumeToken(); +    if (Tok.is(tok::kw_delete)) { +      // In principle, an initializer of '= delete p;' is legal, but it will +      // never type-check. It's better to diagnose it as an ill-formed expression +      // than as an ill-formed deleted non-function member. +      // An initializer of '= delete p, foo' will never be parsed, because +      // a top-level comma always ends the initializer expression. +      const Token &Next = NextToken(); +      if (IsFunction || Next.is(tok::semi) || Next.is(tok::comma) || +           Next.is(tok::eof)) { +        if (IsFunction) +          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration) +            << 1 /* delete */; +        else +          Diag(ConsumeToken(), diag::err_deleted_non_function); +        return ExprResult(); +      } +    } else if (Tok.is(tok::kw_default)) { +      Diag(ConsumeToken(), diag::err_default_special_members); +      if (IsFunction) +        Diag(Tok, diag::err_default_delete_in_multiple_declaration) +          << 0 /* default */; +      else +        Diag(ConsumeToken(), diag::err_default_special_members); +      return ExprResult(); +    } + +    return ParseInitializer(); +  } else +    return ExprError(Diag(Tok, diag::err_generalized_initializer_lists)); +} +  /// ParseCXXMemberSpecification - Parse the class definition.  ///  ///       member-specification: @@ -1839,6 +2085,12 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,      while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) {        // Each iteration of this loop reads one member-declaration. +      if (getLang().Microsoft && (Tok.is(tok::kw___if_exists) || +          Tok.is(tok::kw___if_not_exists))) { +        ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); +        continue; +      } +        // Check for extraneous top-level semicolon.        if (Tok.is(tok::semi)) {          Diag(Tok, diag::ext_extra_struct_semi) @@ -1882,19 +2134,20 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,                                                LBraceLoc, RBraceLoc,                                                attrs.getList()); -  // C++ 9.2p2: Within the class member-specification, the class is regarded as -  // complete within function bodies, default arguments, -  // exception-specifications, and constructor ctor-initializers (including -  // such things in nested classes). +  // C++0x [class.mem]p2: Within the class member-specification, the class is +  // regarded as complete within function bodies, default arguments, exception- +  // specifications, and brace-or-equal-initializers for non-static data +  // members (including such things in nested classes).    // -  // FIXME: Only function bodies and constructor ctor-initializers are -  // parsed correctly, fix the rest. +  // FIXME: Only function bodies and brace-or-equal-initializers are currently +  // handled. Fix the others!    if (TagDecl && NonNestedClass) {      // We are not inside a nested class. This class and its nested classes      // are complete and we can parse the delayed portions of method      // declarations and the lexed inline method definitions.      SourceLocation SavedPrevTokLocation = PrevTokLocation;      ParseLexedMethodDeclarations(getCurrentClass()); +    ParseLexedMemberInitializers(getCurrentClass());      ParseLexedMethodDefs(getCurrentClass());      PrevTokLocation = SavedPrevTokLocation;    } @@ -1982,6 +2235,7 @@ void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {  ///  /// [C++] mem-initializer:  ///         mem-initializer-id '(' expression-list[opt] ')' +/// [C++0x] mem-initializer-id braced-init-list  ///  /// [C++] mem-initializer-id:  ///         '::'[opt] nested-name-specifier[opt] class-name @@ -2012,31 +2266,37 @@ Parser::MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {    SourceLocation IdLoc = ConsumeToken();    // Parse the '('. -  if (Tok.isNot(tok::l_paren)) { -    Diag(Tok, diag::err_expected_lparen); +  if (getLang().CPlusPlus0x && Tok.is(tok::l_brace)) { +    // FIXME: Do something with the braced-init-list. +    ParseBraceInitializer();      return true; -  } -  SourceLocation LParenLoc = ConsumeParen(); +  } else if(Tok.is(tok::l_paren)) { +    SourceLocation LParenLoc = ConsumeParen(); -  // Parse the optional expression-list. -  ExprVector ArgExprs(Actions); -  CommaLocsTy CommaLocs; -  if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { -    SkipUntil(tok::r_paren); -    return true; -  } +    // Parse the optional expression-list. +    ExprVector ArgExprs(Actions); +    CommaLocsTy CommaLocs; +    if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) { +      SkipUntil(tok::r_paren); +      return true; +    } -  SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); +    SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); -  SourceLocation EllipsisLoc; -  if (Tok.is(tok::ellipsis)) -    EllipsisLoc = ConsumeToken(); -   -  return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, -                                     TemplateTypeTy, IdLoc, -                                     LParenLoc, ArgExprs.take(), -                                     ArgExprs.size(), RParenLoc, -                                     EllipsisLoc); +    SourceLocation EllipsisLoc; +    if (Tok.is(tok::ellipsis)) +      EllipsisLoc = ConsumeToken(); + +    return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II, +                                       TemplateTypeTy, IdLoc, +                                       LParenLoc, ArgExprs.take(), +                                       ArgExprs.size(), RParenLoc, +                                       EllipsisLoc); +  } + +  Diag(Tok, getLang().CPlusPlus0x ? diag::err_expected_lparen_or_lbrace +                                  : diag::err_expected_lparen); +  return true;  }  /// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). @@ -2438,3 +2698,64 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,      ExpectAndConsume(tok::r_square, diag::err_expected_rsquare);    }  } + +void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, +                                                    AccessSpecifier& CurAS) { +  bool Result; +  if (ParseMicrosoftIfExistsCondition(Result)) +    return; +   +  if (Tok.isNot(tok::l_brace)) { +    Diag(Tok, diag::err_expected_lbrace); +    return; +  } +  ConsumeBrace(); + +  // Condition is false skip all inside the {}. +  if (!Result) { +    SkipUntil(tok::r_brace, false); +    return; +  } + +  // Condition is true, parse the declaration. +  while (Tok.isNot(tok::r_brace)) { + +    // __if_exists, __if_not_exists can nest. +    if ((Tok.is(tok::kw___if_exists) || Tok.is(tok::kw___if_not_exists))) { +      ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); +      continue; +    } + +    // Check for extraneous top-level semicolon. +    if (Tok.is(tok::semi)) { +      Diag(Tok, diag::ext_extra_struct_semi) +        << DeclSpec::getSpecifierName((DeclSpec::TST)TagType) +        << FixItHint::CreateRemoval(Tok.getLocation()); +      ConsumeToken(); +      continue; +    } + +    AccessSpecifier AS = getAccessSpecifierIfPresent(); +    if (AS != AS_none) { +      // Current token is a C++ access specifier. +      CurAS = AS; +      SourceLocation ASLoc = Tok.getLocation(); +      ConsumeToken(); +      if (Tok.is(tok::colon)) +        Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); +      else +        Diag(Tok, diag::err_expected_colon); +      ConsumeToken(); +      continue; +    } + +    // Parse all the comma separated declarators. +    ParseCXXClassMemberDeclaration(CurAS); +  } + +  if (Tok.isNot(tok::r_brace)) { +    Diag(Tok, diag::err_expected_rbrace); +    return; +  } +  ConsumeBrace(); +}  | 
