//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the C++ Declaration portions of the Parser interfaces.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/Attributes.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/ParsedTemplate.h"
#include "clang/Sema/PrettyDeclStackTrace.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/ADT/SmallString.h"

using namespace clang;

/// ParseNamespace - We know that the current token is a namespace keyword. This
/// may either be a top level namespace or a block-level namespace alias. If
/// there was an inline keyword, it has already been parsed.
///
///       namespace-definition: [C++ 7.3: basic.namespace]
///         named-namespace-definition
///         unnamed-namespace-definition
///
///       unnamed-namespace-definition:
///         'inline'[opt] 'namespace' attributes[opt] '{' namespace-body '}'
///
///       named-namespace-definition:
///         original-namespace-definition
///         extension-namespace-definition
///
///       original-namespace-definition:
///         'inline'[opt] 'namespace' identifier attributes[opt]
///             '{' namespace-body '}'
///
///       extension-namespace-definition:
///         'inline'[opt] 'namespace' original-namespace-name
///             '{' namespace-body '}'
///
///       namespace-alias-definition:  [C++ 7.3.2: namespace.alias]
///         'namespace' identifier '=' qualified-namespace-specifier ';'
///
Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context,
                                              SourceLocation &DeclEnd,
                                              SourceLocation InlineLoc) {
  assert(Tok.is(tok::kw_namespace) && "Not a namespace!");
  SourceLocation NamespaceLoc = ConsumeToken();  // eat the 'namespace'.
  ObjCDeclContextSwitch ObjCDC(*this);
    
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteNamespaceDecl(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  SourceLocation IdentLoc;
  IdentifierInfo *Ident = nullptr;
  std::vector<SourceLocation> ExtraIdentLoc;
  std::vector<IdentifierInfo*> ExtraIdent;
  std::vector<SourceLocation> ExtraNamespaceLoc;

  ParsedAttributesWithRange attrs(AttrFactory);
  SourceLocation attrLoc;
  if (getLangOpts().CPlusPlus11 && isCXX11AttributeSpecifier()) {
    if (!getLangOpts().CPlusPlus1z)
      Diag(Tok.getLocation(), diag::warn_cxx14_compat_attribute)
          << 0 /*namespace*/;
    attrLoc = Tok.getLocation();
    ParseCXX11Attributes(attrs);
  }

  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());
    }
  }

  // A nested namespace definition cannot have attributes.
  if (!ExtraNamespaceLoc.empty() && attrLoc.isValid())
    Diag(attrLoc, diag::err_unexpected_nested_namespace_attribute);

  // Read label attributes, if present.
  if (Tok.is(tok::kw___attribute)) {
    attrLoc = Tok.getLocation();
    ParseGNUAttributes(attrs);
  }

  if (Tok.is(tok::equal)) {
    if (!Ident) {
      Diag(Tok, diag::err_expected) << tok::identifier;
      // Skip to end of the definition and eat the ';'.
      SkipUntil(tok::semi);
      return nullptr;
    }
    if (attrLoc.isValid())
      Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias);
    if (InlineLoc.isValid())
      Diag(InlineLoc, diag::err_inline_namespace_alias)
          << FixItHint::CreateRemoval(InlineLoc);
    Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd);
    return Actions.ConvertDeclToDeclGroup(NSAlias);
}

  BalancedDelimiterTracker T(*this, tok::l_brace);
  if (T.consumeOpen()) {
    if (Ident)
      Diag(Tok, diag::err_expected) << tok::l_brace;
    else
      Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace;
    return nullptr;
  }

  if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || 
      getCurScope()->isInObjcMethodScope() || getCurScope()->getBlockParent() || 
      getCurScope()->getFnParent()) {
    Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope);
    SkipUntil(tok::r_brace);
    return nullptr;
  }

  if (ExtraIdent.empty()) {
    // Normal namespace definition, not a nested-namespace-definition.
  } else if (InlineLoc.isValid()) {
    Diag(InlineLoc, diag::err_inline_nested_namespace_definition);
  } else if (getLangOpts().CPlusPlus1z) {
    Diag(ExtraNamespaceLoc[0],
         diag::warn_cxx14_compat_nested_namespace_definition);
  } else {
    TentativeParsingAction TPA(*this);
    SkipUntil(tok::r_brace, StopBeforeMatch);
    Token rBraceToken = Tok;
    TPA.Revert();

    if (!rBraceToken.is(tok::r_brace)) {
      Diag(ExtraNamespaceLoc[0], diag::ext_nested_namespace_definition)
          << 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::ext_nested_namespace_definition)
          << 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 (InlineLoc.isValid())
    Diag(InlineLoc, getLangOpts().CPlusPlus11 ?
         diag::warn_cxx98_compat_inline_namespace : diag::ext_inline_namespace);

  // Enter a scope for the namespace.
  ParseScope NamespaceScope(this, Scope::DeclScope);

  UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
  Decl *NamespcDecl =
    Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc,
                                   IdentLoc, Ident, T.getOpenLocation(), 
                                   attrs.getList(), ImplicitUsingDirectiveDecl);

  PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc,
                                      "parsing namespace");

  // Parse the contents of the namespace.  This includes parsing recovery on 
  // any improperly nested namespaces.
  ParseInnerNamespace(ExtraIdentLoc, ExtraIdent, ExtraNamespaceLoc, 0,
                      InlineLoc, attrs, T);

  // Leave the namespace scope.
  NamespaceScope.Exit();

  DeclEnd = T.getCloseLocation();
  Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd);
  
  return Actions.ConvertDeclToDeclGroup(NamespcDecl, 
                                        ImplicitUsingDirectiveDecl);
}

/// 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,
                                 ParsedAttributes &attrs,
                                 BalancedDelimiterTracker &Tracker) {
  if (index == Ident.size()) {
    while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
           Tok.isNot(tok::eof)) {
      ParsedAttributesWithRange attrs(AttrFactory);
      MaybeParseCXX11Attributes(attrs);
      ParseExternalDeclaration(attrs);
    }

    // The caller is what called check -- we are simply calling
    // the close for it.
    Tracker.consumeClose();

    return;
  }

  // Handle a nested namespace definition.
  // FIXME: Preserve the source information through to the AST rather than
  // desugaring it here.
  ParseScope NamespaceScope(this, Scope::DeclScope);
  UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
  Decl *NamespcDecl =
    Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(),
                                   NamespaceLoc[index], IdentLoc[index],
                                   Ident[index], Tracker.getOpenLocation(), 
                                   attrs.getList(), ImplicitUsingDirectiveDecl);
  assert(!ImplicitUsingDirectiveDecl && 
         "nested namespace definition cannot define anonymous namespace");

  ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc,
                      attrs, Tracker);

  NamespaceScope.Exit();
  Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation());
}

/// ParseNamespaceAlias - Parse the part after the '=' in a namespace
/// alias definition.
///
Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc,
                                  SourceLocation AliasLoc,
                                  IdentifierInfo *Alias,
                                  SourceLocation &DeclEnd) {
  assert(Tok.is(tok::equal) && "Not equal token");

  ConsumeToken(); // eat the '='.

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteNamespaceAliasDecl(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  CXXScopeSpec SS;
  // Parse (optional) nested-name-specifier.
  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
                                 /*MayBePseudoDestructor=*/nullptr,
                                 /*IsTypename=*/false,
                                 /*LastII=*/nullptr,
                                 /*OnlyNamespace=*/true);

  if (Tok.isNot(tok::identifier)) {
    Diag(Tok, diag::err_expected_namespace_name);
    // Skip to end of the definition and eat the ';'.
    SkipUntil(tok::semi);
    return nullptr;
  }

  if (SS.isInvalid()) {
    // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
    // Skip to end of the definition and eat the ';'.
    SkipUntil(tok::semi);
    return nullptr;
  }

  // Parse identifier.
  IdentifierInfo *Ident = Tok.getIdentifierInfo();
  SourceLocation IdentLoc = ConsumeToken();

  // Eat the ';'.
  DeclEnd = Tok.getLocation();
  if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name))
    SkipUntil(tok::semi);

  return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc,
                                        Alias, SS, IdentLoc, Ident);
}

/// ParseLinkage - We know that the current token is a string_literal
/// and just before that, that extern was seen.
///
///       linkage-specification: [C++ 7.5p2: dcl.link]
///         'extern' string-literal '{' declaration-seq[opt] '}'
///         'extern' string-literal declaration
///
Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) {
  assert(isTokenStringLiteral() && "Not a string literal!");
  ExprResult Lang = ParseStringLiteralExpression(false);

  ParseScope LinkageScope(this, Scope::DeclScope);
  Decl *LinkageSpec =
      Lang.isInvalid()
          ? nullptr
          : Actions.ActOnStartLinkageSpecification(
                getCurScope(), DS.getSourceRange().getBegin(), Lang.get(),
                Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());

  ParsedAttributesWithRange attrs(AttrFactory);
  MaybeParseCXX11Attributes(attrs);

  if (Tok.isNot(tok::l_brace)) {
    // Reset the source range in DS, as the leading "extern"
    // does not really belong to the inner declaration ...
    DS.SetRangeStart(SourceLocation());
    DS.SetRangeEnd(SourceLocation());
    // ... but anyway remember that such an "extern" was seen.
    DS.setExternInLinkageSpec(true);
    ParseExternalDeclaration(attrs, &DS);
    return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
                             getCurScope(), LinkageSpec, SourceLocation())
                       : nullptr;
  }

  DS.abort();

  ProhibitAttributes(attrs);

  BalancedDelimiterTracker T(*this, tok::l_brace);
  T.consumeOpen();

  unsigned NestedModules = 0;
  while (true) {
    switch (Tok.getKind()) {
    case tok::annot_module_begin:
      ++NestedModules;
      ParseTopLevelDecl();
      continue;

    case tok::annot_module_end:
      if (!NestedModules)
        break;
      --NestedModules;
      ParseTopLevelDecl();
      continue;

    case tok::annot_module_include:
      ParseTopLevelDecl();
      continue;

    case tok::eof:
      break;

    case tok::r_brace:
      if (!NestedModules)
        break;
      // Fall through.
    default:
      ParsedAttributesWithRange attrs(AttrFactory);
      MaybeParseCXX11Attributes(attrs);
      ParseExternalDeclaration(attrs);
      continue;
    }

    break;
  }

  T.consumeClose();
  return LinkageSpec ? Actions.ActOnFinishLinkageSpecification(
                           getCurScope(), LinkageSpec, T.getCloseLocation())
                     : nullptr;
}

/// Parse a C++ Modules TS export-declaration.
///
///       export-declaration:
///         'export' declaration
///         'export' '{' declaration-seq[opt] '}'
///
Decl *Parser::ParseExportDeclaration() {
  assert(Tok.is(tok::kw_export));
  SourceLocation ExportLoc = ConsumeToken();

  ParseScope ExportScope(this, Scope::DeclScope);
  Decl *ExportDecl = Actions.ActOnStartExportDecl(
      getCurScope(), ExportLoc,
      Tok.is(tok::l_brace) ? Tok.getLocation() : SourceLocation());

  if (Tok.isNot(tok::l_brace)) {
    // FIXME: Factor out a ParseExternalDeclarationWithAttrs.
    ParsedAttributesWithRange Attrs(AttrFactory);
    MaybeParseCXX11Attributes(Attrs);
    MaybeParseMicrosoftAttributes(Attrs);
    ParseExternalDeclaration(Attrs);
    return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
                                         SourceLocation());
  }

  BalancedDelimiterTracker T(*this, tok::l_brace);
  T.consumeOpen();

  // The Modules TS draft says "An export-declaration shall declare at least one
  // entity", but the intent is that it shall contain at least one declaration.
  if (Tok.is(tok::r_brace))
    Diag(ExportLoc, diag::err_export_empty)
        << SourceRange(ExportLoc, Tok.getLocation());

  while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
         Tok.isNot(tok::eof)) {
    ParsedAttributesWithRange Attrs(AttrFactory);
    MaybeParseCXX11Attributes(Attrs);
    MaybeParseMicrosoftAttributes(Attrs);
    ParseExternalDeclaration(Attrs);
  }

  T.consumeClose();
  return Actions.ActOnFinishExportDecl(getCurScope(), ExportDecl,
                                       T.getCloseLocation());
}

/// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or
/// using-directive. Assumes that current token is 'using'.
Parser::DeclGroupPtrTy
Parser::ParseUsingDirectiveOrDeclaration(unsigned Context,
                                         const ParsedTemplateInfo &TemplateInfo,
                                         SourceLocation &DeclEnd,
                                         ParsedAttributesWithRange &attrs) {
  assert(Tok.is(tok::kw_using) && "Not using token");
  ObjCDeclContextSwitch ObjCDC(*this);
  
  // Eat 'using'.
  SourceLocation UsingLoc = ConsumeToken();

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteUsing(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  // 'using namespace' means this is a using-directive.
  if (Tok.is(tok::kw_namespace)) {
    // Template parameters are always an error here.
    if (TemplateInfo.Kind) {
      SourceRange R = TemplateInfo.getSourceRange();
      Diag(UsingLoc, diag::err_templated_using_directive_declaration)
        << 0 /* directive */ << R << FixItHint::CreateRemoval(R);
    }

    Decl *UsingDir = ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs);
    return Actions.ConvertDeclToDeclGroup(UsingDir);
  }

  // Otherwise, it must be a using-declaration or an alias-declaration.

  // Using declarations can't have attributes.
  ProhibitAttributes(attrs);

  return ParseUsingDeclaration(Context, TemplateInfo, UsingLoc, DeclEnd,
                               AS_none);
}

/// ParseUsingDirective - Parse C++ using-directive, assumes
/// that current token is 'namespace' and 'using' was already parsed.
///
///       using-directive: [C++ 7.3.p4: namespace.udir]
///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
///                 namespace-name ;
/// [GNU] using-directive:
///        'using' 'namespace' ::[opt] nested-name-specifier[opt]
///                 namespace-name attributes[opt] ;
///
Decl *Parser::ParseUsingDirective(unsigned Context,
                                  SourceLocation UsingLoc,
                                  SourceLocation &DeclEnd,
                                  ParsedAttributes &attrs) {
  assert(Tok.is(tok::kw_namespace) && "Not 'namespace' token");

  // Eat 'namespace'.
  SourceLocation NamespcLoc = ConsumeToken();

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteUsingDirective(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  CXXScopeSpec SS;
  // Parse (optional) nested-name-specifier.
  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false,
                                 /*MayBePseudoDestructor=*/nullptr,
                                 /*IsTypename=*/false,
                                 /*LastII=*/nullptr,
                                 /*OnlyNamespace=*/true);

  IdentifierInfo *NamespcName = nullptr;
  SourceLocation IdentLoc = SourceLocation();

  // Parse namespace-name.
  if (Tok.isNot(tok::identifier)) {
    Diag(Tok, diag::err_expected_namespace_name);
    // If there was invalid namespace name, skip to end of decl, and eat ';'.
    SkipUntil(tok::semi);
    // FIXME: Are there cases, when we would like to call ActOnUsingDirective?
    return nullptr;
  }

  if (SS.isInvalid()) {
    // Diagnostics have been emitted in ParseOptionalCXXScopeSpecifier.
    // Skip to end of the definition and eat the ';'.
    SkipUntil(tok::semi);
    return nullptr;
  }

  // Parse identifier.
  NamespcName = Tok.getIdentifierInfo();
  IdentLoc = ConsumeToken();

  // Parse (optional) attributes (most likely GNU strong-using extension).
  bool GNUAttr = false;
  if (Tok.is(tok::kw___attribute)) {
    GNUAttr = true;
    ParseGNUAttributes(attrs);
  }

  // Eat ';'.
  DeclEnd = Tok.getLocation();
  if (ExpectAndConsume(tok::semi,
                       GNUAttr ? diag::err_expected_semi_after_attribute_list
                               : diag::err_expected_semi_after_namespace_name))
    SkipUntil(tok::semi);

  return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS,
                                     IdentLoc, NamespcName, attrs.getList());
}

/// Parse a using-declarator (or the identifier in a C++11 alias-declaration).
///
///     using-declarator:
///       'typename'[opt] nested-name-specifier unqualified-id
///
bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) {
  D.clear();

  // Ignore optional 'typename'.
  // FIXME: This is wrong; we should parse this as a typename-specifier.
  TryConsumeToken(tok::kw_typename, D.TypenameLoc);

  if (Tok.is(tok::kw___super)) {
    Diag(Tok.getLocation(), diag::err_super_in_using_declaration);
    return true;
  }

  // Parse nested-name-specifier.
  IdentifierInfo *LastII = nullptr;
  ParseOptionalCXXScopeSpecifier(D.SS, nullptr, /*EnteringContext=*/false,
                                 /*MayBePseudoDtor=*/nullptr,
                                 /*IsTypename=*/false,
                                 /*LastII=*/&LastII);
  if (D.SS.isInvalid())
    return true;

  // Parse the unqualified-id. We allow parsing of both constructor and
  // destructor names and allow the action module to diagnose any semantic
  // errors.
  //
  // C++11 [class.qual]p2:
  //   [...] in a using-declaration that is a member-declaration, if the name
  //   specified after the nested-name-specifier is the same as the identifier
  //   or the simple-template-id's template-name in the last component of the
  //   nested-name-specifier, the name is [...] considered to name the
  //   constructor.
  if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext &&
      Tok.is(tok::identifier) &&
      (NextToken().is(tok::semi) || NextToken().is(tok::comma) ||
       NextToken().is(tok::ellipsis)) &&
      D.SS.isNotEmpty() && LastII == Tok.getIdentifierInfo() &&
      !D.SS.getScopeRep()->getAsNamespace() &&
      !D.SS.getScopeRep()->getAsNamespaceAlias()) {
    SourceLocation IdLoc = ConsumeToken();
    ParsedType Type =
        Actions.getInheritingConstructorName(D.SS, IdLoc, *LastII);
    D.Name.setConstructorName(Type, IdLoc, IdLoc);
  } else {
    if (ParseUnqualifiedId(
            D.SS, /*EnteringContext=*/false,
            /*AllowDestructorName=*/true,
            /*AllowConstructorName=*/!(Tok.is(tok::identifier) &&
                                       NextToken().is(tok::equal)),
            /*AllowDeductionGuide=*/false,
            nullptr, D.TemplateKWLoc, D.Name))
      return true;
  }

  if (TryConsumeToken(tok::ellipsis, D.EllipsisLoc))
    Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
         diag::warn_cxx1z_compat_using_declaration_pack :
         diag::ext_using_declaration_pack);

  return false;
}

/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration.
/// Assumes that 'using' was already seen.
///
///     using-declaration: [C++ 7.3.p3: namespace.udecl]
///       'using' using-declarator-list[opt] ;
///
///     using-declarator-list: [C++1z]
///       using-declarator '...'[opt]
///       using-declarator-list ',' using-declarator '...'[opt]
///
///     using-declarator-list: [C++98-14]
///       using-declarator
///
///     alias-declaration: C++11 [dcl.dcl]p1
///       'using' identifier attribute-specifier-seq[opt] = type-id ;
///
Parser::DeclGroupPtrTy
Parser::ParseUsingDeclaration(unsigned Context,
                              const ParsedTemplateInfo &TemplateInfo,
                              SourceLocation UsingLoc, SourceLocation &DeclEnd,
                              AccessSpecifier AS) {
  // Check for misplaced attributes before the identifier in an
  // alias-declaration.
  ParsedAttributesWithRange MisplacedAttrs(AttrFactory);
  MaybeParseCXX11Attributes(MisplacedAttrs);

  UsingDeclarator D;
  bool InvalidDeclarator = ParseUsingDeclarator(Context, D);

  ParsedAttributesWithRange Attrs(AttrFactory);
  MaybeParseGNUAttributes(Attrs);
  MaybeParseCXX11Attributes(Attrs);

  // Maybe this is an alias-declaration.
  if (Tok.is(tok::equal)) {
    if (InvalidDeclarator) {
      SkipUntil(tok::semi);
      return nullptr;
    }

    // If we had any misplaced attributes from earlier, this is where they
    // should have been written.
    if (MisplacedAttrs.Range.isValid()) {
      Diag(MisplacedAttrs.Range.getBegin(), diag::err_attributes_not_allowed)
        << FixItHint::CreateInsertionFromRange(
               Tok.getLocation(),
               CharSourceRange::getTokenRange(MisplacedAttrs.Range))
        << FixItHint::CreateRemoval(MisplacedAttrs.Range);
      Attrs.takeAllFrom(MisplacedAttrs);
    }

    Decl *DeclFromDeclSpec = nullptr;
    Decl *AD = ParseAliasDeclarationAfterDeclarator(
        TemplateInfo, UsingLoc, D, DeclEnd, AS, Attrs, &DeclFromDeclSpec);
    return Actions.ConvertDeclToDeclGroup(AD, DeclFromDeclSpec);
  }

  // C++11 attributes are not allowed on a using-declaration, but GNU ones
  // are.
  ProhibitAttributes(MisplacedAttrs);
  ProhibitAttributes(Attrs);

  // Diagnose an attempt to declare a templated using-declaration.
  // In C++11, alias-declarations can be templates:
  //   template <...> using id = type;
  if (TemplateInfo.Kind) {
    SourceRange R = TemplateInfo.getSourceRange();
    Diag(UsingLoc, diag::err_templated_using_directive_declaration)
      << 1 /* declaration */ << R << FixItHint::CreateRemoval(R);

    // Unfortunately, we have to bail out instead of recovering by
    // ignoring the parameters, just in case the nested name specifier
    // depends on the parameters.
    return nullptr;
  }

  SmallVector<Decl *, 8> DeclsInGroup;
  while (true) {
    // Parse (optional) attributes (most likely GNU strong-using extension).
    MaybeParseGNUAttributes(Attrs);

    if (InvalidDeclarator)
      SkipUntil(tok::comma, tok::semi, StopBeforeMatch);
    else {
      // "typename" keyword is allowed for identifiers only,
      // because it may be a type definition.
      if (D.TypenameLoc.isValid() &&
          D.Name.getKind() != UnqualifiedId::IK_Identifier) {
        Diag(D.Name.getSourceRange().getBegin(),
             diag::err_typename_identifiers_only)
            << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc));
        // Proceed parsing, but discard the typename keyword.
        D.TypenameLoc = SourceLocation();
      }

      Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc,
                                               D.TypenameLoc, D.SS, D.Name,
                                               D.EllipsisLoc, Attrs.getList());
      if (UD)
        DeclsInGroup.push_back(UD);
    }

    if (!TryConsumeToken(tok::comma))
      break;

    // Parse another using-declarator.
    Attrs.clear();
    InvalidDeclarator = ParseUsingDeclarator(Context, D);
  }

  if (DeclsInGroup.size() > 1)
    Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z ?
         diag::warn_cxx1z_compat_multi_using_declaration :
         diag::ext_multi_using_declaration);

  // Eat ';'.
  DeclEnd = Tok.getLocation();
  if (ExpectAndConsume(tok::semi, diag::err_expected_after,
                       !Attrs.empty() ? "attributes list"
                                      : "using declaration"))
    SkipUntil(tok::semi);

  return Actions.BuildDeclaratorGroup(DeclsInGroup);
}

Decl *Parser::ParseAliasDeclarationAfterDeclarator(
    const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc,
    UsingDeclarator &D, SourceLocation &DeclEnd, AccessSpecifier AS,
    ParsedAttributes &Attrs, Decl **OwnedType) {
  if (ExpectAndConsume(tok::equal)) {
    SkipUntil(tok::semi);
    return nullptr;
  }

  Diag(Tok.getLocation(), getLangOpts().CPlusPlus11 ?
       diag::warn_cxx98_compat_alias_declaration :
       diag::ext_alias_declaration);

  // Type alias templates cannot be specialized.
  int SpecKind = -1;
  if (TemplateInfo.Kind == ParsedTemplateInfo::Template &&
      D.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(D.Name.TemplateId->LAngleLoc,
                          D.Name.TemplateId->RAngleLoc);
    else
      Range = TemplateInfo.getSourceRange();
    Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
      << SpecKind << Range;
    SkipUntil(tok::semi);
    return nullptr;
  }

  // Name must be an identifier.
  if (D.Name.getKind() != UnqualifiedId::IK_Identifier) {
    Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier);
    // No removal fixit: can't recover from this.
    SkipUntil(tok::semi);
    return nullptr;
  } else if (D.TypenameLoc.isValid())
    Diag(D.TypenameLoc, diag::err_alias_declaration_not_identifier)
        << FixItHint::CreateRemoval(SourceRange(
               D.TypenameLoc,
               D.SS.isNotEmpty() ? D.SS.getEndLoc() : D.TypenameLoc));
  else if (D.SS.isNotEmpty())
    Diag(D.SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
      << FixItHint::CreateRemoval(D.SS.getRange());
  if (D.EllipsisLoc.isValid())
    Diag(D.EllipsisLoc, diag::err_alias_declaration_pack_expansion)
      << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc));

  Decl *DeclFromDeclSpec = nullptr;
  TypeResult TypeAlias =
      ParseTypeName(nullptr,
                    TemplateInfo.Kind ? Declarator::AliasTemplateContext
                                      : Declarator::AliasDeclContext,
                    AS, &DeclFromDeclSpec, &Attrs);
  if (OwnedType)
    *OwnedType = DeclFromDeclSpec;

  // Eat ';'.
  DeclEnd = Tok.getLocation();
  if (ExpectAndConsume(tok::semi, diag::err_expected_after,
                       !Attrs.empty() ? "attributes list"
                                      : "alias declaration"))
    SkipUntil(tok::semi);

  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
  MultiTemplateParamsArg TemplateParamsArg(
    TemplateParams ? TemplateParams->data() : nullptr,
    TemplateParams ? TemplateParams->size() : 0);
  return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
                                       UsingLoc, D.Name, Attrs.getList(),
                                       TypeAlias, DeclFromDeclSpec);
}

/// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration.
///
/// [C++0x] static_assert-declaration:
///           static_assert ( constant-expression  ,  string-literal  ) ;
///
/// [C11]   static_assert-declaration:
///           _Static_assert ( constant-expression  ,  string-literal  ) ;
///
Decl *Parser::ParseStaticAssertDeclaration(SourceLocation &DeclEnd){
  assert(Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert) &&
         "Not a static_assert declaration");

  if (Tok.is(tok::kw__Static_assert) && !getLangOpts().C11)
    Diag(Tok, diag::ext_c11_static_assert);
  if (Tok.is(tok::kw_static_assert))
    Diag(Tok, diag::warn_cxx98_compat_static_assert);

  SourceLocation StaticAssertLoc = ConsumeToken();

  BalancedDelimiterTracker T(*this, tok::l_paren);
  if (T.consumeOpen()) {
    Diag(Tok, diag::err_expected) << tok::l_paren;
    SkipMalformedDecl();
    return nullptr;
  }

  ExprResult AssertExpr(ParseConstantExpression());
  if (AssertExpr.isInvalid()) {
    SkipMalformedDecl();
    return nullptr;
  }

  ExprResult AssertMessage;
  if (Tok.is(tok::r_paren)) {
    Diag(Tok, getLangOpts().CPlusPlus1z
                  ? diag::warn_cxx14_compat_static_assert_no_message
                  : diag::ext_static_assert_no_message)
      << (getLangOpts().CPlusPlus1z
              ? FixItHint()
              : FixItHint::CreateInsertion(Tok.getLocation(), ", \"\""));
  } else {
    if (ExpectAndConsume(tok::comma)) {
      SkipUntil(tok::semi);
      return nullptr;
    }

    if (!isTokenStringLiteral()) {
      Diag(Tok, diag::err_expected_string_literal)
        << /*Source='static_assert'*/1;
      SkipMalformedDecl();
      return nullptr;
    }

    AssertMessage = ParseStringLiteralExpression();
    if (AssertMessage.isInvalid()) {
      SkipMalformedDecl();
      return nullptr;
    }
  }

  T.consumeClose();

  DeclEnd = Tok.getLocation();
  ExpectAndConsumeSemi(diag::err_expected_semi_after_static_assert);

  return Actions.ActOnStaticAssertDeclaration(StaticAssertLoc,
                                              AssertExpr.get(),
                                              AssertMessage.get(),
                                              T.getCloseLocation());
}

/// ParseDecltypeSpecifier - Parse a C++11 decltype specifier.
///
/// 'decltype' ( expression )
/// 'decltype' ( 'auto' )      [C++1y]
///
SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) {
  assert(Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)
           && "Not a decltype specifier");
  
  ExprResult Result;
  SourceLocation StartLoc = Tok.getLocation();
  SourceLocation EndLoc;

  if (Tok.is(tok::annot_decltype)) {
    Result = getExprAnnotation(Tok);
    EndLoc = Tok.getAnnotationEndLoc();
    ConsumeToken();
    if (Result.isInvalid()) {
      DS.SetTypeSpecError();
      return EndLoc;
    }
  } else {
    if (Tok.getIdentifierInfo()->isStr("decltype"))
      Diag(Tok, diag::warn_cxx98_compat_decltype);

    ConsumeToken();

    BalancedDelimiterTracker T(*this, tok::l_paren);
    if (T.expectAndConsume(diag::err_expected_lparen_after,
                           "decltype", tok::r_paren)) {
      DS.SetTypeSpecError();
      return T.getOpenLocation() == Tok.getLocation() ?
             StartLoc : T.getOpenLocation();
    }

    // Check for C++1y 'decltype(auto)'.
    if (Tok.is(tok::kw_auto)) {
      // No need to disambiguate here: an expression can't start with 'auto',
      // because the typename-specifier in a function-style cast operation can't
      // be 'auto'.
      Diag(Tok.getLocation(),
           getLangOpts().CPlusPlus14
             ? diag::warn_cxx11_compat_decltype_auto_type_specifier
             : diag::ext_decltype_auto_type_specifier);
      ConsumeToken();
    } else {
      // Parse the expression

      // C++11 [dcl.type.simple]p4:
      //   The operand of the decltype specifier is an unevaluated operand.
      EnterExpressionEvaluationContext Unevaluated(
          Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
          /*IsDecltype=*/true);
      Result =
          Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) {
            return E->hasPlaceholderType() ? ExprError() : E;
          });
      if (Result.isInvalid()) {
        DS.SetTypeSpecError();
        if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) {
          EndLoc = ConsumeParen();
        } else {
          if (PP.isBacktrackEnabled() && Tok.is(tok::semi)) {
            // Backtrack to get the location of the last token before the semi.
            PP.RevertCachedTokens(2);
            ConsumeToken(); // the semi.
            EndLoc = ConsumeAnyToken();
            assert(Tok.is(tok::semi));
          } else {
            EndLoc = Tok.getLocation();
          }
        }
        return EndLoc;
      }

      Result = Actions.ActOnDecltypeExpression(Result.get());
    }

    // Match the ')'
    T.consumeClose();
    if (T.getCloseLocation().isInvalid()) {
      DS.SetTypeSpecError();
      // FIXME: this should return the location of the last token
      //        that was consumed (by "consumeClose()")
      return T.getCloseLocation();
    }

    if (Result.isInvalid()) {
      DS.SetTypeSpecError();
      return T.getCloseLocation();
    }

    EndLoc = T.getCloseLocation();
  }
  assert(!Result.isInvalid());

  const char *PrevSpec = nullptr;
  unsigned DiagID;
  const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
  // Check for duplicate type specifiers (e.g. "int decltype(a)").
  if (Result.get()
        ? DS.SetTypeSpecType(DeclSpec::TST_decltype, StartLoc, PrevSpec,
                             DiagID, Result.get(), Policy)
        : DS.SetTypeSpecType(DeclSpec::TST_decltype_auto, StartLoc, PrevSpec,
                             DiagID, Policy)) {
    Diag(StartLoc, DiagID) << PrevSpec;
    DS.SetTypeSpecError();
  }
  return EndLoc;
}

void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec& DS, 
                                               SourceLocation StartLoc,
                                               SourceLocation EndLoc) {
  // make sure we have a token we can turn into an annotation token
  if (PP.isBacktrackEnabled())
    PP.RevertCachedTokens(1);
  else
    PP.EnterToken(Tok);

  Tok.setKind(tok::annot_decltype);
  setExprAnnotation(Tok,
                    DS.getTypeSpecType() == TST_decltype ? DS.getRepAsExpr() :
                    DS.getTypeSpecType() == TST_decltype_auto ? ExprResult() :
                    ExprError());
  Tok.setAnnotationEndLoc(EndLoc);
  Tok.setLocation(StartLoc);
  PP.AnnotateCachedTokens(Tok);
}

void Parser::ParseUnderlyingTypeSpecifier(DeclSpec &DS) {
  assert(Tok.is(tok::kw___underlying_type) &&
         "Not an underlying type specifier");

  SourceLocation StartLoc = ConsumeToken();
  BalancedDelimiterTracker T(*this, tok::l_paren);
  if (T.expectAndConsume(diag::err_expected_lparen_after,
                       "__underlying_type", tok::r_paren)) {
    return;
  }

  TypeResult Result = ParseTypeName();
  if (Result.isInvalid()) {
    SkipUntil(tok::r_paren, StopAtSemi);
    return;
  }

  // Match the ')'
  T.consumeClose();
  if (T.getCloseLocation().isInvalid())
    return;

  const char *PrevSpec = nullptr;
  unsigned DiagID;
  if (DS.SetTypeSpecType(DeclSpec::TST_underlyingType, StartLoc, PrevSpec,
                         DiagID, Result.get(),
                         Actions.getASTContext().getPrintingPolicy()))
    Diag(StartLoc, DiagID) << PrevSpec;
  DS.setTypeofParensRange(T.getRange());
}

/// ParseBaseTypeSpecifier - Parse a C++ base-type-specifier which is either a
/// class name or decltype-specifier. 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 either a type or null, depending on whether a type 
/// name was found.
///
///       base-type-specifier: [C++11 class.derived]
///         class-or-decltype
///       class-or-decltype: [C++11 class.derived]
///         nested-name-specifier[opt] class-name
///         decltype-specifier
///       class-name: [C++ class.name]
///         identifier
///         simple-template-id
///
/// In C++98, instead of base-type-specifier, we have:
///
///         ::[opt] nested-name-specifier[opt] class-name
TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc,
                                          SourceLocation &EndLocation) {
  // Ignore attempts to use typename
  if (Tok.is(tok::kw_typename)) {
    Diag(Tok, diag::err_expected_class_name_not_template)
      << FixItHint::CreateRemoval(Tok.getLocation());
    ConsumeToken();
  }

  // Parse optional nested-name-specifier
  CXXScopeSpec SS;
  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);

  BaseLoc = Tok.getLocation();

  // Parse decltype-specifier
  // tok == kw_decltype is just error recovery, it can only happen when SS 
  // isn't empty
  if (Tok.isOneOf(tok::kw_decltype, tok::annot_decltype)) {
    if (SS.isNotEmpty())
      Diag(SS.getBeginLoc(), diag::err_unexpected_scope_on_base_decltype)
        << FixItHint::CreateRemoval(SS.getRange());
    // Fake up a Declarator to use with ActOnTypeName.
    DeclSpec DS(AttrFactory);

    EndLocation = ParseDecltypeSpecifier(DS);

    Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
    return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
  }

  // Check whether we have a template-id that names a type.
  if (Tok.is(tok::annot_template_id)) {
    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
    if (TemplateId->Kind == TNK_Type_template ||
        TemplateId->Kind == TNK_Dependent_template_name) {
      AnnotateTemplateIdTokenAsType(/*IsClassName*/true);

      assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
      ParsedType Type = getTypeAnnotation(Tok);
      EndLocation = Tok.getAnnotationEndLoc();
      ConsumeToken();

      if (Type)
        return Type;
      return true;
    }

    // Fall through to produce an error below.
  }

  if (Tok.isNot(tok::identifier)) {
    Diag(Tok, diag::err_expected_class_name);
    return true;
  }

  IdentifierInfo *Id = Tok.getIdentifierInfo();
  SourceLocation IdLoc = ConsumeToken();

  if (Tok.is(tok::less)) {
    // It looks the user intended to write a template-id here, but the
    // template-name was wrong. Try to fix that.
    TemplateNameKind TNK = TNK_Type_template;
    TemplateTy Template;
    if (!Actions.DiagnoseUnknownTemplateName(*Id, IdLoc, getCurScope(),
                                             &SS, Template, TNK)) {
      Diag(IdLoc, diag::err_unknown_template_name)
        << Id;
    }

    if (!Template) {
      TemplateArgList TemplateArgs;
      SourceLocation LAngleLoc, RAngleLoc;
      ParseTemplateIdAfterTemplateName(nullptr, IdLoc, SS, true, LAngleLoc,
                                       TemplateArgs, RAngleLoc);
      return true;
    }

    // Form the template name
    UnqualifiedId TemplateName;
    TemplateName.setIdentifier(Id, IdLoc);

    // Parse the full template-id, then turn it into a type.
    if (AnnotateTemplateIdToken(Template, TNK, SS, SourceLocation(),
                                TemplateName))
      return true;
    if (TNK == TNK_Type_template || TNK == TNK_Dependent_template_name)
      AnnotateTemplateIdTokenAsType(/*IsClassName*/true);

    // If we didn't end up with a typename token, there's nothing more we
    // can do.
    if (Tok.isNot(tok::annot_typename))
      return true;

    // Retrieve the type from the annotation token, consume that token, and
    // return.
    EndLocation = Tok.getAnnotationEndLoc();
    ParsedType Type = getTypeAnnotation(Tok);
    ConsumeToken();
    return Type;
  }

  // We have an identifier; check whether it is actually a type.
  IdentifierInfo *CorrectedII = nullptr;
  ParsedType Type = Actions.getTypeName(
      *Id, IdLoc, getCurScope(), &SS, /*IsClassName=*/true, false, nullptr,
      /*IsCtorOrDtorName=*/false,
      /*NonTrivialTypeSourceInfo=*/true,
      /*IsClassTemplateDeductionContext*/ false, &CorrectedII);
  if (!Type) {
    Diag(IdLoc, diag::err_expected_class_name);
    return true;
  }

  // Consume the identifier.
  EndLocation = IdLoc;

  // Fake up a Declarator to use with ActOnTypeName.
  DeclSpec DS(AttrFactory);
  DS.SetRangeStart(IdLoc);
  DS.SetRangeEnd(EndLocation);
  DS.getTypeSpecScope() = SS;

  const char *PrevSpec = nullptr;
  unsigned DiagID;
  DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type,
                     Actions.getASTContext().getPrintingPolicy());

  Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
  return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
}

void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) {
  while (Tok.isOneOf(tok::kw___single_inheritance,
                     tok::kw___multiple_inheritance,
                     tok::kw___virtual_inheritance)) {
    IdentifierInfo *AttrName = Tok.getIdentifierInfo();
    SourceLocation AttrNameLoc = ConsumeToken();
    attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
                 AttributeList::AS_Keyword);
  }
}

/// Determine whether the following tokens are valid after a type-specifier
/// which could be a standalone declaration. This will conservatively return
/// true if there's any doubt, and is appropriate for insert-';' fixits.
bool Parser::isValidAfterTypeSpecifier(bool CouldBeBitfield) {
  // This switch enumerates the valid "follow" set for type-specifiers.
  switch (Tok.getKind()) {
  default: break;
  case tok::semi:               // struct foo {...} ;
  case tok::star:               // struct foo {...} *         P;
  case tok::amp:                // struct foo {...} &         R = ...
  case tok::ampamp:             // struct foo {...} &&        R = ...
  case tok::identifier:         // struct foo {...} V         ;
  case tok::r_paren:            //(struct foo {...} )         {4}
  case tok::annot_cxxscope:     // struct foo {...} a::       b;
  case tok::annot_typename:     // struct foo {...} a         ::b;
  case tok::annot_template_id:  // struct foo {...} a<int>    ::b;
  case tok::l_paren:            // struct foo {...} (         x);
  case tok::comma:              // __builtin_offsetof(struct foo{...} ,
  case tok::kw_operator:        // struct foo       operator  ++() {...}
  case tok::kw___declspec:      // struct foo {...} __declspec(...)
  case tok::l_square:           // void f(struct f  [         3])
  case tok::ellipsis:           // void f(struct f  ...       [Ns])
  // FIXME: we should emit semantic diagnostic when declaration
  // attribute is in type attribute position.
  case tok::kw___attribute:     // struct foo __attribute__((used)) x;
  case tok::annot_pragma_pack:  // struct foo {...} _Pragma(pack(pop));
  // struct foo {...} _Pragma(section(...));
  case tok::annot_pragma_ms_pragma:
  // struct foo {...} _Pragma(vtordisp(pop));
  case tok::annot_pragma_ms_vtordisp:
  // struct foo {...} _Pragma(pointers_to_members(...));
  case tok::annot_pragma_ms_pointers_to_members:
    return true;
  case tok::colon:
    return CouldBeBitfield;     // enum E { ... }   :         2;
  // Microsoft compatibility
  case tok::kw___cdecl:         // struct foo {...} __cdecl      x;
  case tok::kw___fastcall:      // struct foo {...} __fastcall   x;
  case tok::kw___stdcall:       // struct foo {...} __stdcall    x;
  case tok::kw___thiscall:      // struct foo {...} __thiscall   x;
  case tok::kw___vectorcall:    // struct foo {...} __vectorcall x;
    // We will diagnose these calling-convention specifiers on non-function
    // declarations later, so claim they are valid after a type specifier.
    return getLangOpts().MicrosoftExt;
  // Type qualifiers
  case tok::kw_const:           // struct foo {...} const     x;
  case tok::kw_volatile:        // struct foo {...} volatile  x;
  case tok::kw_restrict:        // struct foo {...} restrict  x;
  case tok::kw__Atomic:         // struct foo {...} _Atomic   x;
  case tok::kw___unaligned:     // struct foo {...} __unaligned *x;
  // Function specifiers
  // Note, no 'explicit'. An explicit function must be either a conversion
  // operator or a constructor. Either way, it can't have a return type.
  case tok::kw_inline:          // struct foo       inline    f();
  case tok::kw_virtual:         // struct foo       virtual   f();
  case tok::kw_friend:          // struct foo       friend    f();
  // Storage-class specifiers
  case tok::kw_static:          // struct foo {...} static    x;
  case tok::kw_extern:          // struct foo {...} extern    x;
  case tok::kw_typedef:         // struct foo {...} typedef   x;
  case tok::kw_register:        // struct foo {...} register  x;
  case tok::kw_auto:            // struct foo {...} auto      x;
  case tok::kw_mutable:         // struct foo {...} mutable   x;
  case tok::kw_thread_local:    // struct foo {...} thread_local x;
  case tok::kw_constexpr:       // struct foo {...} constexpr x;
    // As shown above, type qualifiers and storage class specifiers absolutely
    // can occur after class specifiers according to the grammar.  However,
    // almost no one actually writes code like this.  If we see one of these,
    // it is much more likely that someone missed a semi colon and the
    // type/storage class specifier we're seeing is part of the *next*
    // intended declaration, as in:
    //
    //   struct foo { ... }
    //   typedef int X;
    //
    // We'd really like to emit a missing semicolon error instead of emitting
    // an error on the 'int' saying that you can't have two type specifiers in
    // the same declaration of X.  Because of this, we look ahead past this
    // token to see if it's a type specifier.  If so, we know the code is
    // otherwise invalid, so we can produce the expected semi error.
    if (!isKnownToBeTypeSpecifier(NextToken()))
      return true;
    break;
  case tok::r_brace:  // struct bar { struct foo {...} }
    // Missing ';' at end of struct is accepted as an extension in C mode.
    if (!getLangOpts().CPlusPlus)
      return true;
    break;
  case tok::greater:
    // template<class T = class X>
    return getLangOpts().CPlusPlus;
  }
  return false;
}

/// ParseClassSpecifier - Parse a C++ class-specifier [C++ class] or
/// elaborated-type-specifier [C++ dcl.type.elab]; we can't tell which
/// until we reach the start of a definition or see a token that
/// cannot start a definition.
///
///       class-specifier: [C++ class]
///         class-head '{' member-specification[opt] '}'
///         class-head '{' member-specification[opt] '}' attributes[opt]
///       class-head:
///         class-key identifier[opt] base-clause[opt]
///         class-key nested-name-specifier identifier base-clause[opt]
///         class-key nested-name-specifier[opt] simple-template-id
///                          base-clause[opt]
/// [GNU]   class-key attributes[opt] identifier[opt] base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier
///                          identifier base-clause[opt]
/// [GNU]   class-key attributes[opt] nested-name-specifier[opt]
///                          simple-template-id base-clause[opt]
///       class-key:
///         'class'
///         'struct'
///         'union'
///
///       elaborated-type-specifier: [C++ dcl.type.elab]
///         class-key ::[opt] nested-name-specifier[opt] identifier
///         class-key ::[opt] nested-name-specifier[opt] 'template'[opt]
///                          simple-template-id
///
///  Note that the C++ class-specifier and elaborated-type-specifier,
///  together, subsume the C99 struct-or-union-specifier:
///
///       struct-or-union-specifier: [C99 6.7.2.1]
///         struct-or-union identifier[opt] '{' struct-contents '}'
///         struct-or-union identifier
/// [GNU]   struct-or-union attributes[opt] identifier[opt] '{' struct-contents
///                                                         '}' attributes[opt]
/// [GNU]   struct-or-union attributes[opt] identifier
///       struct-or-union:
///         'struct'
///         'union'
void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind,
                                 SourceLocation StartLoc, DeclSpec &DS,
                                 const ParsedTemplateInfo &TemplateInfo,
                                 AccessSpecifier AS, 
                                 bool EnteringContext, DeclSpecContext DSC, 
                                 ParsedAttributesWithRange &Attributes) {
  DeclSpec::TST TagType;
  if (TagTokKind == tok::kw_struct)
    TagType = DeclSpec::TST_struct;
  else if (TagTokKind == tok::kw___interface)
    TagType = DeclSpec::TST_interface;
  else if (TagTokKind == tok::kw_class)
    TagType = DeclSpec::TST_class;
  else {
    assert(TagTokKind == tok::kw_union && "Not a class specifier");
    TagType = DeclSpec::TST_union;
  }

  if (Tok.is(tok::code_completion)) {
    // Code completion for a struct, class, or union name.
    Actions.CodeCompleteTag(getCurScope(), TagType);
    return cutOffParsing();
  }

  // C++03 [temp.explicit] 14.7.2/8:
  //   The usual access checking rules do not apply to names used to specify
  //   explicit instantiations.
  //
  // As an extension we do not perform access checking on the names used to
  // specify explicit specializations either. This is important to allow
  // specializing traits classes for private types.
  //
  // Note that we don't suppress if this turns out to be an elaborated
  // type specifier.
  bool shouldDelayDiagsInTag =
    (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation ||
     TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization);
  SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag);

  ParsedAttributesWithRange attrs(AttrFactory);
  // If attributes exist after tag, parse them.
  MaybeParseGNUAttributes(attrs);
  MaybeParseMicrosoftDeclSpecs(attrs);

  // Parse inheritance specifiers.
  if (Tok.isOneOf(tok::kw___single_inheritance,
                  tok::kw___multiple_inheritance,
                  tok::kw___virtual_inheritance))
    ParseMicrosoftInheritanceClassAttributes(attrs);

  // If C++0x attributes exist here, parse them.
  // FIXME: Are we consistent with the ordering of parsing of different
  // styles of attributes?
  MaybeParseCXX11Attributes(attrs);

  // Source location used by FIXIT to insert misplaced
  // C++11 attributes
  SourceLocation AttrFixitLoc = Tok.getLocation();

  if (TagType == DeclSpec::TST_struct &&
      Tok.isNot(tok::identifier) &&
      !Tok.isAnnotation() &&
      Tok.getIdentifierInfo() &&
      Tok.isOneOf(tok::kw___is_abstract,
                  tok::kw___is_aggregate,
                  tok::kw___is_arithmetic,
                  tok::kw___is_array,
                  tok::kw___is_assignable,
                  tok::kw___is_base_of,
                  tok::kw___is_class,
                  tok::kw___is_complete_type,
                  tok::kw___is_compound,
                  tok::kw___is_const,
                  tok::kw___is_constructible,
                  tok::kw___is_convertible,
                  tok::kw___is_convertible_to,
                  tok::kw___is_destructible,
                  tok::kw___is_empty,
                  tok::kw___is_enum,
                  tok::kw___is_floating_point,
                  tok::kw___is_final,
                  tok::kw___is_function,
                  tok::kw___is_fundamental,
                  tok::kw___is_integral,
                  tok::kw___is_interface_class,
                  tok::kw___is_literal,
                  tok::kw___is_lvalue_expr,
                  tok::kw___is_lvalue_reference,
                  tok::kw___is_member_function_pointer,
                  tok::kw___is_member_object_pointer,
                  tok::kw___is_member_pointer,
                  tok::kw___is_nothrow_assignable,
                  tok::kw___is_nothrow_constructible,
                  tok::kw___is_nothrow_destructible,
                  tok::kw___is_object,
                  tok::kw___is_pod,
                  tok::kw___is_pointer,
                  tok::kw___is_polymorphic,
                  tok::kw___is_reference,
                  tok::kw___is_rvalue_expr,
                  tok::kw___is_rvalue_reference,
                  tok::kw___is_same,
                  tok::kw___is_scalar,
                  tok::kw___is_sealed,
                  tok::kw___is_signed,
                  tok::kw___is_standard_layout,
                  tok::kw___is_trivial,
                  tok::kw___is_trivially_assignable,
                  tok::kw___is_trivially_constructible,
                  tok::kw___is_trivially_copyable,
                  tok::kw___is_union,
                  tok::kw___is_unsigned,
                  tok::kw___is_void,
                  tok::kw___is_volatile))
    // GNU libstdc++ 4.2 and libc++ use certain intrinsic names as the
    // name of struct templates, but some are keywords in GCC >= 4.3
    // and Clang. Therefore, when we see the token sequence "struct
    // X", make X into a normal identifier rather than a keyword, to
    // allow libstdc++ 4.2 and libc++ to work properly.
    TryKeywordIdentFallback(true);

  struct PreserveAtomicIdentifierInfoRAII {
    PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled)
        : AtomicII(nullptr) {
      if (!Enabled)
        return;
      assert(Tok.is(tok::kw__Atomic));
      AtomicII = Tok.getIdentifierInfo();
      AtomicII->revertTokenIDToIdentifier();
      Tok.setKind(tok::identifier);
    }
    ~PreserveAtomicIdentifierInfoRAII() {
      if (!AtomicII)
        return;
      AtomicII->revertIdentifierToTokenID(tok::kw__Atomic);
    }
    IdentifierInfo *AtomicII;
  };

  // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
  // implementation for VS2013 uses _Atomic as an identifier for one of the
  // classes in <atomic>.  When we are parsing 'struct _Atomic', don't consider
  // '_Atomic' to be a keyword.  We are careful to undo this so that clang can
  // use '_Atomic' in its own header files.
  bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat &&
                                        Tok.is(tok::kw__Atomic) &&
                                        TagType == DeclSpec::TST_struct;
  PreserveAtomicIdentifierInfoRAII AtomicTokenGuard(
      Tok, ShouldChangeAtomicToIdentifier);

  // Parse the (optional) nested-name-specifier.
  CXXScopeSpec &SS = DS.getTypeSpecScope();
  if (getLangOpts().CPlusPlus) {
    // "FOO : BAR" is not a potential typo for "FOO::BAR".  In this context it
    // is a base-specifier-list.
    ColonProtectionRAIIObject X(*this);

    CXXScopeSpec Spec;
    bool HasValidSpec = true;
    if (ParseOptionalCXXScopeSpecifier(Spec, nullptr, EnteringContext)) {
      DS.SetTypeSpecError();
      HasValidSpec = false;
    }
    if (Spec.isSet())
      if (Tok.isNot(tok::identifier) && Tok.isNot(tok::annot_template_id)) {
        Diag(Tok, diag::err_expected) << tok::identifier;
        HasValidSpec = false;
      }
    if (HasValidSpec)
      SS = Spec;
  }

  TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;

  // Parse the (optional) class name or simple-template-id.
  IdentifierInfo *Name = nullptr;
  SourceLocation NameLoc;
  TemplateIdAnnotation *TemplateId = nullptr;
  if (Tok.is(tok::identifier)) {
    Name = Tok.getIdentifierInfo();
    NameLoc = ConsumeToken();

    if (Tok.is(tok::less) && getLangOpts().CPlusPlus) {
      // The name was supposed to refer to a template, but didn't.
      // Eat the template argument list and try to continue parsing this as
      // a class (or template thereof).
      TemplateArgList TemplateArgs;
      SourceLocation LAngleLoc, RAngleLoc;
      if (ParseTemplateIdAfterTemplateName(
              nullptr, NameLoc, SS, true, LAngleLoc, TemplateArgs, RAngleLoc)) {
        // We couldn't parse the template argument list at all, so don't
        // try to give any location information for the list.
        LAngleLoc = RAngleLoc = SourceLocation();
      }

      Diag(NameLoc, diag::err_explicit_spec_non_template)
          << (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
          << TagTokKind << Name << SourceRange(LAngleLoc, RAngleLoc);

      // Strip off the last template parameter list if it was empty, since
      // we've removed its template argument list.
      if (TemplateParams && TemplateInfo.LastParameterListWasEmpty) {
        if (TemplateParams->size() > 1) {
          TemplateParams->pop_back();
        } else {
          TemplateParams = nullptr;
          const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
            = ParsedTemplateInfo::NonTemplate;
        }
      } else if (TemplateInfo.Kind
                                == ParsedTemplateInfo::ExplicitInstantiation) {
        // Pretend this is just a forward declaration.
        TemplateParams = nullptr;
        const_cast<ParsedTemplateInfo&>(TemplateInfo).Kind
          = ParsedTemplateInfo::NonTemplate;
        const_cast<ParsedTemplateInfo&>(TemplateInfo).TemplateLoc
          = SourceLocation();
        const_cast<ParsedTemplateInfo&>(TemplateInfo).ExternLoc
          = SourceLocation();
      }
    }
  } else if (Tok.is(tok::annot_template_id)) {
    TemplateId = takeTemplateIdAnnotation(Tok);
    NameLoc = ConsumeToken();

    if (TemplateId->Kind != TNK_Type_template &&
        TemplateId->Kind != TNK_Dependent_template_name) {
      // The template-name in the simple-template-id refers to
      // something other than a class template. Give an appropriate
      // error message and skip to the ';'.
      SourceRange Range(NameLoc);
      if (SS.isNotEmpty())
        Range.setBegin(SS.getBeginLoc());

      // FIXME: Name may be null here.
      Diag(TemplateId->LAngleLoc, diag::err_template_spec_syntax_non_template)
        << TemplateId->Name << static_cast<int>(TemplateId->Kind) << Range;

      DS.SetTypeSpecError();
      SkipUntil(tok::semi, StopBeforeMatch);
      return;
    }
  }

  // There are four options here.
  //  - If we are in a trailing return type, this is always just a reference,
  //    and we must not try to parse a definition. For instance,
  //      [] () -> struct S { };
  //    does not define a type.
  //  - If we have 'struct foo {...', 'struct foo :...',
  //    'struct foo final :' or 'struct foo final {', then this is a definition.
  //  - If we have 'struct foo;', then this is either a forward declaration
  //    or a friend declaration, which have to be treated differently.
  //  - Otherwise we have something like 'struct foo xyz', a reference.
  //
  //  We also detect these erroneous cases to provide better diagnostic for
  //  C++11 attributes parsing.
  //  - attributes follow class name:
  //    struct foo [[]] {};
  //  - attributes appear before or after 'final':
  //    struct foo [[]] final [[]] {};
  //
  // However, in type-specifier-seq's, things look like declarations but are
  // just references, e.g.
  //   new struct s;
  // or
  //   &T::operator struct s;
  // For these, DSC is DSC_type_specifier or DSC_alias_declaration.

  // If there are attributes after class name, parse them.
  MaybeParseCXX11Attributes(Attributes);

  const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy();
  Sema::TagUseKind TUK;
  if (DSC == DSC_trailing)
    TUK = Sema::TUK_Reference;
  else if (Tok.is(tok::l_brace) ||
           (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
           (isCXX11FinalKeyword() &&
            (NextToken().is(tok::l_brace) || NextToken().is(tok::colon)))) {
    if (DS.isFriendSpecified()) {
      // C++ [class.friend]p2:
      //   A class shall not be defined in a friend declaration.
      Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
        << SourceRange(DS.getFriendSpecLoc());

      // Skip everything up to the semicolon, so that this looks like a proper
      // friend class (or template thereof) declaration.
      SkipUntil(tok::semi, StopBeforeMatch);
      TUK = Sema::TUK_Friend;
    } else {
      // Okay, this is a class definition.
      TUK = Sema::TUK_Definition;
    }
  } else if (isCXX11FinalKeyword() && (NextToken().is(tok::l_square) ||
                                       NextToken().is(tok::kw_alignas))) {
    // We can't tell if this is a definition or reference
    // until we skipped the 'final' and C++11 attribute specifiers.
    TentativeParsingAction PA(*this);

    // Skip the 'final' keyword.
    ConsumeToken();

    // Skip C++11 attribute specifiers.
    while (true) {
      if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
        ConsumeBracket();
        if (!SkipUntil(tok::r_square, StopAtSemi))
          break;
      } else if (Tok.is(tok::kw_alignas) && NextToken().is(tok::l_paren)) {
        ConsumeToken();
        ConsumeParen();
        if (!SkipUntil(tok::r_paren, StopAtSemi))
          break;
      } else {
        break;
      }
    }

    if (Tok.isOneOf(tok::l_brace, tok::colon))
      TUK = Sema::TUK_Definition;
    else
      TUK = Sema::TUK_Reference;

    PA.Revert();
  } else if (!isTypeSpecifier(DSC) &&
             (Tok.is(tok::semi) ||
              (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier(false)))) {
    TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
    if (Tok.isNot(tok::semi)) {
      const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
      // A semicolon was missing after this declaration. Diagnose and recover.
      ExpectAndConsume(tok::semi, diag::err_expected_after,
                       DeclSpec::getSpecifierName(TagType, PPol));
      PP.EnterToken(Tok);
      Tok.setKind(tok::semi);
    }
  } else
    TUK = Sema::TUK_Reference;

  // Forbid misplaced attributes. In cases of a reference, we pass attributes
  // to caller to handle.
  if (TUK != Sema::TUK_Reference) {
    // If this is not a reference, then the only possible
    // valid place for C++11 attributes to appear here
    // is between class-key and class-name. If there are
    // any attributes after class-name, we try a fixit to move
    // them to the right place.
    SourceRange AttrRange = Attributes.Range;
    if (AttrRange.isValid()) {
      Diag(AttrRange.getBegin(), diag::err_attributes_not_allowed)
        << AttrRange
        << FixItHint::CreateInsertionFromRange(AttrFixitLoc,
                                               CharSourceRange(AttrRange, true))
        << FixItHint::CreateRemoval(AttrRange);

      // Recover by adding misplaced attributes to the attribute list
      // of the class so they can be applied on the class later.
      attrs.takeAllFrom(Attributes);
    }
  }

  // If this is an elaborated type specifier, and we delayed
  // diagnostics before, just merge them into the current pool.
  if (shouldDelayDiagsInTag) {
    diagsFromTag.done();
    if (TUK == Sema::TUK_Reference)
      diagsFromTag.redelay();
  }

  if (!Name && !TemplateId && (DS.getTypeSpecType() == DeclSpec::TST_error ||
                               TUK != Sema::TUK_Definition)) {
    if (DS.getTypeSpecType() != DeclSpec::TST_error) {
      // We have a declaration or reference to an anonymous class.
      Diag(StartLoc, diag::err_anon_type_definition)
        << DeclSpec::getSpecifierName(TagType, Policy);
    }

    // If we are parsing a definition and stop at a base-clause, continue on
    // until the semicolon.  Continuing from the comma will just trick us into
    // thinking we are seeing a variable declaration.
    if (TUK == Sema::TUK_Definition && Tok.is(tok::colon))
      SkipUntil(tok::semi, StopBeforeMatch);
    else
      SkipUntil(tok::comma, StopAtSemi);
    return;
  }

  // Create the tag portion of the class or class template.
  DeclResult TagOrTempResult = true; // invalid
  TypeResult TypeResult = true; // invalid

  bool Owned = false;
  Sema::SkipBodyInfo SkipBody;
  if (TemplateId) {
    // Explicit specialization, class template partial specialization,
    // or explicit instantiation.
    ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
                                       TemplateId->NumArgs);
    if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
        TUK == Sema::TUK_Declaration) {
      // This is an explicit instantiation of a class template.
      ProhibitAttributes(attrs);

      TagOrTempResult
        = Actions.ActOnExplicitInstantiation(getCurScope(),
                                             TemplateInfo.ExternLoc,
                                             TemplateInfo.TemplateLoc,
                                             TagType,
                                             StartLoc,
                                             SS,
                                             TemplateId->Template,
                                             TemplateId->TemplateNameLoc,
                                             TemplateId->LAngleLoc,
                                             TemplateArgsPtr,
                                             TemplateId->RAngleLoc,
                                             attrs.getList());

    // Friend template-ids are treated as references unless
    // they have template headers, in which case they're ill-formed
    // (FIXME: "template <class T> friend class A<T>::B<int>;").
    // We diagnose this error in ActOnClassTemplateSpecialization.
    } else if (TUK == Sema::TUK_Reference ||
               (TUK == Sema::TUK_Friend &&
                TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) {
      ProhibitAttributes(attrs);
      TypeResult = Actions.ActOnTagTemplateIdType(TUK, TagType, StartLoc,
                                                  TemplateId->SS,
                                                  TemplateId->TemplateKWLoc,
                                                  TemplateId->Template,
                                                  TemplateId->TemplateNameLoc,
                                                  TemplateId->LAngleLoc,
                                                  TemplateArgsPtr,
                                                  TemplateId->RAngleLoc);
    } else {
      // This is an explicit specialization or a class template
      // partial specialization.
      TemplateParameterLists FakedParamLists;
      if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
        // This looks like an explicit instantiation, because we have
        // something like
        //
        //   template class Foo<X>
        //
        // but it actually has a definition. Most likely, this was
        // meant to be an explicit specialization, but the user forgot
        // the '<>' after 'template'.
        // It this is friend declaration however, since it cannot have a
        // template header, it is most likely that the user meant to
        // remove the 'template' keyword.
        assert((TUK == Sema::TUK_Definition || TUK == Sema::TUK_Friend) &&
               "Expected a definition here");

        if (TUK == Sema::TUK_Friend) {
          Diag(DS.getFriendSpecLoc(), diag::err_friend_explicit_instantiation);
          TemplateParams = nullptr;
        } else {
          SourceLocation LAngleLoc =
              PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
          Diag(TemplateId->TemplateNameLoc,
               diag::err_explicit_instantiation_with_definition)
              << SourceRange(TemplateInfo.TemplateLoc)
              << FixItHint::CreateInsertion(LAngleLoc, "<>");

          // Create a fake template parameter list that contains only
          // "template<>", so that we treat this construct as a class
          // template specialization.
          FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
              0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None,
              LAngleLoc, nullptr));
          TemplateParams = &FakedParamLists;
        }
      }

      // Build the class template specialization.
      TagOrTempResult = Actions.ActOnClassTemplateSpecialization(
          getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(),
          *TemplateId, attrs.getList(),
          MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0]
                                                : nullptr,
                                 TemplateParams ? TemplateParams->size() : 0),
          &SkipBody);
    }
  } else if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation &&
             TUK == Sema::TUK_Declaration) {
    // Explicit instantiation of a member of a class template
    // specialization, e.g.,
    //
    //   template struct Outer<int>::Inner;
    //
    ProhibitAttributes(attrs);

    TagOrTempResult
      = Actions.ActOnExplicitInstantiation(getCurScope(),
                                           TemplateInfo.ExternLoc,
                                           TemplateInfo.TemplateLoc,
                                           TagType, StartLoc, SS, Name,
                                           NameLoc, attrs.getList());
  } else if (TUK == Sema::TUK_Friend &&
             TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) {
    ProhibitAttributes(attrs);

    TagOrTempResult =
      Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(),
                                      TagType, StartLoc, SS,
                                      Name, NameLoc, attrs.getList(),
                                      MultiTemplateParamsArg(
                                    TemplateParams? &(*TemplateParams)[0]
                                                  : nullptr,
                                 TemplateParams? TemplateParams->size() : 0));
  } else {
    if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition)
      ProhibitAttributes(attrs);

    if (TUK == Sema::TUK_Definition &&
        TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
      // If the declarator-id is not a template-id, issue a diagnostic and
      // recover by ignoring the 'template' keyword.
      Diag(Tok, diag::err_template_defn_explicit_instantiation)
        << 1 << FixItHint::CreateRemoval(TemplateInfo.TemplateLoc);
      TemplateParams = nullptr;
    }

    bool IsDependent = false;

    // Don't pass down template parameter lists if this is just a tag
    // reference.  For example, we don't need the template parameters here:
    //   template <class T> class A *makeA(T t);
    MultiTemplateParamsArg TParams;
    if (TUK != Sema::TUK_Reference && TemplateParams)
      TParams =
        MultiTemplateParamsArg(&(*TemplateParams)[0], TemplateParams->size());

    stripTypeAttributesOffDeclSpec(attrs, DS, TUK);

    // Declaration or definition of a class type
    TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
                                       SS, Name, NameLoc, attrs.getList(), AS,
                                       DS.getModulePrivateSpecLoc(),
                                       TParams, Owned, IsDependent,
                                       SourceLocation(), false,
                                       clang::TypeResult(),
                                       DSC == DSC_type_specifier,
                                       &SkipBody);

    // If ActOnTag said the type was dependent, try again with the
    // less common call.
    if (IsDependent) {
      assert(TUK == Sema::TUK_Reference || TUK == Sema::TUK_Friend);
      TypeResult = Actions.ActOnDependentTag(getCurScope(), TagType, TUK,
                                             SS, Name, StartLoc, NameLoc);
    }
  }

  // If there is a body, parse it and inform the actions module.
  if (TUK == Sema::TUK_Definition) {
    assert(Tok.is(tok::l_brace) ||
           (getLangOpts().CPlusPlus && Tok.is(tok::colon)) ||
           isCXX11FinalKeyword());
    if (SkipBody.ShouldSkip)
      SkipCXXMemberSpecification(StartLoc, AttrFixitLoc, TagType,
                                 TagOrTempResult.get());
    else if (getLangOpts().CPlusPlus)
      ParseCXXMemberSpecification(StartLoc, AttrFixitLoc, attrs, TagType,
                                  TagOrTempResult.get());
    else
      ParseStructUnionBody(StartLoc, TagType, TagOrTempResult.get());
  }

  if (!TagOrTempResult.isInvalid())
    // Delayed proccessing of attributes.
    Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList());

  const char *PrevSpec = nullptr;
  unsigned DiagID;
  bool Result;
  if (!TypeResult.isInvalid()) {
    Result = DS.SetTypeSpecType(DeclSpec::TST_typename, StartLoc,
                                NameLoc.isValid() ? NameLoc : StartLoc,
                                PrevSpec, DiagID, TypeResult.get(), Policy);
  } else if (!TagOrTempResult.isInvalid()) {
    Result = DS.SetTypeSpecType(TagType, StartLoc,
                                NameLoc.isValid() ? NameLoc : StartLoc,
                                PrevSpec, DiagID, TagOrTempResult.get(), Owned,
                                Policy);
  } else {
    DS.SetTypeSpecError();
    return;
  }

  if (Result)
    Diag(StartLoc, DiagID) << PrevSpec;

  // At this point, we've successfully parsed a class-specifier in 'definition'
  // form (e.g. "struct foo { int x; }".  While we could just return here, we're
  // going to look at what comes after it to improve error recovery.  If an
  // impossible token occurs next, we assume that the programmer forgot a ; at
  // the end of the declaration and recover that way.
  //
  // Also enforce C++ [temp]p3:
  //   In a template-declaration which defines a class, no declarator
  //   is permitted.
  //
  // After a type-specifier, we don't expect a semicolon. This only happens in
  // C, since definitions are not permitted in this context in C++.
  if (TUK == Sema::TUK_Definition &&
      (getLangOpts().CPlusPlus || !isTypeSpecifier(DSC)) &&
      (TemplateInfo.Kind || !isValidAfterTypeSpecifier(false))) {
    if (Tok.isNot(tok::semi)) {
      const PrintingPolicy &PPol = Actions.getASTContext().getPrintingPolicy();
      ExpectAndConsume(tok::semi, diag::err_expected_after,
                       DeclSpec::getSpecifierName(TagType, PPol));
      // Push this token back into the preprocessor and change our current token
      // to ';' so that the rest of the code recovers as though there were an
      // ';' after the definition.
      PP.EnterToken(Tok);
      Tok.setKind(tok::semi);
    }
  }
}

/// ParseBaseClause - Parse the base-clause of a C++ class [C++ class.derived].
///
///       base-clause : [C++ class.derived]
///         ':' base-specifier-list
///       base-specifier-list:
///         base-specifier '...'[opt]
///         base-specifier-list ',' base-specifier '...'[opt]
void Parser::ParseBaseClause(Decl *ClassDecl) {
  assert(Tok.is(tok::colon) && "Not a base clause");
  ConsumeToken();

  // Build up an array of parsed base specifiers.
  SmallVector<CXXBaseSpecifier *, 8> BaseInfo;

  while (true) {
    // Parse a base-specifier.
    BaseResult Result = ParseBaseSpecifier(ClassDecl);
    if (Result.isInvalid()) {
      // Skip the rest of this base specifier, up until the comma or
      // opening brace.
      SkipUntil(tok::comma, tok::l_brace, StopAtSemi | StopBeforeMatch);
    } else {
      // Add this to our array of base specifiers.
      BaseInfo.push_back(Result.get());
    }

    // If the next token is a comma, consume it and keep reading
    // base-specifiers.
    if (!TryConsumeToken(tok::comma))
      break;
  }

  // Attach the base specifiers
  Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo);
}

/// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is
/// one entry in the base class list of a class specifier, for example:
///    class foo : public bar, virtual private baz {
/// 'public bar' and 'virtual private baz' are each base-specifiers.
///
///       base-specifier: [C++ class.derived]
///         attribute-specifier-seq[opt] base-type-specifier
///         attribute-specifier-seq[opt] 'virtual' access-specifier[opt]
///                 base-type-specifier
///         attribute-specifier-seq[opt] access-specifier 'virtual'[opt]
///                 base-type-specifier
BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) {
  bool IsVirtual = false;
  SourceLocation StartLoc = Tok.getLocation();

  ParsedAttributesWithRange Attributes(AttrFactory);
  MaybeParseCXX11Attributes(Attributes);

  // Parse the 'virtual' keyword.
  if (TryConsumeToken(tok::kw_virtual))
    IsVirtual = true;

  CheckMisplacedCXX11Attribute(Attributes, StartLoc);

  // Parse an (optional) access specifier.
  AccessSpecifier Access = getAccessSpecifierIfPresent();
  if (Access != AS_none)
    ConsumeToken();

  CheckMisplacedCXX11Attribute(Attributes, StartLoc);

  // Parse the 'virtual' keyword (again!), in case it came after the
  // access specifier.
  if (Tok.is(tok::kw_virtual))  {
    SourceLocation VirtualLoc = ConsumeToken();
    if (IsVirtual) {
      // Complain about duplicate 'virtual'
      Diag(VirtualLoc, diag::err_dup_virtual)
        << FixItHint::CreateRemoval(VirtualLoc);
    }

    IsVirtual = true;
  }

  CheckMisplacedCXX11Attribute(Attributes, StartLoc);

  // Parse the class-name.

  // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL
  // implementation for VS2013 uses _Atomic as an identifier for one of the
  // classes in <atomic>.  Treat '_Atomic' to be an identifier when we are
  // parsing the class-name for a base specifier.
  if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) &&
      NextToken().is(tok::less))
    Tok.setKind(tok::identifier);

  SourceLocation EndLocation;
  SourceLocation BaseLoc;
  TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation);
  if (BaseType.isInvalid())
    return true;

  // Parse the optional ellipsis (for a pack expansion). The ellipsis is 
  // actually part of the base-specifier-list grammar productions, but we
  // parse it here for convenience.
  SourceLocation EllipsisLoc;
  TryConsumeToken(tok::ellipsis, EllipsisLoc);

  // Find the complete source range for the base-specifier.
  SourceRange Range(StartLoc, EndLocation);

  // Notify semantic analysis that we have parsed a complete
  // base-specifier.
  return Actions.ActOnBaseSpecifier(ClassDecl, Range, Attributes, IsVirtual,
                                    Access, BaseType.get(), BaseLoc,
                                    EllipsisLoc);
}

/// getAccessSpecifierIfPresent - Determine whether the next token is
/// a C++ access-specifier.
///
///       access-specifier: [C++ class.derived]
///         'private'
///         'protected'
///         'public'
AccessSpecifier Parser::getAccessSpecifierIfPresent() const {
  switch (Tok.getKind()) {
  default: return AS_none;
  case tok::kw_private: return AS_private;
  case tok::kw_protected: return AS_protected;
  case tok::kw_public: return AS_public;
  }
}

/// \brief If the given declarator has any parts for which parsing has to be
/// delayed, e.g., default arguments or an exception-specification, create a
/// late-parsed method declaration record to handle the parsing at the end of
/// the class definition.
void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo,
                                            Decl *ThisDecl) {
  DeclaratorChunk::FunctionTypeInfo &FTI
    = DeclaratorInfo.getFunctionTypeInfo();
  // If there was a late-parsed exception-specification, we'll need a
  // late parse
  bool NeedLateParse = FTI.getExceptionSpecType() == EST_Unparsed;

  if (!NeedLateParse) {
    // Look ahead to see if there are any default args
    for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx) {
      auto Param = cast<ParmVarDecl>(FTI.Params[ParamIdx].Param);
      if (Param->hasUnparsedDefaultArg()) {
        NeedLateParse = true;
        break;
      }
    }
  }

  if (NeedLateParse) {
    // Push this method onto the stack of late-parsed method
    // declarations.
    auto LateMethod = new LateParsedMethodDeclaration(this, ThisDecl);
    getCurrentClass().LateParsedDeclarations.push_back(LateMethod);
    LateMethod->TemplateScope = getCurScope()->isTemplateParamScope();

    // Stash the exception-specification tokens in the late-pased method.
    LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens;
    FTI.ExceptionSpecTokens = nullptr;

    // Push tokens for each parameter.  Those that do not have
    // defaults will be NULL.
    LateMethod->DefaultArgs.reserve(FTI.NumParams);
    for (unsigned ParamIdx = 0; ParamIdx < FTI.NumParams; ++ParamIdx)
      LateMethod->DefaultArgs.push_back(LateParsedDefaultArgument(
          FTI.Params[ParamIdx].Param,
          std::move(FTI.Params[ParamIdx].DefaultArgTokens)));
  }
}

/// isCXX11VirtSpecifier - Determine whether the given token is a C++11
/// virt-specifier.
///
///       virt-specifier:
///         override
///         final
///         __final
VirtSpecifiers::Specifier Parser::isCXX11VirtSpecifier(const Token &Tok) const {
  if (!getLangOpts().CPlusPlus || Tok.isNot(tok::identifier))
    return VirtSpecifiers::VS_None;

  IdentifierInfo *II = Tok.getIdentifierInfo();

  // Initialize the contextual keywords.
  if (!Ident_final) {
    Ident_final = &PP.getIdentifierTable().get("final");
    if (getLangOpts().GNUKeywords)
      Ident_GNU_final = &PP.getIdentifierTable().get("__final");
    if (getLangOpts().MicrosoftExt)
      Ident_sealed = &PP.getIdentifierTable().get("sealed");
    Ident_override = &PP.getIdentifierTable().get("override");
  }

  if (II == Ident_override)
    return VirtSpecifiers::VS_Override;

  if (II == Ident_sealed)
    return VirtSpecifiers::VS_Sealed;

  if (II == Ident_final)
    return VirtSpecifiers::VS_Final;

  if (II == Ident_GNU_final)
    return VirtSpecifiers::VS_GNU_Final;

  return VirtSpecifiers::VS_None;
}

/// ParseOptionalCXX11VirtSpecifierSeq - Parse a virt-specifier-seq.
///
///       virt-specifier-seq:
///         virt-specifier
///         virt-specifier-seq virt-specifier
void Parser::ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS,
                                                bool IsInterface,
                                                SourceLocation FriendLoc) {
  while (true) {
    VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
    if (Specifier == VirtSpecifiers::VS_None)
      return;

    if (FriendLoc.isValid()) {
      Diag(Tok.getLocation(), diag::err_friend_decl_spec)
        << VirtSpecifiers::getSpecifierName(Specifier)
        << FixItHint::CreateRemoval(Tok.getLocation())
        << SourceRange(FriendLoc, FriendLoc);
      ConsumeToken();
      continue;
    }

    // C++ [class.mem]p8:
    //   A virt-specifier-seq shall contain at most one of each virt-specifier.
    const char *PrevSpec = nullptr;
    if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
      Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
        << PrevSpec
        << FixItHint::CreateRemoval(Tok.getLocation());

    if (IsInterface && (Specifier == VirtSpecifiers::VS_Final ||
                        Specifier == VirtSpecifiers::VS_Sealed)) {
      Diag(Tok.getLocation(), diag::err_override_control_interface)
        << VirtSpecifiers::getSpecifierName(Specifier);
    } else if (Specifier == VirtSpecifiers::VS_Sealed) {
      Diag(Tok.getLocation(), diag::ext_ms_sealed_keyword);
    } else if (Specifier == VirtSpecifiers::VS_GNU_Final) {
      Diag(Tok.getLocation(), diag::ext_warn_gnu_final);
    } else {
      Diag(Tok.getLocation(),
           getLangOpts().CPlusPlus11
               ? diag::warn_cxx98_compat_override_control_keyword
               : diag::ext_override_control_keyword)
          << VirtSpecifiers::getSpecifierName(Specifier);
    }
    ConsumeToken();
  }
}

/// isCXX11FinalKeyword - Determine whether the next token is a C++11
/// 'final' or Microsoft 'sealed' contextual keyword.
bool Parser::isCXX11FinalKeyword() const {
  VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier();
  return Specifier == VirtSpecifiers::VS_Final ||
         Specifier == VirtSpecifiers::VS_GNU_Final || 
         Specifier == VirtSpecifiers::VS_Sealed;
}

/// \brief Parse a C++ member-declarator up to, but not including, the optional
/// brace-or-equal-initializer or pure-specifier.
bool Parser::ParseCXXMemberDeclaratorBeforeInitializer(
    Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize,
    LateParsedAttrList &LateParsedAttrs) {
  // member-declarator:
  //   declarator pure-specifier[opt]
  //   declarator brace-or-equal-initializer[opt]
  //   identifier[opt] ':' constant-expression
  if (Tok.isNot(tok::colon))
    ParseDeclarator(DeclaratorInfo);
  else
    DeclaratorInfo.SetIdentifier(nullptr, Tok.getLocation());

  if (!DeclaratorInfo.isFunctionDeclarator() && TryConsumeToken(tok::colon)) {
    assert(DeclaratorInfo.isPastIdentifier() &&
           "don't know where identifier would go yet?");
    BitfieldSize = ParseConstantExpression();
    if (BitfieldSize.isInvalid())
      SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
  } else {
    ParseOptionalCXX11VirtSpecifierSeq(
        VS, getCurrentClass().IsInterface,
        DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
    if (!VS.isUnset())
      MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
  }

  // If a simple-asm-expr is present, parse it.
  if (Tok.is(tok::kw_asm)) {
    SourceLocation Loc;
    ExprResult AsmLabel(ParseSimpleAsm(&Loc));
    if (AsmLabel.isInvalid())
      SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);

    DeclaratorInfo.setAsmLabel(AsmLabel.get());
    DeclaratorInfo.SetRangeEnd(Loc);
  }

  // If attributes exist after the declarator, but before an '{', parse them.
  MaybeParseGNUAttributes(DeclaratorInfo, &LateParsedAttrs);

  // For compatibility with code written to older Clang, also accept a
  // virt-specifier *after* the GNU attributes.
  if (BitfieldSize.isUnset() && VS.isUnset()) {
    ParseOptionalCXX11VirtSpecifierSeq(
        VS, getCurrentClass().IsInterface,
        DeclaratorInfo.getDeclSpec().getFriendSpecLoc());
    if (!VS.isUnset()) {
      // If we saw any GNU-style attributes that are known to GCC followed by a
      // virt-specifier, issue a GCC-compat warning.
      const AttributeList *Attr = DeclaratorInfo.getAttributes();
      while (Attr) {
        if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute())
          Diag(Attr->getLoc(), diag::warn_gcc_attribute_location);
        Attr = Attr->getNext();
      }
      MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS);
    }
  }

  // If this has neither a name nor a bit width, something has gone seriously
  // wrong. Skip until the semi-colon or }.
  if (!DeclaratorInfo.hasName() && BitfieldSize.isUnset()) {
    // If so, skip until the semi-colon or a }.
    SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
    return true;
  }
  return false;
}

/// \brief Look for declaration specifiers possibly occurring after C++11
/// virt-specifier-seq and diagnose them.
void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(
    Declarator &D,
    VirtSpecifiers &VS) {
  DeclSpec DS(AttrFactory);

  // GNU-style and C++11 attributes are not allowed here, but they will be
  // handled by the caller.  Diagnose everything else.
  ParseTypeQualifierListOpt(
      DS, AR_NoAttributesParsed, false,
      /*IdentifierRequired=*/false, llvm::function_ref<void()>([&]() {
        Actions.CodeCompleteFunctionQualifiers(DS, D, &VS);
      }));
  D.ExtendWithDeclSpec(DS);

  if (D.isFunctionDeclarator()) {
    auto &Function = D.getFunctionTypeInfo();
    if (DS.getTypeQualifiers() != DeclSpec::TQ_unspecified) {
      auto DeclSpecCheck = [&] (DeclSpec::TQ TypeQual,
                                const char *FixItName,
                                SourceLocation SpecLoc,
                                unsigned* QualifierLoc) {
        FixItHint Insertion;
        if (DS.getTypeQualifiers() & TypeQual) {
          if (!(Function.TypeQuals & TypeQual)) {
            std::string Name(FixItName);
            Name += " ";
            Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
            Function.TypeQuals |= TypeQual;
            *QualifierLoc = SpecLoc.getRawEncoding();
          }
          Diag(SpecLoc, diag::err_declspec_after_virtspec)
            << FixItName
            << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
            << FixItHint::CreateRemoval(SpecLoc)
            << Insertion;
        }
      };
      DeclSpecCheck(DeclSpec::TQ_const, "const", DS.getConstSpecLoc(),
                    &Function.ConstQualifierLoc);
      DeclSpecCheck(DeclSpec::TQ_volatile, "volatile", DS.getVolatileSpecLoc(),
                    &Function.VolatileQualifierLoc);
      DeclSpecCheck(DeclSpec::TQ_restrict, "restrict", DS.getRestrictSpecLoc(),
                    &Function.RestrictQualifierLoc);
    }

    // Parse ref-qualifiers.
    bool RefQualifierIsLValueRef = true;
    SourceLocation RefQualifierLoc;
    if (ParseRefQualifier(RefQualifierIsLValueRef, RefQualifierLoc)) {
      const char *Name = (RefQualifierIsLValueRef ? "& " : "&& ");
      FixItHint Insertion = FixItHint::CreateInsertion(VS.getFirstLocation(), Name);
      Function.RefQualifierIsLValueRef = RefQualifierIsLValueRef;
      Function.RefQualifierLoc = RefQualifierLoc.getRawEncoding();

      Diag(RefQualifierLoc, diag::err_declspec_after_virtspec)
        << (RefQualifierIsLValueRef ? "&" : "&&")
        << VirtSpecifiers::getSpecifierName(VS.getLastSpecifier())
        << FixItHint::CreateRemoval(RefQualifierLoc)
        << Insertion;
      D.SetRangeEnd(RefQualifierLoc);
    }
  }
}

/// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
///
///       member-declaration:
///         decl-specifier-seq[opt] member-declarator-list[opt] ';'
///         function-definition ';'[opt]
///         ::[opt] nested-name-specifier template[opt] unqualified-id ';'[TODO]
///         using-declaration                                            [TODO]
/// [C++0x] static_assert-declaration
///         template-declaration
/// [GNU]   '__extension__' member-declaration
///
///       member-declarator-list:
///         member-declarator
///         member-declarator-list ',' member-declarator
///
///       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:
///         virt-specifier
///         virt-specifier-seq virt-specifier
///
///       virt-specifier:
///         override
///         final
/// [MS]    sealed
/// 
///       pure-specifier:
///         '= 0'
///
///       constant-initializer:
///         '=' constant-expression
///
Parser::DeclGroupPtrTy
Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
                                       AttributeList *AccessAttrs,
                                       const ParsedTemplateInfo &TemplateInfo,
                                       ParsingDeclRAIIObject *TemplateDiags) {
  if (Tok.is(tok::at)) {
    if (getLangOpts().ObjC1 && NextToken().isObjCAtKeyword(tok::objc_defs))
      Diag(Tok, diag::err_at_defs_cxx);
    else
      Diag(Tok, diag::err_at_in_class);

    ConsumeToken();
    SkipUntil(tok::r_brace, StopAtSemi);
    return nullptr;
  }

  // Turn on colon protection early, while parsing declspec, although there is
  // nothing to protect there. It prevents from false errors if error recovery
  // incorrectly determines where the declspec ends, as in the example:
  //   struct A { enum class B { C }; };
  //   const int C = 4;
  //   struct D { A::B : C; };
  ColonProtectionRAIIObject X(*this);

  // Access declarations.
  bool MalformedTypeSpec = false;
  if (!TemplateInfo.Kind &&
      Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw___super)) {
    if (TryAnnotateCXXScopeToken())
      MalformedTypeSpec = true;

    bool isAccessDecl;
    if (Tok.isNot(tok::annot_cxxscope))
      isAccessDecl = false;
    else if (NextToken().is(tok::identifier))
      isAccessDecl = GetLookAheadToken(2).is(tok::semi);
    else
      isAccessDecl = NextToken().is(tok::kw_operator);

    if (isAccessDecl) {
      // Collect the scope specifier token we annotated earlier.
      CXXScopeSpec SS;
      ParseOptionalCXXScopeSpecifier(SS, nullptr,
                                     /*EnteringContext=*/false);

      if (SS.isInvalid()) {
        SkipUntil(tok::semi);
        return nullptr;
      }

      // Try to parse an unqualified-id.
      SourceLocation TemplateKWLoc;
      UnqualifiedId Name;
      if (ParseUnqualifiedId(SS, false, true, true, false, nullptr,
                             TemplateKWLoc, Name)) {
        SkipUntil(tok::semi);
        return nullptr;
      }

      // TODO: recover from mistakenly-qualified operator declarations.
      if (ExpectAndConsume(tok::semi, diag::err_expected_after,
                           "access declaration")) {
        SkipUntil(tok::semi);
        return nullptr;
      }

      return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration(
          getCurScope(), AS, /*UsingLoc*/ SourceLocation(),
          /*TypenameLoc*/ SourceLocation(), SS, Name,
          /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr)));
    }
  }

  // static_assert-declaration. A templated static_assert declaration is
  // diagnosed in Parser::ParseSingleDeclarationAfterTemplate.
  if (!TemplateInfo.Kind &&
      Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
    SourceLocation DeclEnd;
    return DeclGroupPtrTy::make(
        DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd)));
  }

  if (Tok.is(tok::kw_template)) {
    assert(!TemplateInfo.TemplateParams &&
           "Nested template improperly parsed?");
    ObjCDeclContextSwitch ObjCDC(*this);
    SourceLocation DeclEnd;
    return DeclGroupPtrTy::make(
        DeclGroupRef(ParseTemplateDeclarationOrSpecialization(
            Declarator::MemberContext, DeclEnd, AS, AccessAttrs)));
  }

  // Handle:  member-declaration ::= '__extension__' member-declaration
  if (Tok.is(tok::kw___extension__)) {
    // __extension__ silences extension warnings in the subexpression.
    ExtensionRAIIObject O(Diags);  // Use RAII to do this.
    ConsumeToken();
    return ParseCXXClassMemberDeclaration(AS, AccessAttrs,
                                          TemplateInfo, TemplateDiags);
  }

  ParsedAttributesWithRange attrs(AttrFactory);
  ParsedAttributesWithRange FnAttrs(AttrFactory);
  // Optional C++11 attribute-specifier
  MaybeParseCXX11Attributes(attrs);
  // We need to keep these attributes for future diagnostic
  // before they are taken over by declaration specifier.
  FnAttrs.addAll(attrs.getList());
  FnAttrs.Range = attrs.Range;

  MaybeParseMicrosoftAttributes(attrs);

  if (Tok.is(tok::kw_using)) {
    ProhibitAttributes(attrs);

    // Eat 'using'.
    SourceLocation UsingLoc = ConsumeToken();

    if (Tok.is(tok::kw_namespace)) {
      Diag(UsingLoc, diag::err_using_namespace_in_class);
      SkipUntil(tok::semi, StopBeforeMatch);
      return nullptr;
    }
    SourceLocation DeclEnd;
    // Otherwise, it must be a using-declaration or an alias-declaration.
    return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
                                 UsingLoc, DeclEnd, AS);
  }

  // Hold late-parsed attributes so we can attach a Decl to them later.
  LateParsedAttrList CommonLateParsedAttrs;

  // decl-specifier-seq:
  // Parse the common declaration-specifiers piece.
  ParsingDeclSpec DS(*this, TemplateDiags);
  DS.takeAttributesFrom(attrs);
  if (MalformedTypeSpec)
    DS.SetTypeSpecError();

  ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class,
                             &CommonLateParsedAttrs);

  // Turn off colon protection that was set for declspec.
  X.restore();

  // If we had a free-standing type definition with a missing semicolon, we
  // may get this far before the problem becomes obvious.
  if (DS.hasTagDefinition() &&
      TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate &&
      DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class,
                                            &CommonLateParsedAttrs))
    return nullptr;

  MultiTemplateParamsArg TemplateParams(
      TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data()
                                 : nullptr,
      TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->size() : 0);

  if (TryConsumeToken(tok::semi)) {
    if (DS.isFriendSpecified())
      ProhibitAttributes(FnAttrs);

    RecordDecl *AnonRecord = nullptr;
    Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(
        getCurScope(), AS, DS, TemplateParams, false, AnonRecord);
    DS.complete(TheDecl);
    if (AnonRecord) {
      Decl* decls[] = {AnonRecord, TheDecl};
      return Actions.BuildDeclaratorGroup(decls);
    }
    return Actions.ConvertDeclToDeclGroup(TheDecl);
  }

  ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext);
  VirtSpecifiers VS;

  // Hold late-parsed attributes so we can attach a Decl to them later.
  LateParsedAttrList LateParsedAttrs;

  SourceLocation EqualLoc;
  SourceLocation PureSpecLoc;

  auto TryConsumePureSpecifier = [&] (bool AllowDefinition) {
    if (Tok.isNot(tok::equal))
      return false;

    auto &Zero = NextToken();
    SmallString<8> Buffer;
    if (Zero.isNot(tok::numeric_constant) || Zero.getLength() != 1 ||
        PP.getSpelling(Zero, Buffer) != "0")
      return false;

    auto &After = GetLookAheadToken(2);
    if (!After.isOneOf(tok::semi, tok::comma) &&
        !(AllowDefinition &&
          After.isOneOf(tok::l_brace, tok::colon, tok::kw_try)))
      return false;

    EqualLoc = ConsumeToken();
    PureSpecLoc = ConsumeToken();
    return true;
  };

  SmallVector<Decl *, 8> DeclsInGroup;
  ExprResult BitfieldSize;
  bool ExpectSemi = true;

  // Parse the first declarator.
  if (ParseCXXMemberDeclaratorBeforeInitializer(
          DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) {
    TryConsumeToken(tok::semi);
    return nullptr;
  }

  // Check for a member function definition.
  if (BitfieldSize.isUnset()) {
    // MSVC permits pure specifier on inline functions defined at class scope.
    // Hence check for =0 before checking for function definition.
    if (getLangOpts().MicrosoftExt && DeclaratorInfo.isDeclarationOfFunction())
      TryConsumePureSpecifier(/*AllowDefinition*/ true);

    FunctionDefinitionKind DefinitionKind = FDK_Declaration;
    // function-definition:
    //
    // 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) && !getLangOpts().CPlusPlus11) {
      DefinitionKind = FDK_Definition;
    } else if (DeclaratorInfo.isFunctionDeclarator()) {
      if (Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try)) {
        DefinitionKind = FDK_Definition;
      } else if (Tok.is(tok::equal)) {
        const Token &KW = NextToken();
        if (KW.is(tok::kw_default))
          DefinitionKind = FDK_Defaulted;
        else if (KW.is(tok::kw_delete))
          DefinitionKind = FDK_Deleted;
      }
    }
    DeclaratorInfo.setFunctionDefinitionKind(DefinitionKind);

    // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains 
    // to a friend declaration, that declaration shall be a definition.
    if (DeclaratorInfo.isFunctionDeclarator() && 
        DefinitionKind != FDK_Definition && DS.isFriendSpecified()) {
      // Diagnose attributes that appear before decl specifier:
      // [[]] friend int foo();
      ProhibitAttributes(FnAttrs);
    }

    if (DefinitionKind != FDK_Declaration) {
      if (!DeclaratorInfo.isFunctionDeclarator()) {
        Diag(DeclaratorInfo.getIdentifierLoc(), diag::err_func_def_no_params);
        ConsumeBrace();
        SkipUntil(tok::r_brace);

        // Consume the optional ';'
        TryConsumeToken(tok::semi);

        return nullptr;
      }

      if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
        Diag(DeclaratorInfo.getIdentifierLoc(),
             diag::err_function_declared_typedef);

        // Recover by treating the 'typedef' as spurious.
        DS.ClearStorageClassSpecs();
      }

      Decl *FunDecl =
        ParseCXXInlineMethodDef(AS, AccessAttrs, DeclaratorInfo, TemplateInfo,
                                VS, PureSpecLoc);

      if (FunDecl) {
        for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i) {
          CommonLateParsedAttrs[i]->addDecl(FunDecl);
        }
        for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i) {
          LateParsedAttrs[i]->addDecl(FunDecl);
        }
      }
      LateParsedAttrs.clear();

      // Consume the ';' - it's optional unless we have a delete or default
      if (Tok.is(tok::semi))
        ConsumeExtraSemi(AfterMemberFunctionDefinition);

      return DeclGroupPtrTy::make(DeclGroupRef(FunDecl));
    }
  }

  // member-declarator-list:
  //   member-declarator
  //   member-declarator-list ',' member-declarator

  while (1) {
    InClassInitStyle HasInClassInit = ICIS_NoInit;
    bool HasStaticInitializer = false;
    if (Tok.isOneOf(tok::equal, tok::l_brace) && PureSpecLoc.isInvalid()) {
      if (BitfieldSize.get()) {
        Diag(Tok, diag::err_bitfield_member_init);
        SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
      } else if (DeclaratorInfo.isDeclarationOfFunction()) {
        // It's a pure-specifier.
        if (!TryConsumePureSpecifier(/*AllowFunctionDefinition*/ false))
          // Parse it as an expression so that Sema can diagnose it.
          HasStaticInitializer = true;
      } else if (DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
                     DeclSpec::SCS_static &&
                 DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
                     DeclSpec::SCS_typedef &&
                 !DS.isFriendSpecified()) {
        // It's a default member initializer.
        HasInClassInit = Tok.is(tok::equal) ? ICIS_CopyInit : ICIS_ListInit;
      } else {
        HasStaticInitializer = 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.

    NamedDecl *ThisDecl = nullptr;
    if (DS.isFriendSpecified()) {
      // C++11 [dcl.attr.grammar] p4: If an attribute-specifier-seq appertains
      // to a friend declaration, that declaration shall be a definition.
      //
      // Diagnose attributes that appear in a friend member function declarator:
      //   friend int foo [[]] ();
      SmallVector<SourceRange, 4> Ranges;
      DeclaratorInfo.getCXX11AttributeRanges(Ranges);
      for (SmallVectorImpl<SourceRange>::iterator I = Ranges.begin(),
           E = Ranges.end(); I != E; ++I)
        Diag((*I).getBegin(), diag::err_attributes_not_allowed) << *I;

      ThisDecl = Actions.ActOnFriendFunctionDecl(getCurScope(), DeclaratorInfo,
                                                 TemplateParams);
    } else {
      ThisDecl = Actions.ActOnCXXMemberDeclarator(getCurScope(), AS,
                                                  DeclaratorInfo,
                                                  TemplateParams,
                                                  BitfieldSize.get(),
                                                  VS, HasInClassInit);

      if (VarTemplateDecl *VT =
              ThisDecl ? dyn_cast<VarTemplateDecl>(ThisDecl) : nullptr)
        // Re-direct this decl to refer to the templated decl so that we can
        // initialize it.
        ThisDecl = VT->getTemplatedDecl();

      if (ThisDecl && AccessAttrs)
        Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs);
    }

    // Error recovery might have converted a non-static member into a static
    // member.
    if (HasInClassInit != ICIS_NoInit &&
        DeclaratorInfo.getDeclSpec().getStorageClassSpec() ==
            DeclSpec::SCS_static) {
      HasInClassInit = ICIS_NoInit;
      HasStaticInitializer = true;
    }

    if (ThisDecl && PureSpecLoc.isValid())
      Actions.ActOnPureSpecifier(ThisDecl, PureSpecLoc);

    // Handle the initializer.
    if (HasInClassInit != ICIS_NoInit) {
      // The initializer was deferred; parse it and cache the tokens.
      Diag(Tok, getLangOpts().CPlusPlus11
                    ? diag::warn_cxx98_compat_nonstatic_member_init
                    : diag::ext_nonstatic_member_init);

      if (DeclaratorInfo.isArrayOfUnknownBound()) {
        // C++11 [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 grammar, so this is ill-formed.
        Diag(Tok, diag::err_incomplete_array_member_init);
        SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);

        // Avoid later warnings about a class member of incomplete type.
        if (ThisDecl)
          ThisDecl->setInvalidDecl();
      } else
        ParseCXXNonStaticMemberInitializer(ThisDecl);
    } else if (HasStaticInitializer) {
      // Normal initializer.
      ExprResult Init = ParseCXXMemberInitializer(
          ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);

      if (Init.isInvalid())
        SkipUntil(tok::comma, StopAtSemi | StopBeforeMatch);
      else if (ThisDecl)
        Actions.AddInitializerToDecl(ThisDecl, Init.get(), EqualLoc.isInvalid());
    } else if (ThisDecl && DS.getStorageClassSpec() == DeclSpec::SCS_static)
      // No initializer.
      Actions.ActOnUninitializedDecl(ThisDecl);

    if (ThisDecl) {
      if (!ThisDecl->isInvalidDecl()) {
        // Set the Decl for any late parsed attributes
        for (unsigned i = 0, ni = CommonLateParsedAttrs.size(); i < ni; ++i)
          CommonLateParsedAttrs[i]->addDecl(ThisDecl);

        for (unsigned i = 0, ni = LateParsedAttrs.size(); i < ni; ++i)
          LateParsedAttrs[i]->addDecl(ThisDecl);
      }
      Actions.FinalizeDeclaration(ThisDecl);
      DeclsInGroup.push_back(ThisDecl);

      if (DeclaratorInfo.isFunctionDeclarator() &&
          DeclaratorInfo.getDeclSpec().getStorageClassSpec() !=
              DeclSpec::SCS_typedef)
        HandleMemberFunctionDeclDelays(DeclaratorInfo, ThisDecl);
    }
    LateParsedAttrs.clear();

    DeclaratorInfo.complete(ThisDecl);

    // If we don't have a comma, it is either the end of the list (a ';')
    // or an error, bail out.
    SourceLocation CommaLoc;
    if (!TryConsumeToken(tok::comma, CommaLoc))
      break;

    if (Tok.isAtStartOfLine() &&
        !MightBeDeclarator(Declarator::MemberContext)) {
      // This comma was followed by a line-break and something which can't be
      // the start of a declarator. The comma was probably a typo for a
      // semicolon.
      Diag(CommaLoc, diag::err_expected_semi_declaration)
        << FixItHint::CreateReplacement(CommaLoc, ";");
      ExpectSemi = false;
      break;
    }

    // Parse the next declarator.
    DeclaratorInfo.clear();
    VS.clear();
    BitfieldSize = ExprResult(/*Invalid=*/false);
    EqualLoc = PureSpecLoc = SourceLocation();
    DeclaratorInfo.setCommaLoc(CommaLoc);

    // GNU attributes are allowed before the second and subsequent declarator.
    MaybeParseGNUAttributes(DeclaratorInfo);

    if (ParseCXXMemberDeclaratorBeforeInitializer(
            DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs))
      break;
  }

  if (ExpectSemi &&
      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list)) {
    // Skip to end of block or statement.
    SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
    // If we stopped at a ';', eat it.
    TryConsumeToken(tok::semi);
    return nullptr;
  }

  return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup);
}

/// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer.
/// Also detect and reject any attempted defaulted/deleted function definition.
/// The location of the '=', if any, will be placed in EqualLoc.
///
/// This does not check for a pure-specifier; that's handled elsewhere.
///
///   brace-or-equal-initializer:
///     '=' initializer-expression
///     braced-init-list
///
///   initializer-clause:
///     assignment-expression
///     braced-init-list
///
///   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(Decl *D, bool IsFunction,
                                             SourceLocation &EqualLoc) {
  assert(Tok.isOneOf(tok::equal, tok::l_brace)
         && "Data member initializer not starting with '=' or '{'");

  EnterExpressionEvaluationContext Context(
      Actions, Sema::ExpressionEvaluationContext::PotentiallyEvaluated, D);
  if (TryConsumeToken(tok::equal, EqualLoc)) {
    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.isOneOf(tok::semi, tok::comma, tok::eof)) {
        if (IsFunction)
          Diag(ConsumeToken(), diag::err_default_delete_in_multiple_declaration)
            << 1 /* delete */;
        else
          Diag(ConsumeToken(), diag::err_deleted_non_function);
        return ExprError();
      }
    } else if (Tok.is(tok::kw_default)) {
      if (IsFunction)
        Diag(Tok, diag::err_default_delete_in_multiple_declaration)
          << 0 /* default */;
      else
        Diag(ConsumeToken(), diag::err_default_special_members);
      return ExprError();
    }
  }
  if (const auto *PD = dyn_cast_or_null<MSPropertyDecl>(D)) {
    Diag(Tok, diag::err_ms_property_initializer) << PD;
    return ExprError();
  }
  return ParseInitializer();
}

void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc,
                                        SourceLocation AttrFixitLoc,
                                        unsigned TagType, Decl *TagDecl) {
  // Skip the optional 'final' keyword.
  if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
    assert(isCXX11FinalKeyword() && "not a class definition");
    ConsumeToken();

    // Diagnose any C++11 attributes after 'final' keyword.
    // We deliberately discard these attributes.
    ParsedAttributesWithRange Attrs(AttrFactory);
    CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);

    // This can only happen if we had malformed misplaced attributes;
    // we only get called if there is a colon or left-brace after the
    // attributes.
    if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_brace))
      return;
  }

  // Skip the base clauses. This requires actually parsing them, because
  // otherwise we can't be sure where they end (a left brace may appear
  // within a template argument).
  if (Tok.is(tok::colon)) {
    // Enter the scope of the class so that we can correctly parse its bases.
    ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);
    ParsingClassDefinition ParsingDef(*this, TagDecl, /*NonNestedClass*/ true,
                                      TagType == DeclSpec::TST_interface);
    auto OldContext =
        Actions.ActOnTagStartSkippedDefinition(getCurScope(), TagDecl);

    // Parse the bases but don't attach them to the class.
    ParseBaseClause(nullptr);

    Actions.ActOnTagFinishSkippedDefinition(OldContext);

    if (!Tok.is(tok::l_brace)) {
      Diag(PP.getLocForEndOfToken(PrevTokLocation),
           diag::err_expected_lbrace_after_base_specifiers);
      return;
    }
  }

  // Skip the body.
  assert(Tok.is(tok::l_brace));
  BalancedDelimiterTracker T(*this, tok::l_brace);
  T.consumeOpen();
  T.skipToEnd();

  // Parse and discard any trailing attributes.
  ParsedAttributes Attrs(AttrFactory);
  if (Tok.is(tok::kw___attribute))
    MaybeParseGNUAttributes(Attrs);
}

Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas(
    AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs,
    DeclSpec::TST TagType, Decl *TagDecl) {
  switch (Tok.getKind()) {
  case tok::kw___if_exists:
  case tok::kw___if_not_exists:
    ParseMicrosoftIfExistsClassDeclaration(TagType, AS);
    return nullptr;

  case tok::semi:
    // Check for extraneous top-level semicolon.
    ConsumeExtraSemi(InsideStruct, TagType);
    return nullptr;

    // Handle pragmas that can appear as member declarations.
  case tok::annot_pragma_vis:
    HandlePragmaVisibility();
    return nullptr;
  case tok::annot_pragma_pack:
    HandlePragmaPack();
    return nullptr;
  case tok::annot_pragma_align:
    HandlePragmaAlign();
    return nullptr;
  case tok::annot_pragma_ms_pointers_to_members:
    HandlePragmaMSPointersToMembers();
    return nullptr;
  case tok::annot_pragma_ms_pragma:
    HandlePragmaMSPragma();
    return nullptr;
  case tok::annot_pragma_ms_vtordisp:
    HandlePragmaMSVtorDisp();
    return nullptr;
  case tok::annot_pragma_dump:
    HandlePragmaDump();
    return nullptr;

  case tok::kw_namespace:
    // If we see a namespace here, a close brace was missing somewhere.
    DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl));
    return nullptr;

  case tok::kw_public:
  case tok::kw_protected:
  case tok::kw_private: {
    AccessSpecifier NewAS = getAccessSpecifierIfPresent();
    assert(NewAS != AS_none);
    // Current token is a C++ access specifier.
    AS = NewAS;
    SourceLocation ASLoc = Tok.getLocation();
    unsigned TokLength = Tok.getLength();
    ConsumeToken();
    AccessAttrs.clear();
    MaybeParseGNUAttributes(AccessAttrs);

    SourceLocation EndLoc;
    if (TryConsumeToken(tok::colon, EndLoc)) {
    } else if (TryConsumeToken(tok::semi, EndLoc)) {
      Diag(EndLoc, diag::err_expected)
          << tok::colon << FixItHint::CreateReplacement(EndLoc, ":");
    } else {
      EndLoc = ASLoc.getLocWithOffset(TokLength);
      Diag(EndLoc, diag::err_expected)
          << tok::colon << FixItHint::CreateInsertion(EndLoc, ":");
    }

    // The Microsoft extension __interface does not permit non-public
    // access specifiers.
    if (TagType == DeclSpec::TST_interface && AS != AS_public) {
      Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected);
    }

    if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc,
                                     AccessAttrs.getList())) {
      // found another attribute than only annotations
      AccessAttrs.clear();
    }

    return nullptr;
  }

  case tok::annot_pragma_openmp:
    return ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, AccessAttrs, TagType,
                                                      TagDecl);

  default:
    return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList());
  }
}

/// ParseCXXMemberSpecification - Parse the class definition.
///
///       member-specification:
///         member-declaration member-specification[opt]
///         access-specifier ':' member-specification[opt]
///
void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
                                         SourceLocation AttrFixitLoc,
                                         ParsedAttributesWithRange &Attrs,
                                         unsigned TagType, Decl *TagDecl) {
  assert((TagType == DeclSpec::TST_struct ||
         TagType == DeclSpec::TST_interface ||
         TagType == DeclSpec::TST_union  ||
         TagType == DeclSpec::TST_class) && "Invalid TagType!");

  PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc,
                                      "parsing struct/union/class body");

  // Determine whether this is a non-nested class. Note that local
  // classes are *not* considered to be nested classes.
  bool NonNestedClass = true;
  if (!ClassStack.empty()) {
    for (const Scope *S = getCurScope(); S; S = S->getParent()) {
      if (S->isClassScope()) {
        // We're inside a class scope, so this is a nested class.
        NonNestedClass = false;

        // The Microsoft extension __interface does not permit nested classes.
        if (getCurrentClass().IsInterface) {
          Diag(RecordLoc, diag::err_invalid_member_in_interface)
            << /*ErrorType=*/6
            << (isa<NamedDecl>(TagDecl)
                  ? cast<NamedDecl>(TagDecl)->getQualifiedNameAsString()
                  : "(anonymous)");
        }
        break;
      }

      if ((S->getFlags() & Scope::FnScope))
        // If we're in a function or function template then this is a local
        // class rather than a nested class.
        break;
    }
  }

  // Enter a scope for the class.
  ParseScope ClassScope(this, Scope::ClassScope|Scope::DeclScope);

  // Note that we are parsing a new (potentially-nested) class definition.
  ParsingClassDefinition ParsingDef(*this, TagDecl, NonNestedClass,
                                    TagType == DeclSpec::TST_interface);

  if (TagDecl)
    Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);

  SourceLocation FinalLoc;
  bool IsFinalSpelledSealed = false;

  // Parse the optional 'final' keyword.
  if (getLangOpts().CPlusPlus && Tok.is(tok::identifier)) {
    VirtSpecifiers::Specifier Specifier = isCXX11VirtSpecifier(Tok);
    assert((Specifier == VirtSpecifiers::VS_Final ||
            Specifier == VirtSpecifiers::VS_GNU_Final || 
            Specifier == VirtSpecifiers::VS_Sealed) &&
           "not a class definition");
    FinalLoc = ConsumeToken();
    IsFinalSpelledSealed = Specifier == VirtSpecifiers::VS_Sealed;

    if (TagType == DeclSpec::TST_interface)
      Diag(FinalLoc, diag::err_override_control_interface)
        << VirtSpecifiers::getSpecifierName(Specifier);
    else if (Specifier == VirtSpecifiers::VS_Final)
      Diag(FinalLoc, getLangOpts().CPlusPlus11
                         ? diag::warn_cxx98_compat_override_control_keyword
                         : diag::ext_override_control_keyword)
        << VirtSpecifiers::getSpecifierName(Specifier);
    else if (Specifier == VirtSpecifiers::VS_Sealed)
      Diag(FinalLoc, diag::ext_ms_sealed_keyword);
    else if (Specifier == VirtSpecifiers::VS_GNU_Final)
      Diag(FinalLoc, diag::ext_warn_gnu_final);

    // Parse any C++11 attributes after 'final' keyword.
    // These attributes are not allowed to appear here,
    // and the only possible place for them to appertain
    // to the class would be between class-key and class-name.
    CheckMisplacedCXX11Attribute(Attrs, AttrFixitLoc);

    // ParseClassSpecifier() does only a superficial check for attributes before
    // deciding to call this method.  For example, for
    // `class C final alignas ([l) {` it will decide that this looks like a
    // misplaced attribute since it sees `alignas '(' ')'`.  But the actual
    // attribute parsing code will try to parse the '[' as a constexpr lambda
    // and consume enough tokens that the alignas parsing code will eat the
    // opening '{'.  So bail out if the next token isn't one we expect.
    if (!Tok.is(tok::colon) && !Tok.is(tok::l_brace)) {
      if (TagDecl)
        Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);
      return;
    }
  }

  if (Tok.is(tok::colon)) {
    ParseBaseClause(TagDecl);
    if (!Tok.is(tok::l_brace)) {
      bool SuggestFixIt = false;
      SourceLocation BraceLoc = PP.getLocForEndOfToken(PrevTokLocation);
      if (Tok.isAtStartOfLine()) {
        switch (Tok.getKind()) {
        case tok::kw_private:
        case tok::kw_protected:
        case tok::kw_public:
          SuggestFixIt = NextToken().getKind() == tok::colon;
          break;
        case tok::kw_static_assert:
        case tok::r_brace:
        case tok::kw_using:
        // base-clause can have simple-template-id; 'template' can't be there
        case tok::kw_template:
          SuggestFixIt = true;
          break;
        case tok::identifier:
          SuggestFixIt = isConstructorDeclarator(true);
          break;
        default:
          SuggestFixIt = isCXXSimpleDeclaration(/*AllowForRangeDecl=*/false);
          break;
        }
      }
      DiagnosticBuilder LBraceDiag =
          Diag(BraceLoc, diag::err_expected_lbrace_after_base_specifiers);
      if (SuggestFixIt) {
        LBraceDiag << FixItHint::CreateInsertion(BraceLoc, " {");
        // Try recovering from missing { after base-clause.
        PP.EnterToken(Tok);
        Tok.setKind(tok::l_brace);
      } else {
        if (TagDecl)
          Actions.ActOnTagDefinitionError(getCurScope(), TagDecl);
        return;
      }
    }
  }

  assert(Tok.is(tok::l_brace));
  BalancedDelimiterTracker T(*this, tok::l_brace);
  T.consumeOpen();

  if (TagDecl)
    Actions.ActOnStartCXXMemberDeclarations(getCurScope(), TagDecl, FinalLoc,
                                            IsFinalSpelledSealed,
                                            T.getOpenLocation());

  // C++ 11p3: Members of a class defined with the keyword class are private
  // by default. Members of a class defined with the keywords struct or union
  // are public by default.
  AccessSpecifier CurAS;
  if (TagType == DeclSpec::TST_class)
    CurAS = AS_private;
  else
    CurAS = AS_public;
  ParsedAttributesWithRange AccessAttrs(AttrFactory);

  if (TagDecl) {
    // While we still have something to read, read the member-declarations.
    while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) &&
           Tok.isNot(tok::eof)) {
      // Each iteration of this loop reads one member-declaration.
      ParseCXXClassMemberDeclarationWithPragmas(
          CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl);
    }
    T.consumeClose();
  } else {
    SkipUntil(tok::r_brace);
  }

  // If attributes exist after class contents, parse them.
  ParsedAttributes attrs(AttrFactory);
  MaybeParseGNUAttributes(attrs);

  if (TagDecl)
    Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl,
                                              T.getOpenLocation(), 
                                              T.getCloseLocation(),
                                              attrs.getList());

  // C++11 [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).
  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, along with any
    // delayed attributes.
    SourceLocation SavedPrevTokLocation = PrevTokLocation;
    ParseLexedAttributes(getCurrentClass());
    ParseLexedMethodDeclarations(getCurrentClass());

    // We've finished with all pending member declarations.
    Actions.ActOnFinishCXXMemberDecls();

    ParseLexedMemberInitializers(getCurrentClass());
    ParseLexedMethodDefs(getCurrentClass());
    PrevTokLocation = SavedPrevTokLocation;

    // We've finished parsing everything, including default argument
    // initializers.
    Actions.ActOnFinishCXXNonNestedClass(TagDecl);
  }

  if (TagDecl)
    Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange());

  // Leave the class scope.
  ParsingDef.Pop();
  ClassScope.Exit();
}

void Parser::DiagnoseUnexpectedNamespace(NamedDecl *D) {
  assert(Tok.is(tok::kw_namespace));

  // FIXME: Suggest where the close brace should have gone by looking
  // at indentation changes within the definition body.
  Diag(D->getLocation(),
       diag::err_missing_end_of_definition) << D;
  Diag(Tok.getLocation(),
       diag::note_missing_end_of_definition_before) << D;

  // Push '};' onto the token stream to recover.
  PP.EnterToken(Tok);

  Tok.startToken();
  Tok.setLocation(PP.getLocForEndOfToken(PrevTokLocation));
  Tok.setKind(tok::semi);
  PP.EnterToken(Tok);

  Tok.setKind(tok::r_brace);
}

/// ParseConstructorInitializer - Parse a C++ constructor initializer,
/// which explicitly initializes the members or base classes of a
/// class (C++ [class.base.init]). For example, the three initializers
/// after the ':' in the Derived constructor below:
///
/// @code
/// class Base { };
/// class Derived : Base {
///   int x;
///   float f;
/// public:
///   Derived(float f) : Base(), x(17), f(f) { }
/// };
/// @endcode
///
/// [C++]  ctor-initializer:
///          ':' mem-initializer-list
///
/// [C++]  mem-initializer-list:
///          mem-initializer ...[opt]
///          mem-initializer ...[opt] , mem-initializer-list
void Parser::ParseConstructorInitializer(Decl *ConstructorDecl) {
  assert(Tok.is(tok::colon) &&
         "Constructor initializer always starts with ':'");

  // Poison the SEH identifiers so they are flagged as illegal in constructor
  // initializers.
  PoisonSEHIdentifiersRAIIObject PoisonSEHIdentifiers(*this, true);
  SourceLocation ColonLoc = ConsumeToken();

  SmallVector<CXXCtorInitializer*, 4> MemInitializers;
  bool AnyErrors = false;

  do {
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteConstructorInitializer(ConstructorDecl,
                                                 MemInitializers);
      return cutOffParsing();
    }

    MemInitResult MemInit = ParseMemInitializer(ConstructorDecl);
    if (!MemInit.isInvalid())
      MemInitializers.push_back(MemInit.get());
    else
      AnyErrors = true;

    if (Tok.is(tok::comma))
      ConsumeToken();
    else if (Tok.is(tok::l_brace))
      break;
    // If the previous initializer was valid and the next token looks like a
    // base or member initializer, assume that we're just missing a comma.
    else if (!MemInit.isInvalid() &&
             Tok.isOneOf(tok::identifier, tok::coloncolon)) {
      SourceLocation Loc = PP.getLocForEndOfToken(PrevTokLocation);
      Diag(Loc, diag::err_ctor_init_missing_comma)
        << FixItHint::CreateInsertion(Loc, ", ");
    } else {
      // Skip over garbage, until we get to '{'.  Don't eat the '{'.
      if (!MemInit.isInvalid())
        Diag(Tok.getLocation(), diag::err_expected_either) << tok::l_brace
                                                           << tok::comma;
      SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
      break;
    }
  } while (true);

  Actions.ActOnMemInitializers(ConstructorDecl, ColonLoc, MemInitializers,
                               AnyErrors);
}

/// ParseMemInitializer - Parse a C++ member initializer, which is
/// part of a constructor initializer that explicitly initializes one
/// member or base class (C++ [class.base.init]). See
/// ParseConstructorInitializer for an example.
///
/// [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
///         identifier
MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) {
  // parse '::'[opt] nested-name-specifier[opt]
  CXXScopeSpec SS;
  ParseOptionalCXXScopeSpecifier(SS, nullptr, /*EnteringContext=*/false);
  ParsedType TemplateTypeTy;
  if (Tok.is(tok::annot_template_id)) {
    TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok);
    if (TemplateId->Kind == TNK_Type_template ||
        TemplateId->Kind == TNK_Dependent_template_name) {
      AnnotateTemplateIdTokenAsType(/*IsClassName*/true);
      assert(Tok.is(tok::annot_typename) && "template-id -> type failed");
      TemplateTypeTy = getTypeAnnotation(Tok);
    }
  }
  // Uses of decltype will already have been converted to annot_decltype by
  // ParseOptionalCXXScopeSpecifier at this point.
  if (!TemplateTypeTy && Tok.isNot(tok::identifier)
      && Tok.isNot(tok::annot_decltype)) {
    Diag(Tok, diag::err_expected_member_or_base_name);
    return true;
  }

  IdentifierInfo *II = nullptr;
  DeclSpec DS(AttrFactory);
  SourceLocation IdLoc = Tok.getLocation();
  if (Tok.is(tok::annot_decltype)) {
    // Get the decltype expression, if there is one.
    ParseDecltypeSpecifier(DS);
  } else {
    if (Tok.is(tok::identifier))
      // Get the identifier. This may be a member name or a class name,
      // but we'll let the semantic analysis determine which it is.
      II = Tok.getIdentifierInfo();
    ConsumeToken();
  }


  // Parse the '('.
  if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
    Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);

    ExprResult InitList = ParseBraceInitializer();
    if (InitList.isInvalid())
      return true;

    SourceLocation EllipsisLoc;
    TryConsumeToken(tok::ellipsis, EllipsisLoc);

    return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
                                       TemplateTypeTy, DS, IdLoc, 
                                       InitList.get(), EllipsisLoc);
  } else if(Tok.is(tok::l_paren)) {
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();

    // Parse the optional expression-list.
    ExprVector ArgExprs;
    CommaLocsTy CommaLocs;
    if (Tok.isNot(tok::r_paren) && ParseExpressionList(ArgExprs, CommaLocs)) {
      SkipUntil(tok::r_paren, StopAtSemi);
      return true;
    }

    T.consumeClose();

    SourceLocation EllipsisLoc;
    TryConsumeToken(tok::ellipsis, EllipsisLoc);

    return Actions.ActOnMemInitializer(ConstructorDecl, getCurScope(), SS, II,
                                       TemplateTypeTy, DS, IdLoc,
                                       T.getOpenLocation(), ArgExprs,
                                       T.getCloseLocation(), EllipsisLoc);
  }

  if (getLangOpts().CPlusPlus11)
    return Diag(Tok, diag::err_expected_either) << tok::l_paren << tok::l_brace;
  else
    return Diag(Tok, diag::err_expected) << tok::l_paren;
}

/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]).
///
///       exception-specification:
///         dynamic-exception-specification
///         noexcept-specification
///
///       noexcept-specification:
///         'noexcept'
///         'noexcept' '(' constant-expression ')'
ExceptionSpecificationType
Parser::tryParseExceptionSpecification(bool Delayed,
                    SourceRange &SpecificationRange,
                    SmallVectorImpl<ParsedType> &DynamicExceptions,
                    SmallVectorImpl<SourceRange> &DynamicExceptionRanges,
                    ExprResult &NoexceptExpr,
                    CachedTokens *&ExceptionSpecTokens) {
  ExceptionSpecificationType Result = EST_None;
  ExceptionSpecTokens = nullptr;
  
  // Handle delayed parsing of exception-specifications.
  if (Delayed) {
    if (Tok.isNot(tok::kw_throw) && Tok.isNot(tok::kw_noexcept))
      return EST_None;

    // Consume and cache the starting token.
    bool IsNoexcept = Tok.is(tok::kw_noexcept);
    Token StartTok = Tok;
    SpecificationRange = SourceRange(ConsumeToken());

    // Check for a '('.
    if (!Tok.is(tok::l_paren)) {
      // If this is a bare 'noexcept', we're done.
      if (IsNoexcept) {
        Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);
        NoexceptExpr = nullptr;
        return EST_BasicNoexcept;
      }
      
      Diag(Tok, diag::err_expected_lparen_after) << "throw";
      return EST_DynamicNone;
    }
    
    // Cache the tokens for the exception-specification.
    ExceptionSpecTokens = new CachedTokens;
    ExceptionSpecTokens->push_back(StartTok); // 'throw' or 'noexcept'
    ExceptionSpecTokens->push_back(Tok); // '('
    SpecificationRange.setEnd(ConsumeParen()); // '('

    ConsumeAndStoreUntil(tok::r_paren, *ExceptionSpecTokens,
                         /*StopAtSemi=*/true,
                         /*ConsumeFinalToken=*/true);
    SpecificationRange.setEnd(ExceptionSpecTokens->back().getLocation());

    return EST_Unparsed;
  }
  
  // See if there's a dynamic specification.
  if (Tok.is(tok::kw_throw)) {
    Result = ParseDynamicExceptionSpecification(SpecificationRange,
                                                DynamicExceptions,
                                                DynamicExceptionRanges);
    assert(DynamicExceptions.size() == DynamicExceptionRanges.size() &&
           "Produced different number of exception types and ranges.");
  }

  // If there's no noexcept specification, we're done.
  if (Tok.isNot(tok::kw_noexcept))
    return Result;

  Diag(Tok, diag::warn_cxx98_compat_noexcept_decl);

  // If we already had a dynamic specification, parse the noexcept for,
  // recovery, but emit a diagnostic and don't store the results.
  SourceRange NoexceptRange;
  ExceptionSpecificationType NoexceptType = EST_None;

  SourceLocation KeywordLoc = ConsumeToken();
  if (Tok.is(tok::l_paren)) {
    // There is an argument.
    BalancedDelimiterTracker T(*this, tok::l_paren);
    T.consumeOpen();
    NoexceptType = EST_ComputedNoexcept;
    NoexceptExpr = ParseConstantExpression();
    T.consumeClose();
    // The argument must be contextually convertible to bool. We use
    // CheckBooleanCondition for this purpose.
    // FIXME: Add a proper Sema entry point for this.
    if (!NoexceptExpr.isInvalid()) {
      NoexceptExpr =
          Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get());
      NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation());
    } else {
      NoexceptType = EST_BasicNoexcept;
    }
  } else {
    // There is no argument.
    NoexceptType = EST_BasicNoexcept;
    NoexceptRange = SourceRange(KeywordLoc, KeywordLoc);
  }

  if (Result == EST_None) {
    SpecificationRange = NoexceptRange;
    Result = NoexceptType;

    // If there's a dynamic specification after a noexcept specification,
    // parse that and ignore the results.
    if (Tok.is(tok::kw_throw)) {
      Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);
      ParseDynamicExceptionSpecification(NoexceptRange, DynamicExceptions,
                                         DynamicExceptionRanges);
    }
  } else {
    Diag(Tok.getLocation(), diag::err_dynamic_and_noexcept_specification);
  }

  return Result;
}

static void diagnoseDynamicExceptionSpecification(
    Parser &P, SourceRange Range, bool IsNoexcept) {
  if (P.getLangOpts().CPlusPlus11) {
    const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)";
    P.Diag(Range.getBegin(),
           P.getLangOpts().CPlusPlus1z && !IsNoexcept
               ? diag::ext_dynamic_exception_spec
               : diag::warn_exception_spec_deprecated)
        << Range;
    P.Diag(Range.getBegin(), diag::note_exception_spec_deprecated)
      << Replacement << FixItHint::CreateReplacement(Range, Replacement);
  }
}

/// ParseDynamicExceptionSpecification - Parse a C++
/// dynamic-exception-specification (C++ [except.spec]).
///
///       dynamic-exception-specification:
///         'throw' '(' type-id-list [opt] ')'
/// [MS]    'throw' '(' '...' ')'
///
///       type-id-list:
///         type-id ... [opt]
///         type-id-list ',' type-id ... [opt]
///
ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification(
                                  SourceRange &SpecificationRange,
                                  SmallVectorImpl<ParsedType> &Exceptions,
                                  SmallVectorImpl<SourceRange> &Ranges) {
  assert(Tok.is(tok::kw_throw) && "expected throw");

  SpecificationRange.setBegin(ConsumeToken());
  BalancedDelimiterTracker T(*this, tok::l_paren);
  if (T.consumeOpen()) {
    Diag(Tok, diag::err_expected_lparen_after) << "throw";
    SpecificationRange.setEnd(SpecificationRange.getBegin());
    return EST_DynamicNone;
  }

  // Parse throw(...), a Microsoft extension that means "this function
  // can throw anything".
  if (Tok.is(tok::ellipsis)) {
    SourceLocation EllipsisLoc = ConsumeToken();
    if (!getLangOpts().MicrosoftExt)
      Diag(EllipsisLoc, diag::ext_ellipsis_exception_spec);
    T.consumeClose();
    SpecificationRange.setEnd(T.getCloseLocation());
    diagnoseDynamicExceptionSpecification(*this, SpecificationRange, false);
    return EST_MSAny;
  }

  // Parse the sequence of type-ids.
  SourceRange Range;
  while (Tok.isNot(tok::r_paren)) {
    TypeResult Res(ParseTypeName(&Range));

    if (Tok.is(tok::ellipsis)) {
      // C++0x [temp.variadic]p5:
      //   - In a dynamic-exception-specification (15.4); the pattern is a 
      //     type-id.
      SourceLocation Ellipsis = ConsumeToken();
      Range.setEnd(Ellipsis);
      if (!Res.isInvalid())
        Res = Actions.ActOnPackExpansion(Res.get(), Ellipsis);
    }

    if (!Res.isInvalid()) {
      Exceptions.push_back(Res.get());
      Ranges.push_back(Range);
    }

    if (!TryConsumeToken(tok::comma))
      break;
  }

  T.consumeClose();
  SpecificationRange.setEnd(T.getCloseLocation());
  diagnoseDynamicExceptionSpecification(*this, SpecificationRange,
                                        Exceptions.empty());
  return Exceptions.empty() ? EST_DynamicNone : EST_Dynamic;
}

/// ParseTrailingReturnType - Parse a trailing return type on a new-style
/// function declaration.
TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) {
  assert(Tok.is(tok::arrow) && "expected arrow");

  ConsumeToken();

  return ParseTypeName(&Range, Declarator::TrailingReturnContext);
}

/// \brief We have just started parsing the definition of a new class,
/// so push that class onto our stack of classes that is currently
/// being parsed.
Sema::ParsingClassState
Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass,
                         bool IsInterface) {
  assert((NonNestedClass || !ClassStack.empty()) &&
         "Nested class without outer class");
  ClassStack.push(new ParsingClass(ClassDecl, NonNestedClass, IsInterface));
  return Actions.PushParsingClass();
}

/// \brief Deallocate the given parsed class and all of its nested
/// classes.
void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) {
  for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I)
    delete Class->LateParsedDeclarations[I];
  delete Class;
}

/// \brief Pop the top class of the stack of classes that are
/// currently being parsed.
///
/// This routine should be called when we have finished parsing the
/// definition of a class, but have not yet popped the Scope
/// associated with the class's definition.
void Parser::PopParsingClass(Sema::ParsingClassState state) {
  assert(!ClassStack.empty() && "Mismatched push/pop for class parsing");

  Actions.PopParsingClass(state);

  ParsingClass *Victim = ClassStack.top();
  ClassStack.pop();
  if (Victim->TopLevelClass) {
    // Deallocate all of the nested classes of this class,
    // recursively: we don't need to keep any of this information.
    DeallocateParsedClasses(Victim);
    return;
  }
  assert(!ClassStack.empty() && "Missing top-level class?");

  if (Victim->LateParsedDeclarations.empty()) {
    // The victim is a nested class, but we will not need to perform
    // any processing after the definition of this class since it has
    // no members whose handling was delayed. Therefore, we can just
    // remove this nested class.
    DeallocateParsedClasses(Victim);
    return;
  }

  // This nested class has some members that will need to be processed
  // after the top-level class is completely defined. Therefore, add
  // it to the list of nested classes within its parent.
  assert(getCurScope()->isClassScope() && "Nested class outside of class scope?");
  ClassStack.top()->LateParsedDeclarations.push_back(new LateParsedClass(this, Victim));
  Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
}

/// \brief Try to parse an 'identifier' which appears within an attribute-token.
///
/// \return the parsed identifier on success, and 0 if the next token is not an
/// attribute-token.
///
/// C++11 [dcl.attr.grammar]p3:
///   If a keyword or an alternative token that satisfies the syntactic
///   requirements of an identifier is contained in an attribute-token,
///   it is considered an identifier.
IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
  switch (Tok.getKind()) {
  default:
    // Identifiers and keywords have identifier info attached.
    if (!Tok.isAnnotation()) {
      if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
        Loc = ConsumeToken();
        return II;
      }
    }
    return nullptr;

  case tok::ampamp:       // 'and'
  case tok::pipe:         // 'bitor'
  case tok::pipepipe:     // 'or'
  case tok::caret:        // 'xor'
  case tok::tilde:        // 'compl'
  case tok::amp:          // 'bitand'
  case tok::ampequal:     // 'and_eq'
  case tok::pipeequal:    // 'or_eq'
  case tok::caretequal:   // 'xor_eq'
  case tok::exclaim:      // 'not'
  case tok::exclaimequal: // 'not_eq'
    // Alternative tokens do not have identifier info, but their spelling
    // starts with an alphabetical character.
    SmallString<8> SpellingBuf;
    SourceLocation SpellingLoc =
        PP.getSourceManager().getSpellingLoc(Tok.getLocation());
    StringRef Spelling = PP.getSpelling(SpellingLoc, SpellingBuf);
    if (isLetter(Spelling[0])) {
      Loc = ConsumeToken();
      return &PP.getIdentifierTable().get(Spelling);
    }
    return nullptr;
  }
}

static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
                                               IdentifierInfo *ScopeName) {
  switch (AttributeList::getKind(AttrName, ScopeName,
                                 AttributeList::AS_CXX11)) {
  case AttributeList::AT_CarriesDependency:
  case AttributeList::AT_Deprecated:
  case AttributeList::AT_FallThrough:
  case AttributeList::AT_CXX11NoReturn:
    return true;
  case AttributeList::AT_WarnUnusedResult:
    return !ScopeName && AttrName->getName().equals("nodiscard");
  case AttributeList::AT_Unused:
    return !ScopeName && AttrName->getName().equals("maybe_unused");
  default:
    return false;
  }
}

/// ParseCXX11AttributeArgs -- Parse a C++11 attribute-argument-clause.
///
/// [C++11] attribute-argument-clause:
///         '(' balanced-token-seq ')'
///
/// [C++11] balanced-token-seq:
///         balanced-token
///         balanced-token-seq balanced-token
///
/// [C++11] balanced-token:
///         '(' balanced-token-seq ')'
///         '[' balanced-token-seq ']'
///         '{' balanced-token-seq '}'
///         any token but '(', ')', '[', ']', '{', or '}'
bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName,
                                     SourceLocation AttrNameLoc,
                                     ParsedAttributes &Attrs,
                                     SourceLocation *EndLoc,
                                     IdentifierInfo *ScopeName,
                                     SourceLocation ScopeLoc) {
  assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list");
  SourceLocation LParenLoc = Tok.getLocation();

  // If the attribute isn't known, we will not attempt to parse any
  // arguments.
  if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName,
                    getTargetInfo(), getLangOpts())) {
    // Eat the left paren, then skip to the ending right paren.
    ConsumeParen();
    SkipUntil(tok::r_paren);
    return false;
  }

  if (ScopeName && ScopeName->getName() == "gnu") {
    // GNU-scoped attributes have some special cases to handle GNU-specific
    // behaviors.
    ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
                          ScopeLoc, AttributeList::AS_CXX11, nullptr);
    return true;
  }

  unsigned NumArgs;
  // Some Clang-scoped attributes have some special parsing behavior.
  if (ScopeName && ScopeName->getName() == "clang")
    NumArgs =
        ParseClangAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
                                ScopeLoc, AttributeList::AS_CXX11);
  else
    NumArgs =
        ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc,
                                 ScopeName, ScopeLoc, AttributeList::AS_CXX11);

  const AttributeList *Attr = Attrs.getList();
  if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) {
    // If the attribute is a standard or built-in attribute and we are
    // parsing an argument list, we need to determine whether this attribute
    // was allowed to have an argument list (such as [[deprecated]]), and how
    // many arguments were parsed (so we can diagnose on [[deprecated()]]).
    if (Attr->getMaxArgs() && !NumArgs) {
      // The attribute was allowed to have arguments, but none were provided
      // even though the attribute parsed successfully. This is an error.
      Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName;
      Attr->setInvalid(true);
    } else if (!Attr->getMaxArgs()) {
      // The attribute parsed successfully, but was not allowed to have any
      // arguments. It doesn't matter whether any were provided -- the
      // presence of the argument list (even if empty) is diagnosed.
      Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments)
          << AttrName
          << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc));
      Attr->setInvalid(true);
    }
  }
  return true;
}

/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier.
///
/// [C++11] attribute-specifier:
///         '[' '[' attribute-list ']' ']'
///         alignment-specifier
///
/// [C++11] attribute-list:
///         attribute[opt]
///         attribute-list ',' attribute[opt]
///         attribute '...'
///         attribute-list ',' attribute '...'
///
/// [C++11] attribute:
///         attribute-token attribute-argument-clause[opt]
///
/// [C++11] attribute-token:
///         identifier
///         attribute-scoped-token
///
/// [C++11] attribute-scoped-token:
///         attribute-namespace '::' identifier
///
/// [C++11] attribute-namespace:
///         identifier
void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
                                          SourceLocation *endLoc) {
  if (Tok.is(tok::kw_alignas)) {
    Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);
    ParseAlignmentSpecifier(attrs, endLoc);
    return;
  }

  assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square)
      && "Not a C++11 attribute list");

  Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute);

  ConsumeBracket();
  ConsumeBracket();

  SourceLocation CommonScopeLoc;
  IdentifierInfo *CommonScopeName = nullptr;
  if (Tok.is(tok::kw_using)) {
    Diag(Tok.getLocation(), getLangOpts().CPlusPlus1z
                                ? diag::warn_cxx14_compat_using_attribute_ns
                                : diag::ext_using_attribute_ns);
    ConsumeToken();

    CommonScopeName = TryParseCXX11AttributeIdentifier(CommonScopeLoc);
    if (!CommonScopeName) {
      Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
      SkipUntil(tok::r_square, tok::colon, StopBeforeMatch);
    }
    if (!TryConsumeToken(tok::colon) && CommonScopeName)
      Diag(Tok.getLocation(), diag::err_expected) << tok::colon;
  }

  llvm::SmallDenseMap<IdentifierInfo*, SourceLocation, 4> SeenAttrs;

  while (Tok.isNot(tok::r_square)) {
    // attribute not present
    if (TryConsumeToken(tok::comma))
      continue;

    SourceLocation ScopeLoc, AttrLoc;
    IdentifierInfo *ScopeName = nullptr, *AttrName = nullptr;

    AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
    if (!AttrName)
      // Break out to the "expected ']'" diagnostic.
      break;

    // scoped attribute
    if (TryConsumeToken(tok::coloncolon)) {
      ScopeName = AttrName;
      ScopeLoc = AttrLoc;

      AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
      if (!AttrName) {
        Diag(Tok.getLocation(), diag::err_expected) << tok::identifier;
        SkipUntil(tok::r_square, tok::comma, StopAtSemi | StopBeforeMatch);
        continue;
      }
    }

    if (CommonScopeName) {
      if (ScopeName) {
        Diag(ScopeLoc, diag::err_using_attribute_ns_conflict)
            << SourceRange(CommonScopeLoc);
      } else {
        ScopeName = CommonScopeName;
        ScopeLoc = CommonScopeLoc;
      }
    }

    bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName);
    bool AttrParsed = false;

    if (StandardAttr &&
        !SeenAttrs.insert(std::make_pair(AttrName, AttrLoc)).second)
      Diag(AttrLoc, diag::err_cxx11_attribute_repeated)
          << AttrName << SourceRange(SeenAttrs[AttrName]);

    // Parse attribute arguments
    if (Tok.is(tok::l_paren))
      AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc,
                                           ScopeName, ScopeLoc);

    if (!AttrParsed)
      attrs.addNew(AttrName,
                   SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
                               AttrLoc),
                   ScopeName, ScopeLoc, nullptr, 0, AttributeList::AS_CXX11);

    if (TryConsumeToken(tok::ellipsis))
      Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
        << AttrName->getName();
  }

  if (ExpectAndConsume(tok::r_square))
    SkipUntil(tok::r_square);
  if (endLoc)
    *endLoc = Tok.getLocation();
  if (ExpectAndConsume(tok::r_square))
    SkipUntil(tok::r_square);
}

/// ParseCXX11Attributes - Parse a C++11 attribute-specifier-seq.
///
/// attribute-specifier-seq:
///       attribute-specifier-seq[opt] attribute-specifier
void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
                                  SourceLocation *endLoc) {
  assert(getLangOpts().CPlusPlus11);

  SourceLocation StartLoc = Tok.getLocation(), Loc;
  if (!endLoc)
    endLoc = &Loc;

  do {
    ParseCXX11AttributeSpecifier(attrs, endLoc);
  } while (isCXX11AttributeSpecifier());

  attrs.Range = SourceRange(StartLoc, *endLoc);
}

void Parser::DiagnoseAndSkipCXX11Attributes() {
  // Start and end location of an attribute or an attribute list.
  SourceLocation StartLoc = Tok.getLocation();
  SourceLocation EndLoc = SkipCXX11Attributes();

  if (EndLoc.isValid()) {
    SourceRange Range(StartLoc, EndLoc);
    Diag(StartLoc, diag::err_attributes_not_allowed)
      << Range;
  }
}

SourceLocation Parser::SkipCXX11Attributes() {
  SourceLocation EndLoc;

  if (!isCXX11AttributeSpecifier())
    return EndLoc;

  do {
    if (Tok.is(tok::l_square)) {
      BalancedDelimiterTracker T(*this, tok::l_square);
      T.consumeOpen();
      T.skipToEnd();
      EndLoc = T.getCloseLocation();
    } else {
      assert(Tok.is(tok::kw_alignas) && "not an attribute specifier");
      ConsumeToken();
      BalancedDelimiterTracker T(*this, tok::l_paren);
      if (!T.consumeOpen())
        T.skipToEnd();
      EndLoc = T.getCloseLocation();
    }
  } while (isCXX11AttributeSpecifier());

  return EndLoc;
}

/// Parse uuid() attribute when it appears in a [] Microsoft attribute.
void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) {
  assert(Tok.is(tok::identifier) && "Not a Microsoft attribute list");
  IdentifierInfo *UuidIdent = Tok.getIdentifierInfo();
  assert(UuidIdent->getName() == "uuid" && "Not a Microsoft attribute list");

  SourceLocation UuidLoc = Tok.getLocation();
  ConsumeToken();

  // Ignore the left paren location for now.
  BalancedDelimiterTracker T(*this, tok::l_paren);
  if (T.consumeOpen()) {
    Diag(Tok, diag::err_expected) << tok::l_paren;
    return;
  }

  ArgsVector ArgExprs;
  if (Tok.is(tok::string_literal)) {
    // Easy case: uuid("...") -- quoted string.
    ExprResult StringResult = ParseStringLiteralExpression();
    if (StringResult.isInvalid())
      return;
    ArgExprs.push_back(StringResult.get());
  } else {
    // something like uuid({000000A0-0000-0000-C000-000000000049}) -- no
    // quotes in the parens. Just append the spelling of all tokens encountered
    // until the closing paren.

    SmallString<42> StrBuffer; // 2 "", 36 bytes UUID, 2 optional {}, 1 nul
    StrBuffer += "\"";

    // Since none of C++'s keywords match [a-f]+, accepting just tok::l_brace,
    // tok::r_brace, tok::minus, tok::identifier (think C000) and
    // tok::numeric_constant (0000) should be enough. But the spelling of the
    // uuid argument is checked later anyways, so there's no harm in accepting
    // almost anything here.
    // cl is very strict about whitespace in this form and errors out if any
    // is present, so check the space flags on the tokens.
    SourceLocation StartLoc = Tok.getLocation();
    while (Tok.isNot(tok::r_paren)) {
      if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
        Diag(Tok, diag::err_attribute_uuid_malformed_guid);
        SkipUntil(tok::r_paren, StopAtSemi);
        return;
      }
      SmallString<16> SpellingBuffer;
      SpellingBuffer.resize(Tok.getLength() + 1);
      bool Invalid = false;
      StringRef TokSpelling = PP.getSpelling(Tok, SpellingBuffer, &Invalid);
      if (Invalid) {
        SkipUntil(tok::r_paren, StopAtSemi);
        return;
      }
      StrBuffer += TokSpelling;
      ConsumeAnyToken();
    }
    StrBuffer += "\"";

    if (Tok.hasLeadingSpace() || Tok.isAtStartOfLine()) {
      Diag(Tok, diag::err_attribute_uuid_malformed_guid);
      ConsumeParen();
      return;
    }

    // Pretend the user wrote the appropriate string literal here.
    // ActOnStringLiteral() copies the string data into the literal, so it's
    // ok that the Token points to StrBuffer.
    Token Toks[1];
    Toks[0].startToken();
    Toks[0].setKind(tok::string_literal);
    Toks[0].setLocation(StartLoc);
    Toks[0].setLiteralData(StrBuffer.data());
    Toks[0].setLength(StrBuffer.size());
    StringLiteral *UuidString =
        cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
    ArgExprs.push_back(UuidString);
  }

  if (!T.consumeClose()) {
    // FIXME: Warn that this syntax is deprecated, with a Fix-It suggesting
    // using __declspec(uuid()) instead.
    Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr,
                 SourceLocation(), ArgExprs.data(), ArgExprs.size(),
                 AttributeList::AS_Microsoft);
  }
}

/// ParseMicrosoftAttributes - Parse Microsoft attributes [Attr]
///
/// [MS] ms-attribute:
///             '[' token-seq ']'
///
/// [MS] ms-attribute-seq:
///             ms-attribute[opt]
///             ms-attribute ms-attribute-seq
void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs,
                                      SourceLocation *endLoc) {
  assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list");

  do {
    // FIXME: If this is actually a C++11 attribute, parse it as one.
    BalancedDelimiterTracker T(*this, tok::l_square);
    T.consumeOpen();

    // Skip most ms attributes except for a whitelist.
    while (true) {
      SkipUntil(tok::r_square, tok::identifier, StopAtSemi | StopBeforeMatch);
      if (Tok.isNot(tok::identifier)) // ']', but also eof
        break;
      if (Tok.getIdentifierInfo()->getName() == "uuid")
        ParseMicrosoftUuidAttributeArgs(attrs);
      else
        ConsumeToken();
    }

    T.consumeClose();
    if (endLoc)
      *endLoc = T.getCloseLocation();
  } while (Tok.is(tok::l_square));
}

void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType,
                                                    AccessSpecifier& CurAS) {
  IfExistsCondition Result;
  if (ParseMicrosoftIfExistsCondition(Result))
    return;
  
  BalancedDelimiterTracker Braces(*this, tok::l_brace);
  if (Braces.consumeOpen()) {
    Diag(Tok, diag::err_expected) << tok::l_brace;
    return;
  }

  switch (Result.Behavior) {
  case IEB_Parse:
    // Parse the declarations below.
    break;
        
  case IEB_Dependent:
    Diag(Result.KeywordLoc, diag::warn_microsoft_dependent_exists)
      << Result.IsIfExists;
    // Fall through to skip.
      
  case IEB_Skip:
    Braces.skipToEnd();
    return;
  }

  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
    // __if_exists, __if_not_exists can nest.
    if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) {
      ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS);
      continue;
    }

    // Check for extraneous top-level semicolon.
    if (Tok.is(tok::semi)) {
      ConsumeExtraSemi(InsideStruct, TagType);
      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) << tok::colon;
      ConsumeToken();
      continue;
    }

    // Parse all the comma separated declarators.
    ParseCXXClassMemberDeclaration(CurAS, nullptr);
  }
  
  Braces.consumeClose();
}
