//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Objective-C portions of the Parser interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/PrettyDeclStackTrace.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/Scope.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"

using namespace clang;

/// Skips attributes after an Objective-C @ directive. Emits a diagnostic.
void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) {
  ParsedAttributes attrs(AttrFactory);
  if (Tok.is(tok::kw___attribute)) {
    if (Kind == tok::objc_interface || Kind == tok::objc_protocol)
      Diag(Tok, diag::err_objc_postfix_attribute_hint)
          << (Kind == tok::objc_protocol);
    else
      Diag(Tok, diag::err_objc_postfix_attribute);
    ParseGNUAttributes(attrs);
  }
}

/// ParseObjCAtDirectives - Handle parts of the external-declaration production:
///       external-declaration: [C99 6.9]
/// [OBJC]  objc-class-definition
/// [OBJC]  objc-class-declaration
/// [OBJC]  objc-alias-declaration
/// [OBJC]  objc-protocol-definition
/// [OBJC]  objc-method-definition
/// [OBJC]  '@' 'end'
Parser::DeclGroupPtrTy
Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) {
  SourceLocation AtLoc = ConsumeToken(); // the "@"

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

  Decl *SingleDecl = nullptr;
  switch (Tok.getObjCKeywordID()) {
  case tok::objc_class:
    return ParseObjCAtClassDeclaration(AtLoc);
  case tok::objc_interface:
    SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs);
    break;
  case tok::objc_protocol:
    return ParseObjCAtProtocolDeclaration(AtLoc, Attrs);
  case tok::objc_implementation:
    return ParseObjCAtImplementationDeclaration(AtLoc, Attrs);
  case tok::objc_end:
    return ParseObjCAtEndDeclaration(AtLoc);
  case tok::objc_compatibility_alias:
    SingleDecl = ParseObjCAtAliasDeclaration(AtLoc);
    break;
  case tok::objc_synthesize:
    SingleDecl = ParseObjCPropertySynthesize(AtLoc);
    break;
  case tok::objc_dynamic:
    SingleDecl = ParseObjCPropertyDynamic(AtLoc);
    break;
  case tok::objc_import:
    if (getLangOpts().Modules || getLangOpts().DebuggerSupport) {
      SingleDecl = ParseModuleImport(AtLoc);
      break;
    }
    Diag(AtLoc, diag::err_atimport);
    SkipUntil(tok::semi);
    return Actions.ConvertDeclToDeclGroup(nullptr);
  default:
    Diag(AtLoc, diag::err_unexpected_at);
    SkipUntil(tok::semi);
    SingleDecl = nullptr;
    break;
  }
  return Actions.ConvertDeclToDeclGroup(SingleDecl);
}

/// Class to handle popping type parameters when leaving the scope.
class Parser::ObjCTypeParamListScope {
  Sema &Actions;
  Scope *S;
  ObjCTypeParamList *Params;

public:
  ObjCTypeParamListScope(Sema &Actions, Scope *S)
      : Actions(Actions), S(S), Params(nullptr) {}

  ~ObjCTypeParamListScope() {
    leave();
  }

  void enter(ObjCTypeParamList *P) {
    assert(!Params);
    Params = P;
  }

  void leave() {
    if (Params)
      Actions.popObjCTypeParamList(S, Params);
    Params = nullptr;
  }
};

///
/// objc-class-declaration:
///    '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';'
///
/// objc-class-forward-decl:
///   identifier objc-type-parameter-list[opt]
///
Parser::DeclGroupPtrTy
Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) {
  ConsumeToken(); // the identifier "class"
  SmallVector<IdentifierInfo *, 8> ClassNames;
  SmallVector<SourceLocation, 8> ClassLocs;
  SmallVector<ObjCTypeParamList *, 8> ClassTypeParams;

  while (1) {
    MaybeSkipAttributes(tok::objc_class);
    if (expectIdentifier()) {
      SkipUntil(tok::semi);
      return Actions.ConvertDeclToDeclGroup(nullptr);
    }
    ClassNames.push_back(Tok.getIdentifierInfo());
    ClassLocs.push_back(Tok.getLocation());
    ConsumeToken();

    // Parse the optional objc-type-parameter-list.
    ObjCTypeParamList *TypeParams = nullptr;
    if (Tok.is(tok::less))
      TypeParams = parseObjCTypeParamList();
    ClassTypeParams.push_back(TypeParams);
    if (!TryConsumeToken(tok::comma))
      break;
  }

  // Consume the ';'.
  if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@class"))
    return Actions.ConvertDeclToDeclGroup(nullptr);

  return Actions.ActOnForwardClassDeclaration(atLoc, ClassNames.data(),
                                              ClassLocs.data(),
                                              ClassTypeParams,
                                              ClassNames.size());
}

void Parser::CheckNestedObjCContexts(SourceLocation AtLoc)
{
  Sema::ObjCContainerKind ock = Actions.getObjCContainerKind();
  if (ock == Sema::OCK_None)
    return;

  Decl *Decl = Actions.getObjCDeclContext();
  if (CurParsedObjCImpl) {
    CurParsedObjCImpl->finish(AtLoc);
  } else {
    Actions.ActOnAtEnd(getCurScope(), AtLoc);
  }
  Diag(AtLoc, diag::err_objc_missing_end)
      << FixItHint::CreateInsertion(AtLoc, "@end\n");
  if (Decl)
    Diag(Decl->getBeginLoc(), diag::note_objc_container_start) << (int)ock;
}

///
///   objc-interface:
///     objc-class-interface-attributes[opt] objc-class-interface
///     objc-category-interface
///
///   objc-class-interface:
///     '@' 'interface' identifier objc-type-parameter-list[opt]
///       objc-superclass[opt] objc-protocol-refs[opt]
///       objc-class-instance-variables[opt]
///       objc-interface-decl-list
///     @end
///
///   objc-category-interface:
///     '@' 'interface' identifier objc-type-parameter-list[opt]
///       '(' identifier[opt] ')' objc-protocol-refs[opt]
///       objc-interface-decl-list
///     @end
///
///   objc-superclass:
///     ':' identifier objc-type-arguments[opt]
///
///   objc-class-interface-attributes:
///     __attribute__((visibility("default")))
///     __attribute__((visibility("hidden")))
///     __attribute__((deprecated))
///     __attribute__((unavailable))
///     __attribute__((objc_exception)) - used by NSException on 64-bit
///     __attribute__((objc_root_class))
///
Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc,
                                              ParsedAttributes &attrs) {
  assert(Tok.isObjCAtKeyword(tok::objc_interface) &&
         "ParseObjCAtInterfaceDeclaration(): Expected @interface");
  CheckNestedObjCContexts(AtLoc);
  ConsumeToken(); // the "interface" identifier

  // Code completion after '@interface'.
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCInterfaceDecl(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  MaybeSkipAttributes(tok::objc_interface);

  if (expectIdentifier())
    return nullptr; // missing class or category name.

  // We have a class or category name - consume it.
  IdentifierInfo *nameId = Tok.getIdentifierInfo();
  SourceLocation nameLoc = ConsumeToken();

  // Parse the objc-type-parameter-list or objc-protocol-refs. For the latter
  // case, LAngleLoc will be valid and ProtocolIdents will capture the
  // protocol references (that have not yet been resolved).
  SourceLocation LAngleLoc, EndProtoLoc;
  SmallVector<IdentifierLocPair, 8> ProtocolIdents;
  ObjCTypeParamList *typeParameterList = nullptr;
  ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
  if (Tok.is(tok::less))
    typeParameterList = parseObjCTypeParamListOrProtocolRefs(
        typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc);

  if (Tok.is(tok::l_paren) &&
      !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category.

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

    SourceLocation categoryLoc;
    IdentifierInfo *categoryId = nullptr;
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCInterfaceCategory(getCurScope(), nameId, nameLoc);
      cutOffParsing();
      return nullptr;
    }

    // For ObjC2, the category name is optional (not an error).
    if (Tok.is(tok::identifier)) {
      categoryId = Tok.getIdentifierInfo();
      categoryLoc = ConsumeToken();
    }
    else if (!getLangOpts().ObjC) {
      Diag(Tok, diag::err_expected)
          << tok::identifier; // missing category name.
      return nullptr;
    }

    T.consumeClose();
    if (T.getCloseLocation().isInvalid())
      return nullptr;

    // Next, we need to check for any protocol references.
    assert(LAngleLoc.isInvalid() && "Cannot have already parsed protocols");
    SmallVector<Decl *, 8> ProtocolRefs;
    SmallVector<SourceLocation, 8> ProtocolLocs;
    if (Tok.is(tok::less) &&
        ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, true, true,
                                    LAngleLoc, EndProtoLoc,
                                    /*consumeLastToken=*/true))
      return nullptr;

    Decl *CategoryType = Actions.ActOnStartCategoryInterface(
        AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc,
        ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(),
        EndProtoLoc, attrs);

    if (Tok.is(tok::l_brace))
      ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc);

    ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType);

    return CategoryType;
  }
  // Parse a class interface.
  IdentifierInfo *superClassId = nullptr;
  SourceLocation superClassLoc;
  SourceLocation typeArgsLAngleLoc;
  SmallVector<ParsedType, 4> typeArgs;
  SourceLocation typeArgsRAngleLoc;
  SmallVector<Decl *, 4> protocols;
  SmallVector<SourceLocation, 4> protocolLocs;
  if (Tok.is(tok::colon)) { // a super class is specified.
    ConsumeToken();

    // Code completion of superclass names.
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCSuperclass(getCurScope(), nameId, nameLoc);
      cutOffParsing();
      return nullptr;
    }

    if (expectIdentifier())
      return nullptr; // missing super class name.
    superClassId = Tok.getIdentifierInfo();
    superClassLoc = ConsumeToken();

    // Type arguments for the superclass or protocol conformances.
    if (Tok.is(tok::less)) {
      parseObjCTypeArgsOrProtocolQualifiers(
          nullptr, typeArgsLAngleLoc, typeArgs, typeArgsRAngleLoc, LAngleLoc,
          protocols, protocolLocs, EndProtoLoc,
          /*consumeLastToken=*/true,
          /*warnOnIncompleteProtocols=*/true);
      if (Tok.is(tok::eof))
        return nullptr;
    }
  }

  // Next, we need to check for any protocol references.
  if (LAngleLoc.isValid()) {
    if (!ProtocolIdents.empty()) {
      // We already parsed the protocols named when we thought we had a
      // type parameter list. Translate them into actual protocol references.
      for (const auto &pair : ProtocolIdents) {
        protocolLocs.push_back(pair.second);
      }
      Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true,
                                      /*ForObjCContainer=*/true,
                                      ProtocolIdents, protocols);
    }
  } else if (protocols.empty() && Tok.is(tok::less) &&
             ParseObjCProtocolReferences(protocols, protocolLocs, true, true,
                                         LAngleLoc, EndProtoLoc,
                                         /*consumeLastToken=*/true)) {
    return nullptr;
  }

  if (Tok.isNot(tok::less))
    Actions.ActOnTypedefedProtocols(protocols, protocolLocs,
                                    superClassId, superClassLoc);

  Decl *ClsType = Actions.ActOnStartClassInterface(
      getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId,
      superClassLoc, typeArgs,
      SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(),
      protocols.size(), protocolLocs.data(), EndProtoLoc, attrs);

  if (Tok.is(tok::l_brace))
    ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc);

  ParseObjCInterfaceDeclList(tok::objc_interface, ClsType);

  return ClsType;
}

/// Add an attribute for a context-sensitive type nullability to the given
/// declarator.
static void addContextSensitiveTypeNullability(Parser &P,
                                               Declarator &D,
                                               NullabilityKind nullability,
                                               SourceLocation nullabilityLoc,
                                               bool &addedToDeclSpec) {
  // Create the attribute.
  auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * {
    return Pool.create(P.getNullabilityKeyword(nullability),
                       SourceRange(nullabilityLoc), nullptr, SourceLocation(),
                       nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword);
  };

  if (D.getNumTypeObjects() > 0) {
    // Add the attribute to the declarator chunk nearest the declarator.
    D.getTypeObject(0).getAttrs().addAtEnd(
        getNullabilityAttr(D.getAttributePool()));
  } else if (!addedToDeclSpec) {
    // Otherwise, just put it on the declaration specifiers (if one
    // isn't there already).
    D.getMutableDeclSpec().getAttributes().addAtEnd(
        getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool()));
    addedToDeclSpec = true;
  }
}

/// Parse an Objective-C type parameter list, if present, or capture
/// the locations of the protocol identifiers for a list of protocol
/// references.
///
///   objc-type-parameter-list:
///     '<' objc-type-parameter (',' objc-type-parameter)* '>'
///
///   objc-type-parameter:
///     objc-type-parameter-variance? identifier objc-type-parameter-bound[opt]
///
///   objc-type-parameter-bound:
///     ':' type-name
///
///   objc-type-parameter-variance:
///     '__covariant'
///     '__contravariant'
///
/// \param lAngleLoc The location of the starting '<'.
///
/// \param protocolIdents Will capture the list of identifiers, if the
/// angle brackets contain a list of protocol references rather than a
/// type parameter list.
///
/// \param rAngleLoc The location of the ending '>'.
ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs(
    ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc,
    SmallVectorImpl<IdentifierLocPair> &protocolIdents,
    SourceLocation &rAngleLoc, bool mayBeProtocolList) {
  assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list");

  // Within the type parameter list, don't treat '>' as an operator.
  GreaterThanIsOperatorScope G(GreaterThanIsOperator, false);

  // Local function to "flush" the protocol identifiers, turning them into
  // type parameters.
  SmallVector<Decl *, 4> typeParams;
  auto makeProtocolIdentsIntoTypeParameters = [&]() {
    unsigned index = 0;
    for (const auto &pair : protocolIdents) {
      DeclResult typeParam = Actions.actOnObjCTypeParam(
          getCurScope(), ObjCTypeParamVariance::Invariant, SourceLocation(),
          index++, pair.first, pair.second, SourceLocation(), nullptr);
      if (typeParam.isUsable())
        typeParams.push_back(typeParam.get());
    }

    protocolIdents.clear();
    mayBeProtocolList = false;
  };

  bool invalid = false;
  lAngleLoc = ConsumeToken();

  do {
    // Parse the variance, if any.
    SourceLocation varianceLoc;
    ObjCTypeParamVariance variance = ObjCTypeParamVariance::Invariant;
    if (Tok.is(tok::kw___covariant) || Tok.is(tok::kw___contravariant)) {
      variance = Tok.is(tok::kw___covariant)
                   ? ObjCTypeParamVariance::Covariant
                   : ObjCTypeParamVariance::Contravariant;
      varianceLoc = ConsumeToken();

      // Once we've seen a variance specific , we know this is not a
      // list of protocol references.
      if (mayBeProtocolList) {
        // Up until now, we have been queuing up parameters because they
        // might be protocol references. Turn them into parameters now.
        makeProtocolIdentsIntoTypeParameters();
      }
    }

    // Parse the identifier.
    if (!Tok.is(tok::identifier)) {
      // Code completion.
      if (Tok.is(tok::code_completion)) {
        // FIXME: If these aren't protocol references, we'll need different
        // completions.
        Actions.CodeCompleteObjCProtocolReferences(protocolIdents);
        cutOffParsing();

        // FIXME: Better recovery here?.
        return nullptr;
      }

      Diag(Tok, diag::err_objc_expected_type_parameter);
      invalid = true;
      break;
    }

    IdentifierInfo *paramName = Tok.getIdentifierInfo();
    SourceLocation paramLoc = ConsumeToken();

    // If there is a bound, parse it.
    SourceLocation colonLoc;
    TypeResult boundType;
    if (TryConsumeToken(tok::colon, colonLoc)) {
      // Once we've seen a bound, we know this is not a list of protocol
      // references.
      if (mayBeProtocolList) {
        // Up until now, we have been queuing up parameters because they
        // might be protocol references. Turn them into parameters now.
        makeProtocolIdentsIntoTypeParameters();
      }

      // type-name
      boundType = ParseTypeName();
      if (boundType.isInvalid())
        invalid = true;
    } else if (mayBeProtocolList) {
      // If this could still be a protocol list, just capture the identifier.
      // We don't want to turn it into a parameter.
      protocolIdents.push_back(std::make_pair(paramName, paramLoc));
      continue;
    }

    // Create the type parameter.
    DeclResult typeParam = Actions.actOnObjCTypeParam(
        getCurScope(), variance, varianceLoc, typeParams.size(), paramName,
        paramLoc, colonLoc, boundType.isUsable() ? boundType.get() : nullptr);
    if (typeParam.isUsable())
      typeParams.push_back(typeParam.get());
  } while (TryConsumeToken(tok::comma));

  // Parse the '>'.
  if (invalid) {
    SkipUntil(tok::greater, tok::at, StopBeforeMatch);
    if (Tok.is(tok::greater))
      ConsumeToken();
  } else if (ParseGreaterThanInTemplateList(rAngleLoc,
                                            /*ConsumeLastToken=*/true,
                                            /*ObjCGenericList=*/true)) {
    Diag(lAngleLoc, diag::note_matching) << "'<'";
    SkipUntil({tok::greater, tok::greaterequal, tok::at, tok::minus,
               tok::minus, tok::plus, tok::colon, tok::l_paren, tok::l_brace,
               tok::comma, tok::semi },
              StopBeforeMatch);
    if (Tok.is(tok::greater))
      ConsumeToken();
  }

  if (mayBeProtocolList) {
    // A type parameter list must be followed by either a ':' (indicating the
    // presence of a superclass) or a '(' (indicating that this is a category
    // or extension). This disambiguates between an objc-type-parameter-list
    // and a objc-protocol-refs.
    if (Tok.isNot(tok::colon) && Tok.isNot(tok::l_paren)) {
      // Returning null indicates that we don't have a type parameter list.
      // The results the caller needs to handle the protocol references are
      // captured in the reference parameters already.
      return nullptr;
    }

    // We have a type parameter list that looks like a list of protocol
    // references. Turn that parameter list into type parameters.
    makeProtocolIdentsIntoTypeParameters();
  }

  // Form the type parameter list and enter its scope.
  ObjCTypeParamList *list = Actions.actOnObjCTypeParamList(
                              getCurScope(),
                              lAngleLoc,
                              typeParams,
                              rAngleLoc);
  Scope.enter(list);

  // Clear out the angle locations; they're used by the caller to indicate
  // whether there are any protocol references.
  lAngleLoc = SourceLocation();
  rAngleLoc = SourceLocation();
  return invalid ? nullptr : list;
}

/// Parse an objc-type-parameter-list.
ObjCTypeParamList *Parser::parseObjCTypeParamList() {
  SourceLocation lAngleLoc;
  SmallVector<IdentifierLocPair, 1> protocolIdents;
  SourceLocation rAngleLoc;

  ObjCTypeParamListScope Scope(Actions, getCurScope());
  return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents,
                                              rAngleLoc,
                                              /*mayBeProtocolList=*/false);
}

///   objc-interface-decl-list:
///     empty
///     objc-interface-decl-list objc-property-decl [OBJC2]
///     objc-interface-decl-list objc-method-requirement [OBJC2]
///     objc-interface-decl-list objc-method-proto ';'
///     objc-interface-decl-list declaration
///     objc-interface-decl-list ';'
///
///   objc-method-requirement: [OBJC2]
///     @required
///     @optional
///
void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey,
                                        Decl *CDecl) {
  SmallVector<Decl *, 32> allMethods;
  SmallVector<DeclGroupPtrTy, 8> allTUVariables;
  tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword;

  SourceRange AtEnd;

  while (1) {
    // If this is a method prototype, parse it.
    if (Tok.isOneOf(tok::minus, tok::plus)) {
      if (Decl *methodPrototype =
          ParseObjCMethodPrototype(MethodImplKind, false))
        allMethods.push_back(methodPrototype);
      // Consume the ';' here, since ParseObjCMethodPrototype() is re-used for
      // method definitions.
      if (ExpectAndConsumeSemi(diag::err_expected_semi_after_method_proto)) {
        // We didn't find a semi and we error'ed out. Skip until a ';' or '@'.
        SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
        if (Tok.is(tok::semi))
          ConsumeToken();
      }
      continue;
    }
    if (Tok.is(tok::l_paren)) {
      Diag(Tok, diag::err_expected_minus_or_plus);
      ParseObjCMethodDecl(Tok.getLocation(),
                          tok::minus,
                          MethodImplKind, false);
      continue;
    }
    // Ignore excess semicolons.
    if (Tok.is(tok::semi)) {
      // FIXME: This should use ConsumeExtraSemi() for extraneous semicolons,
      // to make -Wextra-semi diagnose them.
      ConsumeToken();
      continue;
    }

    // If we got to the end of the file, exit the loop.
    if (isEofOrEom())
      break;

    // Code completion within an Objective-C interface.
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteOrdinaryName(getCurScope(),
                            CurParsedObjCImpl? Sema::PCC_ObjCImplementation
                                             : Sema::PCC_ObjCInterface);
      return cutOffParsing();
    }

    // If we don't have an @ directive, parse it as a function definition.
    if (Tok.isNot(tok::at)) {
      // The code below does not consume '}'s because it is afraid of eating the
      // end of a namespace.  Because of the way this code is structured, an
      // erroneous r_brace would cause an infinite loop if not handled here.
      if (Tok.is(tok::r_brace))
        break;

      ParsedAttributesWithRange attrs(AttrFactory);

      // Since we call ParseDeclarationOrFunctionDefinition() instead of
      // ParseExternalDeclaration() below (so that this doesn't parse nested
      // @interfaces), this needs to duplicate some code from the latter.
      if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
        SourceLocation DeclEnd;
        allTUVariables.push_back(
            ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs));
        continue;
      }

      allTUVariables.push_back(ParseDeclarationOrFunctionDefinition(attrs));
      continue;
    }

    // Otherwise, we have an @ directive, eat the @.
    SourceLocation AtLoc = ConsumeToken(); // the "@"
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCAtDirective(getCurScope());
      return cutOffParsing();
    }

    tok::ObjCKeywordKind DirectiveKind = Tok.getObjCKeywordID();

    if (DirectiveKind == tok::objc_end) { // @end -> terminate list
      AtEnd.setBegin(AtLoc);
      AtEnd.setEnd(Tok.getLocation());
      break;
    } else if (DirectiveKind == tok::objc_not_keyword) {
      Diag(Tok, diag::err_objc_unknown_at);
      SkipUntil(tok::semi);
      continue;
    }

    // Eat the identifier.
    ConsumeToken();

    switch (DirectiveKind) {
    default:
      // FIXME: If someone forgets an @end on a protocol, this loop will
      // continue to eat up tons of stuff and spew lots of nonsense errors.  It
      // would probably be better to bail out if we saw an @class or @interface
      // or something like that.
      Diag(AtLoc, diag::err_objc_illegal_interface_qual);
      // Skip until we see an '@' or '}' or ';'.
      SkipUntil(tok::r_brace, tok::at, StopAtSemi);
      break;

    case tok::objc_implementation:
    case tok::objc_interface:
      Diag(AtLoc, diag::err_objc_missing_end)
          << FixItHint::CreateInsertion(AtLoc, "@end\n");
      Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
          << (int)Actions.getObjCContainerKind();
      ConsumeToken();
      break;

    case tok::objc_required:
    case tok::objc_optional:
      // This is only valid on protocols.
      // FIXME: Should this check for ObjC2 being enabled?
      if (contextKey != tok::objc_protocol)
        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
      else
        MethodImplKind = DirectiveKind;
      break;

    case tok::objc_property:
      if (!getLangOpts().ObjC)
        Diag(AtLoc, diag::err_objc_properties_require_objc2);

      ObjCDeclSpec OCDS;
      SourceLocation LParenLoc;
      // Parse property attribute list, if any.
      if (Tok.is(tok::l_paren)) {
        LParenLoc = Tok.getLocation();
        ParseObjCPropertyAttribute(OCDS);
      }

      bool addedToDeclSpec = false;
      auto ObjCPropertyCallback = [&](ParsingFieldDeclarator &FD) {
        if (FD.D.getIdentifier() == nullptr) {
          Diag(AtLoc, diag::err_objc_property_requires_field_name)
              << FD.D.getSourceRange();
          return;
        }
        if (FD.BitfieldSize) {
          Diag(AtLoc, diag::err_objc_property_bitfield)
              << FD.D.getSourceRange();
          return;
        }

        // Map a nullability property attribute to a context-sensitive keyword
        // attribute.
        if (OCDS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
          addContextSensitiveTypeNullability(*this, FD.D, OCDS.getNullability(),
                                             OCDS.getNullabilityLoc(),
                                             addedToDeclSpec);

        // Install the property declarator into interfaceDecl.
        IdentifierInfo *SelName =
            OCDS.getGetterName() ? OCDS.getGetterName() : FD.D.getIdentifier();

        Selector GetterSel = PP.getSelectorTable().getNullarySelector(SelName);
        IdentifierInfo *SetterName = OCDS.getSetterName();
        Selector SetterSel;
        if (SetterName)
          SetterSel = PP.getSelectorTable().getSelector(1, &SetterName);
        else
          SetterSel = SelectorTable::constructSetterSelector(
              PP.getIdentifierTable(), PP.getSelectorTable(),
              FD.D.getIdentifier());
        Decl *Property = Actions.ActOnProperty(
            getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel,
            MethodImplKind);

        FD.complete(Property);
      };

      // Parse all the comma separated declarators.
      ParsingDeclSpec DS(*this);
      ParseStructDeclaration(DS, ObjCPropertyCallback);

      ExpectAndConsume(tok::semi, diag::err_expected_semi_decl_list);
      break;
    }
  }

  // We break out of the big loop in two cases: when we see @end or when we see
  // EOF.  In the former case, eat the @end.  In the later case, emit an error.
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCAtDirective(getCurScope());
    return cutOffParsing();
  } else if (Tok.isObjCAtKeyword(tok::objc_end)) {
    ConsumeToken(); // the "end" identifier
  } else {
    Diag(Tok, diag::err_objc_missing_end)
        << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
    Diag(CDecl->getBeginLoc(), diag::note_objc_container_start)
        << (int)Actions.getObjCContainerKind();
    AtEnd.setBegin(Tok.getLocation());
    AtEnd.setEnd(Tok.getLocation());
  }

  // Insert collected methods declarations into the @interface object.
  // This passes in an invalid SourceLocation for AtEndLoc when EOF is hit.
  Actions.ActOnAtEnd(getCurScope(), AtEnd, allMethods, allTUVariables);
}

/// Diagnose redundant or conflicting nullability information.
static void diagnoseRedundantPropertyNullability(Parser &P,
                                                 ObjCDeclSpec &DS,
                                                 NullabilityKind nullability,
                                                 SourceLocation nullabilityLoc){
  if (DS.getNullability() == nullability) {
    P.Diag(nullabilityLoc, diag::warn_nullability_duplicate)
      << DiagNullabilityKind(nullability, true)
      << SourceRange(DS.getNullabilityLoc());
    return;
  }

  P.Diag(nullabilityLoc, diag::err_nullability_conflicting)
    << DiagNullabilityKind(nullability, true)
    << DiagNullabilityKind(DS.getNullability(), true)
    << SourceRange(DS.getNullabilityLoc());
}

///   Parse property attribute declarations.
///
///   property-attr-decl: '(' property-attrlist ')'
///   property-attrlist:
///     property-attribute
///     property-attrlist ',' property-attribute
///   property-attribute:
///     getter '=' identifier
///     setter '=' identifier ':'
///     readonly
///     readwrite
///     assign
///     retain
///     copy
///     nonatomic
///     atomic
///     strong
///     weak
///     unsafe_unretained
///     nonnull
///     nullable
///     null_unspecified
///     null_resettable
///     class
///
void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {
  assert(Tok.getKind() == tok::l_paren);
  BalancedDelimiterTracker T(*this, tok::l_paren);
  T.consumeOpen();

  while (1) {
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCPropertyFlags(getCurScope(), DS);
      return cutOffParsing();
    }
    const IdentifierInfo *II = Tok.getIdentifierInfo();

    // If this is not an identifier at all, bail out early.
    if (!II) {
      T.consumeClose();
      return;
    }

    SourceLocation AttrName = ConsumeToken(); // consume last attribute name

    if (II->isStr("readonly"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readonly);
    else if (II->isStr("assign"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_assign);
    else if (II->isStr("unsafe_unretained"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_unsafe_unretained);
    else if (II->isStr("readwrite"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_readwrite);
    else if (II->isStr("retain"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_retain);
    else if (II->isStr("strong"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_strong);
    else if (II->isStr("copy"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_copy);
    else if (II->isStr("nonatomic"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nonatomic);
    else if (II->isStr("atomic"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_atomic);
    else if (II->isStr("weak"))
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_weak);
    else if (II->isStr("getter") || II->isStr("setter")) {
      bool IsSetter = II->getNameStart()[0] == 's';

      // getter/setter require extra treatment.
      unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter :
                                   diag::err_objc_expected_equal_for_getter;

      if (ExpectAndConsume(tok::equal, DiagID)) {
        SkipUntil(tok::r_paren, StopAtSemi);
        return;
      }

      if (Tok.is(tok::code_completion)) {
        if (IsSetter)
          Actions.CodeCompleteObjCPropertySetter(getCurScope());
        else
          Actions.CodeCompleteObjCPropertyGetter(getCurScope());
        return cutOffParsing();
      }

      SourceLocation SelLoc;
      IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc);

      if (!SelIdent) {
        Diag(Tok, diag::err_objc_expected_selector_for_getter_setter)
          << IsSetter;
        SkipUntil(tok::r_paren, StopAtSemi);
        return;
      }

      if (IsSetter) {
        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);
        DS.setSetterName(SelIdent, SelLoc);

        if (ExpectAndConsume(tok::colon,
                             diag::err_expected_colon_after_setter_name)) {
          SkipUntil(tok::r_paren, StopAtSemi);
          return;
        }
      } else {
        DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_getter);
        DS.setGetterName(SelIdent, SelLoc);
      }
    } else if (II->isStr("nonnull")) {
      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
        diagnoseRedundantPropertyNullability(*this, DS,
                                             NullabilityKind::NonNull,
                                             Tok.getLocation());
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
      DS.setNullability(Tok.getLocation(), NullabilityKind::NonNull);
    } else if (II->isStr("nullable")) {
      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
        diagnoseRedundantPropertyNullability(*this, DS,
                                             NullabilityKind::Nullable,
                                             Tok.getLocation());
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
      DS.setNullability(Tok.getLocation(), NullabilityKind::Nullable);
    } else if (II->isStr("null_unspecified")) {
      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
        diagnoseRedundantPropertyNullability(*this, DS,
                                             NullabilityKind::Unspecified,
                                             Tok.getLocation());
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
      DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);
    } else if (II->isStr("null_resettable")) {
      if (DS.getPropertyAttributes() & ObjCDeclSpec::DQ_PR_nullability)
        diagnoseRedundantPropertyNullability(*this, DS,
                                             NullabilityKind::Unspecified,
                                             Tok.getLocation());
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_nullability);
      DS.setNullability(Tok.getLocation(), NullabilityKind::Unspecified);

      // Also set the null_resettable bit.
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_null_resettable);
    } else if (II->isStr("class")) {
      DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_class);
    } else {
      Diag(AttrName, diag::err_objc_expected_property_attr) << II;
      SkipUntil(tok::r_paren, StopAtSemi);
      return;
    }

    if (Tok.isNot(tok::comma))
      break;

    ConsumeToken();
  }

  T.consumeClose();
}

///   objc-method-proto:
///     objc-instance-method objc-method-decl objc-method-attributes[opt]
///     objc-class-method objc-method-decl objc-method-attributes[opt]
///
///   objc-instance-method: '-'
///   objc-class-method: '+'
///
///   objc-method-attributes:         [OBJC2]
///     __attribute__((deprecated))
///
Decl *Parser::ParseObjCMethodPrototype(tok::ObjCKeywordKind MethodImplKind,
                                       bool MethodDefinition) {
  assert(Tok.isOneOf(tok::minus, tok::plus) && "expected +/-");

  tok::TokenKind methodType = Tok.getKind();
  SourceLocation mLoc = ConsumeToken();
  Decl *MDecl = ParseObjCMethodDecl(mLoc, methodType, MethodImplKind,
                                    MethodDefinition);
  // Since this rule is used for both method declarations and definitions,
  // the caller is (optionally) responsible for consuming the ';'.
  return MDecl;
}

///   objc-selector:
///     identifier
///     one of
///       enum struct union if else while do for switch case default
///       break continue return goto asm sizeof typeof __alignof
///       unsigned long const short volatile signed restrict _Complex
///       in out inout bycopy byref oneway int char float double void _Bool
///
IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) {

  switch (Tok.getKind()) {
  default:
    return nullptr;
  case tok::colon:
    // Empty selector piece uses the location of the ':'.
    SelectorLoc = Tok.getLocation();
    return nullptr;
  case tok::ampamp:
  case tok::ampequal:
  case tok::amp:
  case tok::pipe:
  case tok::tilde:
  case tok::exclaim:
  case tok::exclaimequal:
  case tok::pipepipe:
  case tok::pipeequal:
  case tok::caret:
  case tok::caretequal: {
    std::string ThisTok(PP.getSpelling(Tok));
    if (isLetter(ThisTok[0])) {
      IdentifierInfo *II = &PP.getIdentifierTable().get(ThisTok);
      Tok.setKind(tok::identifier);
      SelectorLoc = ConsumeToken();
      return II;
    }
    return nullptr;
  }

  case tok::identifier:
  case tok::kw_asm:
  case tok::kw_auto:
  case tok::kw_bool:
  case tok::kw_break:
  case tok::kw_case:
  case tok::kw_catch:
  case tok::kw_char:
  case tok::kw_class:
  case tok::kw_const:
  case tok::kw_const_cast:
  case tok::kw_continue:
  case tok::kw_default:
  case tok::kw_delete:
  case tok::kw_do:
  case tok::kw_double:
  case tok::kw_dynamic_cast:
  case tok::kw_else:
  case tok::kw_enum:
  case tok::kw_explicit:
  case tok::kw_export:
  case tok::kw_extern:
  case tok::kw_false:
  case tok::kw_float:
  case tok::kw_for:
  case tok::kw_friend:
  case tok::kw_goto:
  case tok::kw_if:
  case tok::kw_inline:
  case tok::kw_int:
  case tok::kw_long:
  case tok::kw_mutable:
  case tok::kw_namespace:
  case tok::kw_new:
  case tok::kw_operator:
  case tok::kw_private:
  case tok::kw_protected:
  case tok::kw_public:
  case tok::kw_register:
  case tok::kw_reinterpret_cast:
  case tok::kw_restrict:
  case tok::kw_return:
  case tok::kw_short:
  case tok::kw_signed:
  case tok::kw_sizeof:
  case tok::kw_static:
  case tok::kw_static_cast:
  case tok::kw_struct:
  case tok::kw_switch:
  case tok::kw_template:
  case tok::kw_this:
  case tok::kw_throw:
  case tok::kw_true:
  case tok::kw_try:
  case tok::kw_typedef:
  case tok::kw_typeid:
  case tok::kw_typename:
  case tok::kw_typeof:
  case tok::kw_union:
  case tok::kw_unsigned:
  case tok::kw_using:
  case tok::kw_virtual:
  case tok::kw_void:
  case tok::kw_volatile:
  case tok::kw_wchar_t:
  case tok::kw_while:
  case tok::kw__Bool:
  case tok::kw__Complex:
  case tok::kw___alignof:
  case tok::kw___auto_type:
    IdentifierInfo *II = Tok.getIdentifierInfo();
    SelectorLoc = ConsumeToken();
    return II;
  }
}

///  objc-for-collection-in: 'in'
///
bool Parser::isTokIdentifier_in() const {
  // FIXME: May have to do additional look-ahead to only allow for
  // valid tokens following an 'in'; such as an identifier, unary operators,
  // '[' etc.
  return (getLangOpts().ObjC && Tok.is(tok::identifier) &&
          Tok.getIdentifierInfo() == ObjCTypeQuals[objc_in]);
}

/// ParseObjCTypeQualifierList - This routine parses the objective-c's type
/// qualifier list and builds their bitmask representation in the input
/// argument.
///
///   objc-type-qualifiers:
///     objc-type-qualifier
///     objc-type-qualifiers objc-type-qualifier
///
///   objc-type-qualifier:
///     'in'
///     'out'
///     'inout'
///     'oneway'
///     'bycopy'
///     'byref'
///     'nonnull'
///     'nullable'
///     'null_unspecified'
///
void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS,
                                        DeclaratorContext Context) {
  assert(Context == DeclaratorContext::ObjCParameterContext ||
         Context == DeclaratorContext::ObjCResultContext);

  while (1) {
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCPassingType(getCurScope(), DS,
                          Context == DeclaratorContext::ObjCParameterContext);
      return cutOffParsing();
    }

    if (Tok.isNot(tok::identifier))
      return;

    const IdentifierInfo *II = Tok.getIdentifierInfo();
    for (unsigned i = 0; i != objc_NumQuals; ++i) {
      if (II != ObjCTypeQuals[i] ||
          NextToken().is(tok::less) ||
          NextToken().is(tok::coloncolon))
        continue;

      ObjCDeclSpec::ObjCDeclQualifier Qual;
      NullabilityKind Nullability;
      switch (i) {
      default: llvm_unreachable("Unknown decl qualifier");
      case objc_in:     Qual = ObjCDeclSpec::DQ_In; break;
      case objc_out:    Qual = ObjCDeclSpec::DQ_Out; break;
      case objc_inout:  Qual = ObjCDeclSpec::DQ_Inout; break;
      case objc_oneway: Qual = ObjCDeclSpec::DQ_Oneway; break;
      case objc_bycopy: Qual = ObjCDeclSpec::DQ_Bycopy; break;
      case objc_byref:  Qual = ObjCDeclSpec::DQ_Byref; break;

      case objc_nonnull:
        Qual = ObjCDeclSpec::DQ_CSNullability;
        Nullability = NullabilityKind::NonNull;
        break;

      case objc_nullable:
        Qual = ObjCDeclSpec::DQ_CSNullability;
        Nullability = NullabilityKind::Nullable;
        break;

      case objc_null_unspecified:
        Qual = ObjCDeclSpec::DQ_CSNullability;
        Nullability = NullabilityKind::Unspecified;
        break;
      }

      // FIXME: Diagnose redundant specifiers.
      DS.setObjCDeclQualifier(Qual);
      if (Qual == ObjCDeclSpec::DQ_CSNullability)
        DS.setNullability(Tok.getLocation(), Nullability);

      ConsumeToken();
      II = nullptr;
      break;
    }

    // If this wasn't a recognized qualifier, bail out.
    if (II) return;
  }
}

/// Take all the decl attributes out of the given list and add
/// them to the given attribute set.
static void takeDeclAttributes(ParsedAttributesView &attrs,
                               ParsedAttributesView &from) {
  for (auto &AL : llvm::reverse(from)) {
    if (!AL.isUsedAsTypeAttr()) {
      from.remove(&AL);
      attrs.addAtEnd(&AL);
    }
  }
}

/// takeDeclAttributes - Take all the decl attributes from the given
/// declarator and add them to the given list.
static void takeDeclAttributes(ParsedAttributes &attrs,
                               Declarator &D) {
  // First, take ownership of all attributes.
  attrs.getPool().takeAllFrom(D.getAttributePool());
  attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool());

  // Now actually move the attributes over.
  takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes());
  takeDeclAttributes(attrs, D.getAttributes());
  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
    takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs());
}

///   objc-type-name:
///     '(' objc-type-qualifiers[opt] type-name ')'
///     '(' objc-type-qualifiers[opt] ')'
///
ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS,
                                     DeclaratorContext context,
                                     ParsedAttributes *paramAttrs) {
  assert(context == DeclaratorContext::ObjCParameterContext ||
         context == DeclaratorContext::ObjCResultContext);
  assert((paramAttrs != nullptr) ==
         (context == DeclaratorContext::ObjCParameterContext));

  assert(Tok.is(tok::l_paren) && "expected (");

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

  SourceLocation TypeStartLoc = Tok.getLocation();
  ObjCDeclContextSwitch ObjCDC(*this);

  // Parse type qualifiers, in, inout, etc.
  ParseObjCTypeQualifierList(DS, context);

  ParsedType Ty;
  if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
    // Parse an abstract declarator.
    DeclSpec declSpec(AttrFactory);
    declSpec.setObjCQualifiers(&DS);
    DeclSpecContext dsContext = DeclSpecContext::DSC_normal;
    if (context == DeclaratorContext::ObjCResultContext)
      dsContext = DeclSpecContext::DSC_objc_method_result;
    ParseSpecifierQualifierList(declSpec, AS_none, dsContext);
    Declarator declarator(declSpec, context);
    ParseDeclarator(declarator);

    // If that's not invalid, extract a type.
    if (!declarator.isInvalidType()) {
      // Map a nullability specifier to a context-sensitive keyword attribute.
      bool addedToDeclSpec = false;
      if (DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability)
        addContextSensitiveTypeNullability(*this, declarator,
                                           DS.getNullability(),
                                           DS.getNullabilityLoc(),
                                           addedToDeclSpec);

      TypeResult type = Actions.ActOnTypeName(getCurScope(), declarator);
      if (!type.isInvalid())
        Ty = type.get();

      // If we're parsing a parameter, steal all the decl attributes
      // and add them to the decl spec.
      if (context == DeclaratorContext::ObjCParameterContext)
        takeDeclAttributes(*paramAttrs, declarator);
    }
  }

  if (Tok.is(tok::r_paren))
    T.consumeClose();
  else if (Tok.getLocation() == TypeStartLoc) {
    // If we didn't eat any tokens, then this isn't a type.
    Diag(Tok, diag::err_expected_type);
    SkipUntil(tok::r_paren, StopAtSemi);
  } else {
    // Otherwise, we found *something*, but didn't get a ')' in the right
    // place.  Emit an error then return what we have as the type.
    T.consumeClose();
  }
  return Ty;
}

///   objc-method-decl:
///     objc-selector
///     objc-keyword-selector objc-parmlist[opt]
///     objc-type-name objc-selector
///     objc-type-name objc-keyword-selector objc-parmlist[opt]
///
///   objc-keyword-selector:
///     objc-keyword-decl
///     objc-keyword-selector objc-keyword-decl
///
///   objc-keyword-decl:
///     objc-selector ':' objc-type-name objc-keyword-attributes[opt] identifier
///     objc-selector ':' objc-keyword-attributes[opt] identifier
///     ':' objc-type-name objc-keyword-attributes[opt] identifier
///     ':' objc-keyword-attributes[opt] identifier
///
///   objc-parmlist:
///     objc-parms objc-ellipsis[opt]
///
///   objc-parms:
///     objc-parms , parameter-declaration
///
///   objc-ellipsis:
///     , ...
///
///   objc-keyword-attributes:         [OBJC2]
///     __attribute__((unused))
///
Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc,
                                  tok::TokenKind mType,
                                  tok::ObjCKeywordKind MethodImplKind,
                                  bool MethodDefinition) {
  ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
                                       /*ReturnType=*/nullptr);
    cutOffParsing();
    return nullptr;
  }

  // Parse the return type if present.
  ParsedType ReturnType;
  ObjCDeclSpec DSRet;
  if (Tok.is(tok::l_paren))
    ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext,
                                   nullptr);

  // If attributes exist before the method, parse them.
  ParsedAttributes methodAttrs(AttrFactory);
  if (getLangOpts().ObjC)
    MaybeParseGNUAttributes(methodAttrs);
  MaybeParseCXX11Attributes(methodAttrs);

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus,
                                       ReturnType);
    cutOffParsing();
    return nullptr;
  }

  // Now parse the selector.
  SourceLocation selLoc;
  IdentifierInfo *SelIdent = ParseObjCSelectorPiece(selLoc);

  // An unnamed colon is valid.
  if (!SelIdent && Tok.isNot(tok::colon)) { // missing selector name.
    Diag(Tok, diag::err_expected_selector_for_method)
      << SourceRange(mLoc, Tok.getLocation());
    // Skip until we get a ; or @.
    SkipUntil(tok::at, StopAtSemi | StopBeforeMatch);
    return nullptr;
  }

  SmallVector<DeclaratorChunk::ParamInfo, 8> CParamInfo;
  if (Tok.isNot(tok::colon)) {
    // If attributes exist after the method, parse them.
    if (getLangOpts().ObjC)
      MaybeParseGNUAttributes(methodAttrs);
    MaybeParseCXX11Attributes(methodAttrs);

    Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent);
    Decl *Result = Actions.ActOnMethodDeclaration(
        getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType,
        selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs,
        MethodImplKind, false, MethodDefinition);
    PD.complete(Result);
    return Result;
  }

  SmallVector<IdentifierInfo *, 12> KeyIdents;
  SmallVector<SourceLocation, 12> KeyLocs;
  SmallVector<Sema::ObjCArgInfo, 12> ArgInfos;
  ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope |
                            Scope::FunctionDeclarationScope | Scope::DeclScope);

  AttributePool allParamAttrs(AttrFactory);
  while (1) {
    ParsedAttributes paramAttrs(AttrFactory);
    Sema::ObjCArgInfo ArgInfo;

    // Each iteration parses a single keyword argument.
    if (ExpectAndConsume(tok::colon))
      break;

    ArgInfo.Type = nullptr;
    if (Tok.is(tok::l_paren)) // Parse the argument type if present.
      ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec,
                                       DeclaratorContext::ObjCParameterContext,
                                       &paramAttrs);

    // If attributes exist before the argument name, parse them.
    // Regardless, collect all the attributes we've parsed so far.
    if (getLangOpts().ObjC)
      MaybeParseGNUAttributes(paramAttrs);
    MaybeParseCXX11Attributes(paramAttrs);
    ArgInfo.ArgAttrs = paramAttrs;

    // Code completion for the next piece of the selector.
    if (Tok.is(tok::code_completion)) {
      KeyIdents.push_back(SelIdent);
      Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
                                                 mType == tok::minus,
                                                 /*AtParameterName=*/true,
                                                 ReturnType, KeyIdents);
      cutOffParsing();
      return nullptr;
    }

    if (expectIdentifier())
      break; // missing argument name.

    ArgInfo.Name = Tok.getIdentifierInfo();
    ArgInfo.NameLoc = Tok.getLocation();
    ConsumeToken(); // Eat the identifier.

    ArgInfos.push_back(ArgInfo);
    KeyIdents.push_back(SelIdent);
    KeyLocs.push_back(selLoc);

    // Make sure the attributes persist.
    allParamAttrs.takeAllFrom(paramAttrs.getPool());

    // Code completion for the next piece of the selector.
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCMethodDeclSelector(getCurScope(),
                                                 mType == tok::minus,
                                                 /*AtParameterName=*/false,
                                                 ReturnType, KeyIdents);
      cutOffParsing();
      return nullptr;
    }

    // Check for another keyword selector.
    SelIdent = ParseObjCSelectorPiece(selLoc);
    if (!SelIdent && Tok.isNot(tok::colon))
      break;
    if (!SelIdent) {
      SourceLocation ColonLoc = Tok.getLocation();
      if (PP.getLocForEndOfToken(ArgInfo.NameLoc) == ColonLoc) {
        Diag(ArgInfo.NameLoc, diag::warn_missing_selector_name) << ArgInfo.Name;
        Diag(ArgInfo.NameLoc, diag::note_missing_selector_name) << ArgInfo.Name;
        Diag(ColonLoc, diag::note_force_empty_selector_name) << ArgInfo.Name;
      }
    }
    // We have a selector or a colon, continue parsing.
  }

  bool isVariadic = false;
  bool cStyleParamWarned = false;
  // Parse the (optional) parameter list.
  while (Tok.is(tok::comma)) {
    ConsumeToken();
    if (Tok.is(tok::ellipsis)) {
      isVariadic = true;
      ConsumeToken();
      break;
    }
    if (!cStyleParamWarned) {
      Diag(Tok, diag::warn_cstyle_param);
      cStyleParamWarned = true;
    }
    DeclSpec DS(AttrFactory);
    ParseDeclarationSpecifiers(DS);
    // Parse the declarator.
    Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext);
    ParseDeclarator(ParmDecl);
    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
    Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
    CParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
                                                    ParmDecl.getIdentifierLoc(),
                                                    Param,
                                                    nullptr));
  }

  // FIXME: Add support for optional parameter list...
  // If attributes exist after the method, parse them.
  if (getLangOpts().ObjC)
    MaybeParseGNUAttributes(methodAttrs);
  MaybeParseCXX11Attributes(methodAttrs);

  if (KeyIdents.size() == 0)
    return nullptr;

  Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(),
                                                   &KeyIdents[0]);
  Decl *Result = Actions.ActOnMethodDeclaration(
      getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs,
      Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs,
      MethodImplKind, isVariadic, MethodDefinition);

  PD.complete(Result);
  return Result;
}

///   objc-protocol-refs:
///     '<' identifier-list '>'
///
bool Parser::
ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols,
                            SmallVectorImpl<SourceLocation> &ProtocolLocs,
                            bool WarnOnDeclarations, bool ForObjCContainer,
                            SourceLocation &LAngleLoc, SourceLocation &EndLoc,
                            bool consumeLastToken) {
  assert(Tok.is(tok::less) && "expected <");

  LAngleLoc = ConsumeToken(); // the "<"

  SmallVector<IdentifierLocPair, 8> ProtocolIdents;

  while (1) {
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents);
      cutOffParsing();
      return true;
    }

    if (expectIdentifier()) {
      SkipUntil(tok::greater, StopAtSemi);
      return true;
    }
    ProtocolIdents.push_back(std::make_pair(Tok.getIdentifierInfo(),
                                       Tok.getLocation()));
    ProtocolLocs.push_back(Tok.getLocation());
    ConsumeToken();

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

  // Consume the '>'.
  if (ParseGreaterThanInTemplateList(EndLoc, consumeLastToken,
                                     /*ObjCGenericList=*/false))
    return true;

  // Convert the list of protocols identifiers into a list of protocol decls.
  Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer,
                                  ProtocolIdents, Protocols);
  return false;
}

TypeResult Parser::parseObjCProtocolQualifierType(SourceLocation &rAngleLoc) {
  assert(Tok.is(tok::less) && "Protocol qualifiers start with '<'");
  assert(getLangOpts().ObjC && "Protocol qualifiers only exist in Objective-C");

  SourceLocation lAngleLoc;
  SmallVector<Decl *, 8> protocols;
  SmallVector<SourceLocation, 8> protocolLocs;
  (void)ParseObjCProtocolReferences(protocols, protocolLocs, false, false,
                                    lAngleLoc, rAngleLoc,
                                    /*consumeLastToken=*/true);
  TypeResult result = Actions.actOnObjCProtocolQualifierType(lAngleLoc,
                                                             protocols,
                                                             protocolLocs,
                                                             rAngleLoc);
  if (result.isUsable()) {
    Diag(lAngleLoc, diag::warn_objc_protocol_qualifier_missing_id)
      << FixItHint::CreateInsertion(lAngleLoc, "id")
      << SourceRange(lAngleLoc, rAngleLoc);
  }

  return result;
}

/// Parse Objective-C type arguments or protocol qualifiers.
///
///   objc-type-arguments:
///     '<' type-name '...'[opt] (',' type-name '...'[opt])* '>'
///
void Parser::parseObjCTypeArgsOrProtocolQualifiers(
       ParsedType baseType,
       SourceLocation &typeArgsLAngleLoc,
       SmallVectorImpl<ParsedType> &typeArgs,
       SourceLocation &typeArgsRAngleLoc,
       SourceLocation &protocolLAngleLoc,
       SmallVectorImpl<Decl *> &protocols,
       SmallVectorImpl<SourceLocation> &protocolLocs,
       SourceLocation &protocolRAngleLoc,
       bool consumeLastToken,
       bool warnOnIncompleteProtocols) {
  assert(Tok.is(tok::less) && "Not at the start of type args or protocols");
  SourceLocation lAngleLoc = ConsumeToken();

  // Whether all of the elements we've parsed thus far are single
  // identifiers, which might be types or might be protocols.
  bool allSingleIdentifiers = true;
  SmallVector<IdentifierInfo *, 4> identifiers;
  SmallVectorImpl<SourceLocation> &identifierLocs = protocolLocs;

  // Parse a list of comma-separated identifiers, bailing out if we
  // see something different.
  do {
    // Parse a single identifier.
    if (Tok.is(tok::identifier) &&
        (NextToken().is(tok::comma) ||
         NextToken().is(tok::greater) ||
         NextToken().is(tok::greatergreater))) {
      identifiers.push_back(Tok.getIdentifierInfo());
      identifierLocs.push_back(ConsumeToken());
      continue;
    }

    if (Tok.is(tok::code_completion)) {
      // FIXME: Also include types here.
      SmallVector<IdentifierLocPair, 4> identifierLocPairs;
      for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
        identifierLocPairs.push_back(IdentifierLocPair(identifiers[i],
                                                       identifierLocs[i]));
      }

      QualType BaseT = Actions.GetTypeFromParser(baseType);
      if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) {
        Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type);
      } else {
        Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs);
      }
      cutOffParsing();
      return;
    }

    allSingleIdentifiers = false;
    break;
  } while (TryConsumeToken(tok::comma));

  // If we parsed an identifier list, semantic analysis sorts out
  // whether it refers to protocols or to type arguments.
  if (allSingleIdentifiers) {
    // Parse the closing '>'.
    SourceLocation rAngleLoc;
    (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken,
                                         /*ObjCGenericList=*/true);

    // Let Sema figure out what we parsed.
    Actions.actOnObjCTypeArgsOrProtocolQualifiers(getCurScope(),
                                                  baseType,
                                                  lAngleLoc,
                                                  identifiers,
                                                  identifierLocs,
                                                  rAngleLoc,
                                                  typeArgsLAngleLoc,
                                                  typeArgs,
                                                  typeArgsRAngleLoc,
                                                  protocolLAngleLoc,
                                                  protocols,
                                                  protocolRAngleLoc,
                                                  warnOnIncompleteProtocols);
    return;
  }

  // We parsed an identifier list but stumbled into non single identifiers, this
  // means we might (a) check that what we already parsed is a legitimate type
  // (not a protocol or unknown type) and (b) parse the remaining ones, which
  // must all be type args.

  // Convert the identifiers into type arguments.
  bool invalid = false;
  IdentifierInfo *foundProtocolId = nullptr, *foundValidTypeId = nullptr;
  SourceLocation foundProtocolSrcLoc, foundValidTypeSrcLoc;
  SmallVector<IdentifierInfo *, 2> unknownTypeArgs;
  SmallVector<SourceLocation, 2> unknownTypeArgsLoc;

  for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
    ParsedType typeArg
      = Actions.getTypeName(*identifiers[i], identifierLocs[i], getCurScope());
    if (typeArg) {
      DeclSpec DS(AttrFactory);
      const char *prevSpec = nullptr;
      unsigned diagID;
      DS.SetTypeSpecType(TST_typename, identifierLocs[i], prevSpec, diagID,
                         typeArg, Actions.getASTContext().getPrintingPolicy());

      // Form a declarator to turn this into a type.
      Declarator D(DS, DeclaratorContext::TypeNameContext);
      TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D);
      if (fullTypeArg.isUsable()) {
        typeArgs.push_back(fullTypeArg.get());
        if (!foundValidTypeId) {
          foundValidTypeId = identifiers[i];
          foundValidTypeSrcLoc = identifierLocs[i];
        }
      } else {
        invalid = true;
        unknownTypeArgs.push_back(identifiers[i]);
        unknownTypeArgsLoc.push_back(identifierLocs[i]);
      }
    } else {
      invalid = true;
      if (!Actions.LookupProtocol(identifiers[i], identifierLocs[i])) {
        unknownTypeArgs.push_back(identifiers[i]);
        unknownTypeArgsLoc.push_back(identifierLocs[i]);
      } else if (!foundProtocolId) {
        foundProtocolId = identifiers[i];
        foundProtocolSrcLoc = identifierLocs[i];
      }
    }
  }

  // Continue parsing type-names.
  do {
    Token CurTypeTok = Tok;
    TypeResult typeArg = ParseTypeName();

    // Consume the '...' for a pack expansion.
    SourceLocation ellipsisLoc;
    TryConsumeToken(tok::ellipsis, ellipsisLoc);
    if (typeArg.isUsable() && ellipsisLoc.isValid()) {
      typeArg = Actions.ActOnPackExpansion(typeArg.get(), ellipsisLoc);
    }

    if (typeArg.isUsable()) {
      typeArgs.push_back(typeArg.get());
      if (!foundValidTypeId) {
        foundValidTypeId = CurTypeTok.getIdentifierInfo();
        foundValidTypeSrcLoc = CurTypeTok.getLocation();
      }
    } else {
      invalid = true;
    }
  } while (TryConsumeToken(tok::comma));

  // Diagnose the mix between type args and protocols.
  if (foundProtocolId && foundValidTypeId)
    Actions.DiagnoseTypeArgsAndProtocols(foundProtocolId, foundProtocolSrcLoc,
                                         foundValidTypeId,
                                         foundValidTypeSrcLoc);

  // Diagnose unknown arg types.
  ParsedType T;
  if (unknownTypeArgs.size())
    for (unsigned i = 0, e = unknownTypeArgsLoc.size(); i < e; ++i)
      Actions.DiagnoseUnknownTypeName(unknownTypeArgs[i], unknownTypeArgsLoc[i],
                                      getCurScope(), nullptr, T);

  // Parse the closing '>'.
  SourceLocation rAngleLoc;
  (void)ParseGreaterThanInTemplateList(rAngleLoc, consumeLastToken,
                                       /*ObjCGenericList=*/true);

  if (invalid) {
    typeArgs.clear();
    return;
  }

  // Record left/right angle locations.
  typeArgsLAngleLoc = lAngleLoc;
  typeArgsRAngleLoc = rAngleLoc;
}

void Parser::parseObjCTypeArgsAndProtocolQualifiers(
       ParsedType baseType,
       SourceLocation &typeArgsLAngleLoc,
       SmallVectorImpl<ParsedType> &typeArgs,
       SourceLocation &typeArgsRAngleLoc,
       SourceLocation &protocolLAngleLoc,
       SmallVectorImpl<Decl *> &protocols,
       SmallVectorImpl<SourceLocation> &protocolLocs,
       SourceLocation &protocolRAngleLoc,
       bool consumeLastToken) {
  assert(Tok.is(tok::less));

  // Parse the first angle-bracket-delimited clause.
  parseObjCTypeArgsOrProtocolQualifiers(baseType,
                                        typeArgsLAngleLoc,
                                        typeArgs,
                                        typeArgsRAngleLoc,
                                        protocolLAngleLoc,
                                        protocols,
                                        protocolLocs,
                                        protocolRAngleLoc,
                                        consumeLastToken,
                                        /*warnOnIncompleteProtocols=*/false);
  if (Tok.is(tok::eof)) // Nothing else to do here...
    return;

  // An Objective-C object pointer followed by type arguments
  // can then be followed again by a set of protocol references, e.g.,
  // \c NSArray<NSView><NSTextDelegate>
  if ((consumeLastToken && Tok.is(tok::less)) ||
      (!consumeLastToken && NextToken().is(tok::less))) {
    // If we aren't consuming the last token, the prior '>' is still hanging
    // there. Consume it before we parse the protocol qualifiers.
    if (!consumeLastToken)
      ConsumeToken();

    if (!protocols.empty()) {
      SkipUntilFlags skipFlags = SkipUntilFlags();
      if (!consumeLastToken)
        skipFlags = skipFlags | StopBeforeMatch;
      Diag(Tok, diag::err_objc_type_args_after_protocols)
        << SourceRange(protocolLAngleLoc, protocolRAngleLoc);
      SkipUntil(tok::greater, tok::greatergreater, skipFlags);
    } else {
      ParseObjCProtocolReferences(protocols, protocolLocs,
                                  /*WarnOnDeclarations=*/false,
                                  /*ForObjCContainer=*/false,
                                  protocolLAngleLoc, protocolRAngleLoc,
                                  consumeLastToken);
    }
  }
}

TypeResult Parser::parseObjCTypeArgsAndProtocolQualifiers(
             SourceLocation loc,
             ParsedType type,
             bool consumeLastToken,
             SourceLocation &endLoc) {
  assert(Tok.is(tok::less));
  SourceLocation typeArgsLAngleLoc;
  SmallVector<ParsedType, 4> typeArgs;
  SourceLocation typeArgsRAngleLoc;
  SourceLocation protocolLAngleLoc;
  SmallVector<Decl *, 4> protocols;
  SmallVector<SourceLocation, 4> protocolLocs;
  SourceLocation protocolRAngleLoc;

  // Parse type arguments and protocol qualifiers.
  parseObjCTypeArgsAndProtocolQualifiers(type, typeArgsLAngleLoc, typeArgs,
                                         typeArgsRAngleLoc, protocolLAngleLoc,
                                         protocols, protocolLocs,
                                         protocolRAngleLoc, consumeLastToken);

  if (Tok.is(tok::eof))
    return true; // Invalid type result.

  // Compute the location of the last token.
  if (consumeLastToken)
    endLoc = PrevTokLocation;
  else
    endLoc = Tok.getLocation();

  return Actions.actOnObjCTypeArgsAndProtocolQualifiers(
           getCurScope(),
           loc,
           type,
           typeArgsLAngleLoc,
           typeArgs,
           typeArgsRAngleLoc,
           protocolLAngleLoc,
           protocols,
           protocolLocs,
           protocolRAngleLoc);
}

void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocation atLoc,
                                 BalancedDelimiterTracker &T,
                                 SmallVectorImpl<Decl *> &AllIvarDecls,
                                 bool RBraceMissing) {
  if (!RBraceMissing)
    T.consumeClose();

  Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
  Actions.ActOnLastBitfield(T.getCloseLocation(), AllIvarDecls);
  Actions.ActOnObjCContainerFinishDefinition();
  // Call ActOnFields() even if we don't have any decls. This is useful
  // for code rewriting tools that need to be aware of the empty list.
  Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls,
                      T.getOpenLocation(), T.getCloseLocation(),
                      ParsedAttributesView());
}

///   objc-class-instance-variables:
///     '{' objc-instance-variable-decl-list[opt] '}'
///
///   objc-instance-variable-decl-list:
///     objc-visibility-spec
///     objc-instance-variable-decl ';'
///     ';'
///     objc-instance-variable-decl-list objc-visibility-spec
///     objc-instance-variable-decl-list objc-instance-variable-decl ';'
///     objc-instance-variable-decl-list static_assert-declaration
///     objc-instance-variable-decl-list ';'
///
///   objc-visibility-spec:
///     @private
///     @protected
///     @public
///     @package [OBJC2]
///
///   objc-instance-variable-decl:
///     struct-declaration
///
void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
                                             tok::ObjCKeywordKind visibility,
                                             SourceLocation atLoc) {
  assert(Tok.is(tok::l_brace) && "expected {");
  SmallVector<Decl *, 32> AllIvarDecls;

  ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
  ObjCDeclContextSwitch ObjCDC(*this);

  BalancedDelimiterTracker T(*this, tok::l_brace);
  T.consumeOpen();
  // While we still have something to read, read the instance variables.
  while (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
    // Each iteration of this loop reads one objc-instance-variable-decl.

    // Check for extraneous top-level semicolon.
    if (Tok.is(tok::semi)) {
      ConsumeExtraSemi(InstanceVariableList);
      continue;
    }

    // Set the default visibility to private.
    if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
      if (Tok.is(tok::code_completion)) {
        Actions.CodeCompleteObjCAtVisibility(getCurScope());
        return cutOffParsing();
      }

      switch (Tok.getObjCKeywordID()) {
      case tok::objc_private:
      case tok::objc_public:
      case tok::objc_protected:
      case tok::objc_package:
        visibility = Tok.getObjCKeywordID();
        ConsumeToken();
        continue;

      case tok::objc_end:
        Diag(Tok, diag::err_objc_unexpected_atend);
        Tok.setLocation(Tok.getLocation().getLocWithOffset(-1));
        Tok.setKind(tok::at);
        Tok.setLength(1);
        PP.EnterToken(Tok);
        HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
                                         T, AllIvarDecls, true);
        return;

      default:
        Diag(Tok, diag::err_objc_illegal_visibility_spec);
        continue;
      }
    }

    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteOrdinaryName(getCurScope(),
                                       Sema::PCC_ObjCInstanceVariableList);
      return cutOffParsing();
    }

    // This needs to duplicate a small amount of code from
    // ParseStructUnionBody() for things that should work in both
    // C struct and in Objective-C class instance variables.
    if (Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) {
      SourceLocation DeclEnd;
      ParseStaticAssertDeclaration(DeclEnd);
      continue;
    }

    auto ObjCIvarCallback = [&](ParsingFieldDeclarator &FD) {
      Actions.ActOnObjCContainerStartDefinition(interfaceDecl);
      // Install the declarator into the interface decl.
      FD.D.setObjCIvar(true);
      Decl *Field = Actions.ActOnIvar(
          getCurScope(), FD.D.getDeclSpec().getSourceRange().getBegin(), FD.D,
          FD.BitfieldSize, visibility);
      Actions.ActOnObjCContainerFinishDefinition();
      if (Field)
        AllIvarDecls.push_back(Field);
      FD.complete(Field);
    };

    // Parse all the comma separated declarators.
    ParsingDeclSpec DS(*this);
    ParseStructDeclaration(DS, ObjCIvarCallback);

    if (Tok.is(tok::semi)) {
      ConsumeToken();
    } else {
      Diag(Tok, diag::err_expected_semi_decl_list);
      // Skip to end of block or statement
      SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
    }
  }
  HelperActionsForIvarDeclarations(interfaceDecl, atLoc,
                                   T, AllIvarDecls, false);
}

///   objc-protocol-declaration:
///     objc-protocol-definition
///     objc-protocol-forward-reference
///
///   objc-protocol-definition:
///     \@protocol identifier
///       objc-protocol-refs[opt]
///       objc-interface-decl-list
///     \@end
///
///   objc-protocol-forward-reference:
///     \@protocol identifier-list ';'
///
///   "\@protocol identifier ;" should be resolved as "\@protocol
///   identifier-list ;": objc-interface-decl-list may not start with a
///   semicolon in the first alternative if objc-protocol-refs are omitted.
Parser::DeclGroupPtrTy
Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc,
                                       ParsedAttributes &attrs) {
  assert(Tok.isObjCAtKeyword(tok::objc_protocol) &&
         "ParseObjCAtProtocolDeclaration(): Expected @protocol");
  ConsumeToken(); // the "protocol" identifier

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

  MaybeSkipAttributes(tok::objc_protocol);

  if (expectIdentifier())
    return nullptr; // missing protocol name.
  // Save the protocol name, then consume it.
  IdentifierInfo *protocolName = Tok.getIdentifierInfo();
  SourceLocation nameLoc = ConsumeToken();

  if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol.
    IdentifierLocPair ProtoInfo(protocolName, nameLoc);
    return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs);
  }

  CheckNestedObjCContexts(AtLoc);

  if (Tok.is(tok::comma)) { // list of forward declarations.
    SmallVector<IdentifierLocPair, 8> ProtocolRefs;
    ProtocolRefs.push_back(std::make_pair(protocolName, nameLoc));

    // Parse the list of forward declarations.
    while (1) {
      ConsumeToken(); // the ','
      if (expectIdentifier()) {
        SkipUntil(tok::semi);
        return nullptr;
      }
      ProtocolRefs.push_back(IdentifierLocPair(Tok.getIdentifierInfo(),
                                               Tok.getLocation()));
      ConsumeToken(); // the identifier

      if (Tok.isNot(tok::comma))
        break;
    }
    // Consume the ';'.
    if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol"))
      return nullptr;

    return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs);
  }

  // Last, and definitely not least, parse a protocol declaration.
  SourceLocation LAngleLoc, EndProtoLoc;

  SmallVector<Decl *, 8> ProtocolRefs;
  SmallVector<SourceLocation, 8> ProtocolLocs;
  if (Tok.is(tok::less) &&
      ParseObjCProtocolReferences(ProtocolRefs, ProtocolLocs, false, true,
                                  LAngleLoc, EndProtoLoc,
                                  /*consumeLastToken=*/true))
    return nullptr;

  Decl *ProtoType = Actions.ActOnStartProtocolInterface(
      AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(),
      ProtocolLocs.data(), EndProtoLoc, attrs);

  ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType);
  return Actions.ConvertDeclToDeclGroup(ProtoType);
}

///   objc-implementation:
///     objc-class-implementation-prologue
///     objc-category-implementation-prologue
///
///   objc-class-implementation-prologue:
///     @implementation identifier objc-superclass[opt]
///       objc-class-instance-variables[opt]
///
///   objc-category-implementation-prologue:
///     @implementation identifier ( identifier )
Parser::DeclGroupPtrTy
Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc,
                                             ParsedAttributes &Attrs) {
  assert(Tok.isObjCAtKeyword(tok::objc_implementation) &&
         "ParseObjCAtImplementationDeclaration(): Expected @implementation");
  CheckNestedObjCContexts(AtLoc);
  ConsumeToken(); // the "implementation" identifier

  // Code completion after '@implementation'.
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCImplementationDecl(getCurScope());
    cutOffParsing();
    return nullptr;
  }

  MaybeSkipAttributes(tok::objc_implementation);

  if (expectIdentifier())
    return nullptr; // missing class or category name.
  // We have a class or category name - consume it.
  IdentifierInfo *nameId = Tok.getIdentifierInfo();
  SourceLocation nameLoc = ConsumeToken(); // consume class or category name
  Decl *ObjCImpDecl = nullptr;

  // Neither a type parameter list nor a list of protocol references is
  // permitted here. Parse and diagnose them.
  if (Tok.is(tok::less)) {
    SourceLocation lAngleLoc, rAngleLoc;
    SmallVector<IdentifierLocPair, 8> protocolIdents;
    SourceLocation diagLoc = Tok.getLocation();
    ObjCTypeParamListScope typeParamScope(Actions, getCurScope());
    if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc,
                                             protocolIdents, rAngleLoc)) {
      Diag(diagLoc, diag::err_objc_parameterized_implementation)
        << SourceRange(diagLoc, PrevTokLocation);
    } else if (lAngleLoc.isValid()) {
      Diag(lAngleLoc, diag::err_unexpected_protocol_qualifier)
        << FixItHint::CreateRemoval(SourceRange(lAngleLoc, rAngleLoc));
    }
  }

  if (Tok.is(tok::l_paren)) {
    // we have a category implementation.
    ConsumeParen();
    SourceLocation categoryLoc, rparenLoc;
    IdentifierInfo *categoryId = nullptr;

    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCImplementationCategory(getCurScope(), nameId, nameLoc);
      cutOffParsing();
      return nullptr;
    }

    if (Tok.is(tok::identifier)) {
      categoryId = Tok.getIdentifierInfo();
      categoryLoc = ConsumeToken();
    } else {
      Diag(Tok, diag::err_expected)
          << tok::identifier; // missing category name.
      return nullptr;
    }
    if (Tok.isNot(tok::r_paren)) {
      Diag(Tok, diag::err_expected) << tok::r_paren;
      SkipUntil(tok::r_paren); // don't stop at ';'
      return nullptr;
    }
    rparenLoc = ConsumeParen();
    if (Tok.is(tok::less)) { // we have illegal '<' try to recover
      Diag(Tok, diag::err_unexpected_protocol_qualifier);
      SourceLocation protocolLAngleLoc, protocolRAngleLoc;
      SmallVector<Decl *, 4> protocols;
      SmallVector<SourceLocation, 4> protocolLocs;
      (void)ParseObjCProtocolReferences(protocols, protocolLocs,
                                        /*warnOnIncompleteProtocols=*/false,
                                        /*ForObjCContainer=*/false,
                                        protocolLAngleLoc, protocolRAngleLoc,
                                        /*consumeLastToken=*/true);
    }
    ObjCImpDecl = Actions.ActOnStartCategoryImplementation(
        AtLoc, nameId, nameLoc, categoryId, categoryLoc, Attrs);

  } else {
    // We have a class implementation
    SourceLocation superClassLoc;
    IdentifierInfo *superClassId = nullptr;
    if (TryConsumeToken(tok::colon)) {
      // We have a super class
      if (expectIdentifier())
        return nullptr; // missing super class name.
      superClassId = Tok.getIdentifierInfo();
      superClassLoc = ConsumeToken(); // Consume super class name
    }
    ObjCImpDecl = Actions.ActOnStartClassImplementation(
        AtLoc, nameId, nameLoc, superClassId, superClassLoc, Attrs);

    if (Tok.is(tok::l_brace)) // we have ivars
      ParseObjCClassInstanceVariables(ObjCImpDecl, tok::objc_private, AtLoc);
    else if (Tok.is(tok::less)) { // we have illegal '<' try to recover
      Diag(Tok, diag::err_unexpected_protocol_qualifier);

      SourceLocation protocolLAngleLoc, protocolRAngleLoc;
      SmallVector<Decl *, 4> protocols;
      SmallVector<SourceLocation, 4> protocolLocs;
      (void)ParseObjCProtocolReferences(protocols, protocolLocs,
                                        /*warnOnIncompleteProtocols=*/false,
                                        /*ForObjCContainer=*/false,
                                        protocolLAngleLoc, protocolRAngleLoc,
                                        /*consumeLastToken=*/true);
    }
  }
  assert(ObjCImpDecl);

  SmallVector<Decl *, 8> DeclsInGroup;

  {
    ObjCImplParsingDataRAII ObjCImplParsing(*this, ObjCImpDecl);
    while (!ObjCImplParsing.isFinished() && !isEofOrEom()) {
      ParsedAttributesWithRange attrs(AttrFactory);
      MaybeParseCXX11Attributes(attrs);
      if (DeclGroupPtrTy DGP = ParseExternalDeclaration(attrs)) {
        DeclGroupRef DG = DGP.get();
        DeclsInGroup.append(DG.begin(), DG.end());
      }
    }
  }

  return Actions.ActOnFinishObjCImplementation(ObjCImpDecl, DeclsInGroup);
}

Parser::DeclGroupPtrTy
Parser::ParseObjCAtEndDeclaration(SourceRange atEnd) {
  assert(Tok.isObjCAtKeyword(tok::objc_end) &&
         "ParseObjCAtEndDeclaration(): Expected @end");
  ConsumeToken(); // the "end" identifier
  if (CurParsedObjCImpl)
    CurParsedObjCImpl->finish(atEnd);
  else
    // missing @implementation
    Diag(atEnd.getBegin(), diag::err_expected_objc_container);
  return nullptr;
}

Parser::ObjCImplParsingDataRAII::~ObjCImplParsingDataRAII() {
  if (!Finished) {
    finish(P.Tok.getLocation());
    if (P.isEofOrEom()) {
      P.Diag(P.Tok, diag::err_objc_missing_end)
          << FixItHint::CreateInsertion(P.Tok.getLocation(), "\n@end\n");
      P.Diag(Dcl->getBeginLoc(), diag::note_objc_container_start)
          << Sema::OCK_Implementation;
    }
  }
  P.CurParsedObjCImpl = nullptr;
  assert(LateParsedObjCMethods.empty());
}

void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) {
  assert(!Finished);
  P.Actions.DefaultSynthesizeProperties(P.getCurScope(), Dcl, AtEnd.getBegin());
  for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
    P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
                               true/*Methods*/);

  P.Actions.ActOnAtEnd(P.getCurScope(), AtEnd);

  if (HasCFunction)
    for (size_t i = 0; i < LateParsedObjCMethods.size(); ++i)
      P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i],
                                 false/*c-functions*/);

  /// Clear and free the cached objc methods.
  for (LateParsedObjCMethodContainer::iterator
         I = LateParsedObjCMethods.begin(),
         E = LateParsedObjCMethods.end(); I != E; ++I)
    delete *I;
  LateParsedObjCMethods.clear();

  Finished = true;
}

///   compatibility-alias-decl:
///     @compatibility_alias alias-name  class-name ';'
///
Decl *Parser::ParseObjCAtAliasDeclaration(SourceLocation atLoc) {
  assert(Tok.isObjCAtKeyword(tok::objc_compatibility_alias) &&
         "ParseObjCAtAliasDeclaration(): Expected @compatibility_alias");
  ConsumeToken(); // consume compatibility_alias
  if (expectIdentifier())
    return nullptr;
  IdentifierInfo *aliasId = Tok.getIdentifierInfo();
  SourceLocation aliasLoc = ConsumeToken(); // consume alias-name
  if (expectIdentifier())
    return nullptr;
  IdentifierInfo *classId = Tok.getIdentifierInfo();
  SourceLocation classLoc = ConsumeToken(); // consume class-name;
  ExpectAndConsume(tok::semi, diag::err_expected_after, "@compatibility_alias");
  return Actions.ActOnCompatibilityAlias(atLoc, aliasId, aliasLoc,
                                         classId, classLoc);
}

///   property-synthesis:
///     @synthesize property-ivar-list ';'
///
///   property-ivar-list:
///     property-ivar
///     property-ivar-list ',' property-ivar
///
///   property-ivar:
///     identifier
///     identifier '=' identifier
///
Decl *Parser::ParseObjCPropertySynthesize(SourceLocation atLoc) {
  assert(Tok.isObjCAtKeyword(tok::objc_synthesize) &&
         "ParseObjCPropertySynthesize(): Expected '@synthesize'");
  ConsumeToken(); // consume synthesize

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

    if (Tok.isNot(tok::identifier)) {
      Diag(Tok, diag::err_synthesized_property_name);
      SkipUntil(tok::semi);
      return nullptr;
    }

    IdentifierInfo *propertyIvar = nullptr;
    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
    SourceLocation propertyLoc = ConsumeToken(); // consume property name
    SourceLocation propertyIvarLoc;
    if (TryConsumeToken(tok::equal)) {
      // property '=' ivar-name
      if (Tok.is(tok::code_completion)) {
        Actions.CodeCompleteObjCPropertySynthesizeIvar(getCurScope(), propertyId);
        cutOffParsing();
        return nullptr;
      }

      if (expectIdentifier())
        break;
      propertyIvar = Tok.getIdentifierInfo();
      propertyIvarLoc = ConsumeToken(); // consume ivar-name
    }
    Actions.ActOnPropertyImplDecl(
        getCurScope(), atLoc, propertyLoc, true,
        propertyId, propertyIvar, propertyIvarLoc,
        ObjCPropertyQueryKind::OBJC_PR_query_unknown);
    if (Tok.isNot(tok::comma))
      break;
    ConsumeToken(); // consume ','
  }
  ExpectAndConsume(tok::semi, diag::err_expected_after, "@synthesize");
  return nullptr;
}

///   property-dynamic:
///     @dynamic  property-list
///
///   property-list:
///     identifier
///     property-list ',' identifier
///
Decl *Parser::ParseObjCPropertyDynamic(SourceLocation atLoc) {
  assert(Tok.isObjCAtKeyword(tok::objc_dynamic) &&
         "ParseObjCPropertyDynamic(): Expected '@dynamic'");
  ConsumeToken(); // consume dynamic

  bool isClassProperty = false;
  if (Tok.is(tok::l_paren)) {
    ConsumeParen();
    const IdentifierInfo *II = Tok.getIdentifierInfo();

    if (!II) {
      Diag(Tok, diag::err_objc_expected_property_attr) << II;
      SkipUntil(tok::r_paren, StopAtSemi);
    } else {
      SourceLocation AttrName = ConsumeToken(); // consume attribute name
      if (II->isStr("class")) {
        isClassProperty = true;
        if (Tok.isNot(tok::r_paren)) {
          Diag(Tok, diag::err_expected) << tok::r_paren;
          SkipUntil(tok::r_paren, StopAtSemi);
        } else
          ConsumeParen();
      } else {
        Diag(AttrName, diag::err_objc_expected_property_attr) << II;
        SkipUntil(tok::r_paren, StopAtSemi);
      }
    }
  }

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

    if (expectIdentifier()) {
      SkipUntil(tok::semi);
      return nullptr;
    }

    IdentifierInfo *propertyId = Tok.getIdentifierInfo();
    SourceLocation propertyLoc = ConsumeToken(); // consume property name
    Actions.ActOnPropertyImplDecl(
        getCurScope(), atLoc, propertyLoc, false,
        propertyId, nullptr, SourceLocation(),
        isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
        ObjCPropertyQueryKind::OBJC_PR_query_unknown);

    if (Tok.isNot(tok::comma))
      break;
    ConsumeToken(); // consume ','
  }
  ExpectAndConsume(tok::semi, diag::err_expected_after, "@dynamic");
  return nullptr;
}

///  objc-throw-statement:
///    throw expression[opt];
///
StmtResult Parser::ParseObjCThrowStmt(SourceLocation atLoc) {
  ExprResult Res;
  ConsumeToken(); // consume throw
  if (Tok.isNot(tok::semi)) {
    Res = ParseExpression();
    if (Res.isInvalid()) {
      SkipUntil(tok::semi);
      return StmtError();
    }
  }
  // consume ';'
  ExpectAndConsume(tok::semi, diag::err_expected_after, "@throw");
  return Actions.ActOnObjCAtThrowStmt(atLoc, Res.get(), getCurScope());
}

/// objc-synchronized-statement:
///   @synchronized '(' expression ')' compound-statement
///
StmtResult
Parser::ParseObjCSynchronizedStmt(SourceLocation atLoc) {
  ConsumeToken(); // consume synchronized
  if (Tok.isNot(tok::l_paren)) {
    Diag(Tok, diag::err_expected_lparen_after) << "@synchronized";
    return StmtError();
  }

  // The operand is surrounded with parentheses.
  ConsumeParen();  // '('
  ExprResult operand(ParseExpression());

  if (Tok.is(tok::r_paren)) {
    ConsumeParen();  // ')'
  } else {
    if (!operand.isInvalid())
      Diag(Tok, diag::err_expected) << tok::r_paren;

    // Skip forward until we see a left brace, but don't consume it.
    SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);
  }

  // Require a compound statement.
  if (Tok.isNot(tok::l_brace)) {
    if (!operand.isInvalid())
      Diag(Tok, diag::err_expected) << tok::l_brace;
    return StmtError();
  }

  // Check the @synchronized operand now.
  if (!operand.isInvalid())
    operand = Actions.ActOnObjCAtSynchronizedOperand(atLoc, operand.get());

  // Parse the compound statement within a new scope.
  ParseScope bodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
  StmtResult body(ParseCompoundStatementBody());
  bodyScope.Exit();

  // If there was a semantic or parse error earlier with the
  // operand, fail now.
  if (operand.isInvalid())
    return StmtError();

  if (body.isInvalid())
    body = Actions.ActOnNullStmt(Tok.getLocation());

  return Actions.ActOnObjCAtSynchronizedStmt(atLoc, operand.get(), body.get());
}

///  objc-try-catch-statement:
///    @try compound-statement objc-catch-list[opt]
///    @try compound-statement objc-catch-list[opt] @finally compound-statement
///
///  objc-catch-list:
///    @catch ( parameter-declaration ) compound-statement
///    objc-catch-list @catch ( catch-parameter-declaration ) compound-statement
///  catch-parameter-declaration:
///     parameter-declaration
///     '...' [OBJC2]
///
StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
  bool catch_or_finally_seen = false;

  ConsumeToken(); // consume try
  if (Tok.isNot(tok::l_brace)) {
    Diag(Tok, diag::err_expected) << tok::l_brace;
    return StmtError();
  }
  StmtVector CatchStmts;
  StmtResult FinallyStmt;
  ParseScope TryScope(this, Scope::DeclScope | Scope::CompoundStmtScope);
  StmtResult TryBody(ParseCompoundStatementBody());
  TryScope.Exit();
  if (TryBody.isInvalid())
    TryBody = Actions.ActOnNullStmt(Tok.getLocation());

  while (Tok.is(tok::at)) {
    // At this point, we need to lookahead to determine if this @ is the start
    // of an @catch or @finally.  We don't want to consume the @ token if this
    // is an @try or @encode or something else.
    Token AfterAt = GetLookAheadToken(1);
    if (!AfterAt.isObjCAtKeyword(tok::objc_catch) &&
        !AfterAt.isObjCAtKeyword(tok::objc_finally))
      break;

    SourceLocation AtCatchFinallyLoc = ConsumeToken();
    if (Tok.isObjCAtKeyword(tok::objc_catch)) {
      Decl *FirstPart = nullptr;
      ConsumeToken(); // consume catch
      if (Tok.is(tok::l_paren)) {
        ConsumeParen();
        ParseScope CatchScope(this, Scope::DeclScope |
                                        Scope::CompoundStmtScope |
                                        Scope::AtCatchScope);
        if (Tok.isNot(tok::ellipsis)) {
          DeclSpec DS(AttrFactory);
          ParseDeclarationSpecifiers(DS);
          Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext);
          ParseDeclarator(ParmDecl);

          // Inform the actions module about the declarator, so it
          // gets added to the current scope.
          FirstPart = Actions.ActOnObjCExceptionDecl(getCurScope(), ParmDecl);
        } else
          ConsumeToken(); // consume '...'

        SourceLocation RParenLoc;

        if (Tok.is(tok::r_paren))
          RParenLoc = ConsumeParen();
        else // Skip over garbage, until we get to ')'.  Eat the ')'.
          SkipUntil(tok::r_paren, StopAtSemi);

        StmtResult CatchBody(true);
        if (Tok.is(tok::l_brace))
          CatchBody = ParseCompoundStatementBody();
        else
          Diag(Tok, diag::err_expected) << tok::l_brace;
        if (CatchBody.isInvalid())
          CatchBody = Actions.ActOnNullStmt(Tok.getLocation());

        StmtResult Catch = Actions.ActOnObjCAtCatchStmt(AtCatchFinallyLoc,
                                                              RParenLoc,
                                                              FirstPart,
                                                              CatchBody.get());
        if (!Catch.isInvalid())
          CatchStmts.push_back(Catch.get());

      } else {
        Diag(AtCatchFinallyLoc, diag::err_expected_lparen_after)
          << "@catch clause";
        return StmtError();
      }
      catch_or_finally_seen = true;
    } else {
      assert(Tok.isObjCAtKeyword(tok::objc_finally) && "Lookahead confused?");
      ConsumeToken(); // consume finally
      ParseScope FinallyScope(this,
                              Scope::DeclScope | Scope::CompoundStmtScope);

      bool ShouldCapture =
          getTargetInfo().getTriple().isWindowsMSVCEnvironment();
      if (ShouldCapture)
        Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(),
                                         CR_ObjCAtFinally, 1);

      StmtResult FinallyBody(true);
      if (Tok.is(tok::l_brace))
        FinallyBody = ParseCompoundStatementBody();
      else
        Diag(Tok, diag::err_expected) << tok::l_brace;

      if (FinallyBody.isInvalid()) {
        FinallyBody = Actions.ActOnNullStmt(Tok.getLocation());
        if (ShouldCapture)
          Actions.ActOnCapturedRegionError();
      } else if (ShouldCapture) {
        FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get());
      }

      FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc,
                                                   FinallyBody.get());
      catch_or_finally_seen = true;
      break;
    }
  }
  if (!catch_or_finally_seen) {
    Diag(atLoc, diag::err_missing_catch_finally);
    return StmtError();
  }

  return Actions.ActOnObjCAtTryStmt(atLoc, TryBody.get(),
                                    CatchStmts,
                                    FinallyStmt.get());
}

/// objc-autoreleasepool-statement:
///   @autoreleasepool compound-statement
///
StmtResult
Parser::ParseObjCAutoreleasePoolStmt(SourceLocation atLoc) {
  ConsumeToken(); // consume autoreleasepool
  if (Tok.isNot(tok::l_brace)) {
    Diag(Tok, diag::err_expected) << tok::l_brace;
    return StmtError();
  }
  // Enter a scope to hold everything within the compound stmt.  Compound
  // statements can always hold declarations.
  ParseScope BodyScope(this, Scope::DeclScope | Scope::CompoundStmtScope);

  StmtResult AutoreleasePoolBody(ParseCompoundStatementBody());

  BodyScope.Exit();
  if (AutoreleasePoolBody.isInvalid())
    AutoreleasePoolBody = Actions.ActOnNullStmt(Tok.getLocation());
  return Actions.ActOnObjCAutoreleasePoolStmt(atLoc,
                                                AutoreleasePoolBody.get());
}

/// StashAwayMethodOrFunctionBodyTokens -  Consume the tokens and store them
/// for later parsing.
void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
  if (SkipFunctionBodies && (!MDecl || Actions.canSkipFunctionBody(MDecl)) &&
      trySkippingFunctionBody()) {
    Actions.ActOnSkippedFunctionBody(MDecl);
    return;
  }

  LexedMethod* LM = new LexedMethod(this, MDecl);
  CurParsedObjCImpl->LateParsedObjCMethods.push_back(LM);
  CachedTokens &Toks = LM->Toks;
  // Begin by storing the '{' or 'try' or ':' token.
  Toks.push_back(Tok);
  if (Tok.is(tok::kw_try)) {
    ConsumeToken();
    if (Tok.is(tok::colon)) {
      Toks.push_back(Tok);
      ConsumeToken();
      while (Tok.isNot(tok::l_brace)) {
        ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
        ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
      }
    }
    Toks.push_back(Tok); // also store '{'
  }
  else if (Tok.is(tok::colon)) {
    ConsumeToken();
    // FIXME: This is wrong, due to C++11 braced initialization.
    while (Tok.isNot(tok::l_brace)) {
      ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
      ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
    }
    Toks.push_back(Tok); // also store '{'
  }
  ConsumeBrace();
  // Consume everything up to (and including) the matching right brace.
  ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
  while (Tok.is(tok::kw_catch)) {
    ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/false);
    ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
  }
}

///   objc-method-def: objc-method-proto ';'[opt] '{' body '}'
///
Decl *Parser::ParseObjCMethodDefinition() {
  Decl *MDecl = ParseObjCMethodPrototype();

  PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(),
                                      "parsing Objective-C method");

  // parse optional ';'
  if (Tok.is(tok::semi)) {
    if (CurParsedObjCImpl) {
      Diag(Tok, diag::warn_semicolon_before_method_body)
        << FixItHint::CreateRemoval(Tok.getLocation());
    }
    ConsumeToken();
  }

  // We should have an opening brace now.
  if (Tok.isNot(tok::l_brace)) {
    Diag(Tok, diag::err_expected_method_body);

    // Skip over garbage, until we get to '{'.  Don't eat the '{'.
    SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch);

    // If we didn't find the '{', bail out.
    if (Tok.isNot(tok::l_brace))
      return nullptr;
  }

  if (!MDecl) {
    ConsumeBrace();
    SkipUntil(tok::r_brace);
    return nullptr;
  }

  // Allow the rest of sema to find private method decl implementations.
  Actions.AddAnyMethodToGlobalPool(MDecl);
  assert (CurParsedObjCImpl
          && "ParseObjCMethodDefinition - Method out of @implementation");
  // Consume the tokens and store them for later parsing.
  StashAwayMethodOrFunctionBodyTokens(MDecl);
  return MDecl;
}

StmtResult Parser::ParseObjCAtStatement(SourceLocation AtLoc,
                                        ParsedStmtContext StmtCtx) {
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCAtStatement(getCurScope());
    cutOffParsing();
    return StmtError();
  }

  if (Tok.isObjCAtKeyword(tok::objc_try))
    return ParseObjCTryStmt(AtLoc);

  if (Tok.isObjCAtKeyword(tok::objc_throw))
    return ParseObjCThrowStmt(AtLoc);

  if (Tok.isObjCAtKeyword(tok::objc_synchronized))
    return ParseObjCSynchronizedStmt(AtLoc);

  if (Tok.isObjCAtKeyword(tok::objc_autoreleasepool))
    return ParseObjCAutoreleasePoolStmt(AtLoc);

  if (Tok.isObjCAtKeyword(tok::objc_import) &&
      getLangOpts().DebuggerSupport) {
    SkipUntil(tok::semi);
    return Actions.ActOnNullStmt(Tok.getLocation());
  }

  ExprStatementTokLoc = AtLoc;
  ExprResult Res(ParseExpressionWithLeadingAt(AtLoc));
  if (Res.isInvalid()) {
    // If the expression is invalid, skip ahead to the next semicolon. Not
    // doing this opens us up to the possibility of infinite loops if
    // ParseExpression does not consume any tokens.
    SkipUntil(tok::semi);
    return StmtError();
  }

  // Otherwise, eat the semicolon.
  ExpectAndConsumeSemi(diag::err_expected_semi_after_expr);
  return handleExprStmt(Res, StmtCtx);
}

ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
  switch (Tok.getKind()) {
  case tok::code_completion:
    Actions.CodeCompleteObjCAtExpression(getCurScope());
    cutOffParsing();
    return ExprError();

  case tok::minus:
  case tok::plus: {
    tok::TokenKind Kind = Tok.getKind();
    SourceLocation OpLoc = ConsumeToken();

    if (!Tok.is(tok::numeric_constant)) {
      const char *Symbol = nullptr;
      switch (Kind) {
      case tok::minus: Symbol = "-"; break;
      case tok::plus: Symbol = "+"; break;
      default: llvm_unreachable("missing unary operator case");
      }
      Diag(Tok, diag::err_nsnumber_nonliteral_unary)
        << Symbol;
      return ExprError();
    }

    ExprResult Lit(Actions.ActOnNumericConstant(Tok));
    if (Lit.isInvalid()) {
      return Lit;
    }
    ConsumeToken(); // Consume the literal token.

    Lit = Actions.ActOnUnaryOp(getCurScope(), OpLoc, Kind, Lit.get());
    if (Lit.isInvalid())
      return Lit;

    return ParsePostfixExpressionSuffix(
             Actions.BuildObjCNumericLiteral(AtLoc, Lit.get()));
  }

  case tok::string_literal:    // primary-expression: string-literal
  case tok::wide_string_literal:
    return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));

  case tok::char_constant:
    return ParsePostfixExpressionSuffix(ParseObjCCharacterLiteral(AtLoc));

  case tok::numeric_constant:
    return ParsePostfixExpressionSuffix(ParseObjCNumericLiteral(AtLoc));

  case tok::kw_true:  // Objective-C++, etc.
  case tok::kw___objc_yes: // c/c++/objc/objc++ __objc_yes
    return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, true));
  case tok::kw_false: // Objective-C++, etc.
  case tok::kw___objc_no: // c/c++/objc/objc++ __objc_no
    return ParsePostfixExpressionSuffix(ParseObjCBooleanLiteral(AtLoc, false));

  case tok::l_square:
    // Objective-C array literal
    return ParsePostfixExpressionSuffix(ParseObjCArrayLiteral(AtLoc));

  case tok::l_brace:
    // Objective-C dictionary literal
    return ParsePostfixExpressionSuffix(ParseObjCDictionaryLiteral(AtLoc));

  case tok::l_paren:
    // Objective-C boxed expression
    return ParsePostfixExpressionSuffix(ParseObjCBoxedExpr(AtLoc));

  default:
    if (Tok.getIdentifierInfo() == nullptr)
      return ExprError(Diag(AtLoc, diag::err_unexpected_at));

    switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
    case tok::objc_encode:
      return ParsePostfixExpressionSuffix(ParseObjCEncodeExpression(AtLoc));
    case tok::objc_protocol:
      return ParsePostfixExpressionSuffix(ParseObjCProtocolExpression(AtLoc));
    case tok::objc_selector:
      return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc));
    case tok::objc_available:
      return ParseAvailabilityCheckExpr(AtLoc);
      default: {
        const char *str = nullptr;
        // Only provide the @try/@finally/@autoreleasepool fixit when we're sure
        // that this is a proper statement where such directives could actually
        // occur.
        if (GetLookAheadToken(1).is(tok::l_brace) &&
            ExprStatementTokLoc == AtLoc) {
          char ch = Tok.getIdentifierInfo()->getNameStart()[0];
          str =
            ch == 't' ? "try"
                      : (ch == 'f' ? "finally"
                                   : (ch == 'a' ? "autoreleasepool" : nullptr));
        }
        if (str) {
          SourceLocation kwLoc = Tok.getLocation();
          return ExprError(Diag(AtLoc, diag::err_unexpected_at) <<
                             FixItHint::CreateReplacement(kwLoc, str));
        }
        else
          return ExprError(Diag(AtLoc, diag::err_unexpected_at));
      }
    }
  }
}

/// Parse the receiver of an Objective-C++ message send.
///
/// This routine parses the receiver of a message send in
/// Objective-C++ either as a type or as an expression. Note that this
/// routine must not be called to parse a send to 'super', since it
/// has no way to return such a result.
///
/// \param IsExpr Whether the receiver was parsed as an expression.
///
/// \param TypeOrExpr If the receiver was parsed as an expression (\c
/// IsExpr is true), the parsed expression. If the receiver was parsed
/// as a type (\c IsExpr is false), the parsed type.
///
/// \returns True if an error occurred during parsing or semantic
/// analysis, in which case the arguments do not have valid
/// values. Otherwise, returns false for a successful parse.
///
///   objc-receiver: [C++]
///     'super' [not parsed here]
///     expression
///     simple-type-specifier
///     typename-specifier
bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) {
  InMessageExpressionRAIIObject InMessage(*this, true);

  if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_typename,
                  tok::annot_cxxscope))
    TryAnnotateTypeOrScopeToken();

  if (!Actions.isSimpleTypeSpecifier(Tok.getKind())) {
    //   objc-receiver:
    //     expression
    // Make sure any typos in the receiver are corrected or diagnosed, so that
    // proper recovery can happen. FIXME: Perhaps filter the corrected expr to
    // only the things that are valid ObjC receivers?
    ExprResult Receiver = Actions.CorrectDelayedTyposInExpr(ParseExpression());
    if (Receiver.isInvalid())
      return true;

    IsExpr = true;
    TypeOrExpr = Receiver.get();
    return false;
  }

  // objc-receiver:
  //   typename-specifier
  //   simple-type-specifier
  //   expression (that starts with one of the above)
  DeclSpec DS(AttrFactory);
  ParseCXXSimpleTypeSpecifier(DS);

  if (Tok.is(tok::l_paren)) {
    // If we see an opening parentheses at this point, we are
    // actually parsing an expression that starts with a
    // function-style cast, e.g.,
    //
    //   postfix-expression:
    //     simple-type-specifier ( expression-list [opt] )
    //     typename-specifier ( expression-list [opt] )
    //
    // Parse the remainder of this case, then the (optional)
    // postfix-expression suffix, followed by the (optional)
    // right-hand side of the binary expression. We have an
    // instance method.
    ExprResult Receiver = ParseCXXTypeConstructExpression(DS);
    if (!Receiver.isInvalid())
      Receiver = ParsePostfixExpressionSuffix(Receiver.get());
    if (!Receiver.isInvalid())
      Receiver = ParseRHSOfBinaryExpression(Receiver.get(), prec::Comma);
    if (Receiver.isInvalid())
      return true;

    IsExpr = true;
    TypeOrExpr = Receiver.get();
    return false;
  }

  // We have a class message. Turn the simple-type-specifier or
  // typename-specifier we parsed into a type and parse the
  // remainder of the class message.
  Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext);
  TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
  if (Type.isInvalid())
    return true;

  IsExpr = false;
  TypeOrExpr = Type.get().getAsOpaquePtr();
  return false;
}

/// Determine whether the parser is currently referring to a an
/// Objective-C message send, using a simplified heuristic to avoid overhead.
///
/// This routine will only return true for a subset of valid message-send
/// expressions.
bool Parser::isSimpleObjCMessageExpression() {
  assert(Tok.is(tok::l_square) && getLangOpts().ObjC &&
         "Incorrect start for isSimpleObjCMessageExpression");
  return GetLookAheadToken(1).is(tok::identifier) &&
         GetLookAheadToken(2).is(tok::identifier);
}

bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
  if (!getLangOpts().ObjC || !NextToken().is(tok::identifier) ||
      InMessageExpression)
    return false;

  ParsedType Type;

  if (Tok.is(tok::annot_typename))
    Type = getTypeAnnotation(Tok);
  else if (Tok.is(tok::identifier))
    Type = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(),
                               getCurScope());
  else
    return false;

  if (!Type.get().isNull() && Type.get()->isObjCObjectOrInterfaceType()) {
    const Token &AfterNext = GetLookAheadToken(2);
    if (AfterNext.isOneOf(tok::colon, tok::r_square)) {
      if (Tok.is(tok::identifier))
        TryAnnotateTypeOrScopeToken();

      return Tok.is(tok::annot_typename);
    }
  }

  return false;
}

///   objc-message-expr:
///     '[' objc-receiver objc-message-args ']'
///
///   objc-receiver: [C]
///     'super'
///     expression
///     class-name
///     type-name
///
ExprResult Parser::ParseObjCMessageExpression() {
  assert(Tok.is(tok::l_square) && "'[' expected");
  SourceLocation LBracLoc = ConsumeBracket(); // consume '['

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

  InMessageExpressionRAIIObject InMessage(*this, true);

  if (getLangOpts().CPlusPlus) {
    // We completely separate the C and C++ cases because C++ requires
    // more complicated (read: slower) parsing.

    // Handle send to super.
    // FIXME: This doesn't benefit from the same typo-correction we
    // get in Objective-C.
    if (Tok.is(tok::identifier) && Tok.getIdentifierInfo() == Ident_super &&
        NextToken().isNot(tok::period) && getCurScope()->isInObjcMethodScope())
      return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
                                            nullptr);

    // Parse the receiver, which is either a type or an expression.
    bool IsExpr;
    void *TypeOrExpr = nullptr;
    if (ParseObjCXXMessageReceiver(IsExpr, TypeOrExpr)) {
      SkipUntil(tok::r_square, StopAtSemi);
      return ExprError();
    }

    if (IsExpr)
      return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
                                            static_cast<Expr *>(TypeOrExpr));

    return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
                              ParsedType::getFromOpaquePtr(TypeOrExpr),
                                          nullptr);
  }

  if (Tok.is(tok::identifier)) {
    IdentifierInfo *Name = Tok.getIdentifierInfo();
    SourceLocation NameLoc = Tok.getLocation();
    ParsedType ReceiverType;
    switch (Actions.getObjCMessageKind(getCurScope(), Name, NameLoc,
                                       Name == Ident_super,
                                       NextToken().is(tok::period),
                                       ReceiverType)) {
    case Sema::ObjCSuperMessage:
      return ParseObjCMessageExpressionBody(LBracLoc, ConsumeToken(), nullptr,
                                            nullptr);

    case Sema::ObjCClassMessage:
      if (!ReceiverType) {
        SkipUntil(tok::r_square, StopAtSemi);
        return ExprError();
      }

      ConsumeToken(); // the type name

      // Parse type arguments and protocol qualifiers.
      if (Tok.is(tok::less)) {
        SourceLocation NewEndLoc;
        TypeResult NewReceiverType
          = parseObjCTypeArgsAndProtocolQualifiers(NameLoc, ReceiverType,
                                                   /*consumeLastToken=*/true,
                                                   NewEndLoc);
        if (!NewReceiverType.isUsable()) {
          SkipUntil(tok::r_square, StopAtSemi);
          return ExprError();
        }

        ReceiverType = NewReceiverType.get();
      }

      return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(),
                                            ReceiverType, nullptr);

    case Sema::ObjCInstanceMessage:
      // Fall through to parse an expression.
      break;
    }
  }

  // Otherwise, an arbitrary expression can be the receiver of a send.
  ExprResult Res = Actions.CorrectDelayedTyposInExpr(ParseExpression());
  if (Res.isInvalid()) {
    SkipUntil(tok::r_square, StopAtSemi);
    return Res;
  }

  return ParseObjCMessageExpressionBody(LBracLoc, SourceLocation(), nullptr,
                                        Res.get());
}

/// Parse the remainder of an Objective-C message following the
/// '[' objc-receiver.
///
/// This routine handles sends to super, class messages (sent to a
/// class name), and instance messages (sent to an object), and the
/// target is represented by \p SuperLoc, \p ReceiverType, or \p
/// ReceiverExpr, respectively. Only one of these parameters may have
/// a valid value.
///
/// \param LBracLoc The location of the opening '['.
///
/// \param SuperLoc If this is a send to 'super', the location of the
/// 'super' keyword that indicates a send to the superclass.
///
/// \param ReceiverType If this is a class message, the type of the
/// class we are sending a message to.
///
/// \param ReceiverExpr If this is an instance message, the expression
/// used to compute the receiver object.
///
///   objc-message-args:
///     objc-selector
///     objc-keywordarg-list
///
///   objc-keywordarg-list:
///     objc-keywordarg
///     objc-keywordarg-list objc-keywordarg
///
///   objc-keywordarg:
///     selector-name[opt] ':' objc-keywordexpr
///
///   objc-keywordexpr:
///     nonempty-expr-list
///
///   nonempty-expr-list:
///     assignment-expression
///     nonempty-expr-list , assignment-expression
///
ExprResult
Parser::ParseObjCMessageExpressionBody(SourceLocation LBracLoc,
                                       SourceLocation SuperLoc,
                                       ParsedType ReceiverType,
                                       Expr *ReceiverExpr) {
  InMessageExpressionRAIIObject InMessage(*this, true);

  if (Tok.is(tok::code_completion)) {
    if (SuperLoc.isValid())
      Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
                                           false);
    else if (ReceiverType)
      Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
                                           false);
    else
      Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                              None, false);
    cutOffParsing();
    return ExprError();
  }

  // Parse objc-selector
  SourceLocation Loc;
  IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);

  SmallVector<IdentifierInfo *, 12> KeyIdents;
  SmallVector<SourceLocation, 12> KeyLocs;
  ExprVector KeyExprs;

  if (Tok.is(tok::colon)) {
    while (1) {
      // Each iteration parses a single keyword argument.
      KeyIdents.push_back(selIdent);
      KeyLocs.push_back(Loc);

      if (ExpectAndConsume(tok::colon)) {
        // We must manually skip to a ']', otherwise the expression skipper will
        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
        // the enclosing expression.
        SkipUntil(tok::r_square, StopAtSemi);
        return ExprError();
      }

      ///  Parse the expression after ':'

      if (Tok.is(tok::code_completion)) {
        if (SuperLoc.isValid())
          Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
                                               KeyIdents,
                                               /*AtArgumentEpression=*/true);
        else if (ReceiverType)
          Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
                                               KeyIdents,
                                               /*AtArgumentEpression=*/true);
        else
          Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                                  KeyIdents,
                                                  /*AtArgumentEpression=*/true);

        cutOffParsing();
        return ExprError();
      }

      ExprResult Expr;
      if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
        Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
        Expr = ParseBraceInitializer();
      } else
        Expr = ParseAssignmentExpression();

      ExprResult Res(Expr);
      if (Res.isInvalid()) {
        // We must manually skip to a ']', otherwise the expression skipper will
        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
        // the enclosing expression.
        SkipUntil(tok::r_square, StopAtSemi);
        return Res;
      }

      // We have a valid expression.
      KeyExprs.push_back(Res.get());

      // Code completion after each argument.
      if (Tok.is(tok::code_completion)) {
        if (SuperLoc.isValid())
          Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc,
                                               KeyIdents,
                                               /*AtArgumentEpression=*/false);
        else if (ReceiverType)
          Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
                                               KeyIdents,
                                               /*AtArgumentEpression=*/false);
        else
          Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                                  KeyIdents,
                                                /*AtArgumentEpression=*/false);
        cutOffParsing();
        return ExprError();
      }

      // Check for another keyword selector.
      selIdent = ParseObjCSelectorPiece(Loc);
      if (!selIdent && Tok.isNot(tok::colon))
        break;
      // We have a selector or a colon, continue parsing.
    }
    // Parse the, optional, argument list, comma separated.
    while (Tok.is(tok::comma)) {
      SourceLocation commaLoc = ConsumeToken(); // Eat the ','.
      ///  Parse the expression after ','
      ExprResult Res(ParseAssignmentExpression());
      if (Tok.is(tok::colon))
        Res = Actions.CorrectDelayedTyposInExpr(Res);
      if (Res.isInvalid()) {
        if (Tok.is(tok::colon)) {
          Diag(commaLoc, diag::note_extra_comma_message_arg) <<
            FixItHint::CreateRemoval(commaLoc);
        }
        // We must manually skip to a ']', otherwise the expression skipper will
        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
        // the enclosing expression.
        SkipUntil(tok::r_square, StopAtSemi);
        return Res;
      }

      // We have a valid expression.
      KeyExprs.push_back(Res.get());
    }
  } else if (!selIdent) {
    Diag(Tok, diag::err_expected) << tok::identifier; // missing selector name.

    // We must manually skip to a ']', otherwise the expression skipper will
    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    // the enclosing expression.
    SkipUntil(tok::r_square, StopAtSemi);
    return ExprError();
  }

  if (Tok.isNot(tok::r_square)) {
    Diag(Tok, diag::err_expected)
        << (Tok.is(tok::identifier) ? tok::colon : tok::r_square);
    // We must manually skip to a ']', otherwise the expression skipper will
    // stop at the ']' when it skips to the ';'.  We want it to skip beyond
    // the enclosing expression.
    SkipUntil(tok::r_square, StopAtSemi);
    return ExprError();
  }

  SourceLocation RBracLoc = ConsumeBracket(); // consume ']'

  unsigned nKeys = KeyIdents.size();
  if (nKeys == 0) {
    KeyIdents.push_back(selIdent);
    KeyLocs.push_back(Loc);
  }
  Selector Sel = PP.getSelectorTable().getSelector(nKeys, &KeyIdents[0]);

  if (SuperLoc.isValid())
    return Actions.ActOnSuperMessage(getCurScope(), SuperLoc, Sel,
                                     LBracLoc, KeyLocs, RBracLoc, KeyExprs);
  else if (ReceiverType)
    return Actions.ActOnClassMessage(getCurScope(), ReceiverType, Sel,
                                     LBracLoc, KeyLocs, RBracLoc, KeyExprs);
  return Actions.ActOnInstanceMessage(getCurScope(), ReceiverExpr, Sel,
                                      LBracLoc, KeyLocs, RBracLoc, KeyExprs);
}

ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
  ExprResult Res(ParseStringLiteralExpression());
  if (Res.isInvalid()) return Res;

  // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
  // expressions.  At this point, we know that the only valid thing that starts
  // with '@' is an @"".
  SmallVector<SourceLocation, 4> AtLocs;
  ExprVector AtStrings;
  AtLocs.push_back(AtLoc);
  AtStrings.push_back(Res.get());

  while (Tok.is(tok::at)) {
    AtLocs.push_back(ConsumeToken()); // eat the @.

    // Invalid unless there is a string literal.
    if (!isTokenStringLiteral())
      return ExprError(Diag(Tok, diag::err_objc_concat_string));

    ExprResult Lit(ParseStringLiteralExpression());
    if (Lit.isInvalid())
      return Lit;

    AtStrings.push_back(Lit.get());
  }

  return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings);
}

/// ParseObjCBooleanLiteral -
/// objc-scalar-literal : '@' boolean-keyword
///                        ;
/// boolean-keyword: 'true' | 'false' | '__objc_yes' | '__objc_no'
///                        ;
ExprResult Parser::ParseObjCBooleanLiteral(SourceLocation AtLoc,
                                           bool ArgValue) {
  SourceLocation EndLoc = ConsumeToken();             // consume the keyword.
  return Actions.ActOnObjCBoolLiteral(AtLoc, EndLoc, ArgValue);
}

/// ParseObjCCharacterLiteral -
/// objc-scalar-literal : '@' character-literal
///                        ;
ExprResult Parser::ParseObjCCharacterLiteral(SourceLocation AtLoc) {
  ExprResult Lit(Actions.ActOnCharacterConstant(Tok));
  if (Lit.isInvalid()) {
    return Lit;
  }
  ConsumeToken(); // Consume the literal token.
  return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
}

/// ParseObjCNumericLiteral -
/// objc-scalar-literal : '@' scalar-literal
///                        ;
/// scalar-literal : | numeric-constant			/* any numeric constant. */
///                    ;
ExprResult Parser::ParseObjCNumericLiteral(SourceLocation AtLoc) {
  ExprResult Lit(Actions.ActOnNumericConstant(Tok));
  if (Lit.isInvalid()) {
    return Lit;
  }
  ConsumeToken(); // Consume the literal token.
  return Actions.BuildObjCNumericLiteral(AtLoc, Lit.get());
}

/// ParseObjCBoxedExpr -
/// objc-box-expression:
///       @( assignment-expression )
ExprResult
Parser::ParseObjCBoxedExpr(SourceLocation AtLoc) {
  if (Tok.isNot(tok::l_paren))
    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@");

  BalancedDelimiterTracker T(*this, tok::l_paren);
  T.consumeOpen();
  ExprResult ValueExpr(ParseAssignmentExpression());
  if (T.consumeClose())
    return ExprError();

  if (ValueExpr.isInvalid())
    return ExprError();

  // Wrap the sub-expression in a parenthesized expression, to distinguish
  // a boxed expression from a literal.
  SourceLocation LPLoc = T.getOpenLocation(), RPLoc = T.getCloseLocation();
  ValueExpr = Actions.ActOnParenExpr(LPLoc, RPLoc, ValueExpr.get());
  return Actions.BuildObjCBoxedExpr(SourceRange(AtLoc, RPLoc),
                                    ValueExpr.get());
}

ExprResult Parser::ParseObjCArrayLiteral(SourceLocation AtLoc) {
  ExprVector ElementExprs;                   // array elements.
  ConsumeBracket(); // consume the l_square.

  bool HasInvalidEltExpr = false;
  while (Tok.isNot(tok::r_square)) {
    // Parse list of array element expressions (all must be id types).
    ExprResult Res(ParseAssignmentExpression());
    if (Res.isInvalid()) {
      // We must manually skip to a ']', otherwise the expression skipper will
      // stop at the ']' when it skips to the ';'.  We want it to skip beyond
      // the enclosing expression.
      SkipUntil(tok::r_square, StopAtSemi);
      return Res;
    }

    Res = Actions.CorrectDelayedTyposInExpr(Res.get());
    if (Res.isInvalid())
      HasInvalidEltExpr = true;

    // Parse the ellipsis that indicates a pack expansion.
    if (Tok.is(tok::ellipsis))
      Res = Actions.ActOnPackExpansion(Res.get(), ConsumeToken());
    if (Res.isInvalid())
      HasInvalidEltExpr = true;

    ElementExprs.push_back(Res.get());

    if (Tok.is(tok::comma))
      ConsumeToken(); // Eat the ','.
    else if (Tok.isNot(tok::r_square))
      return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_square
                                                            << tok::comma);
  }
  SourceLocation EndLoc = ConsumeBracket(); // location of ']'

  if (HasInvalidEltExpr)
    return ExprError();

  MultiExprArg Args(ElementExprs);
  return Actions.BuildObjCArrayLiteral(SourceRange(AtLoc, EndLoc), Args);
}

ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) {
  SmallVector<ObjCDictionaryElement, 4> Elements; // dictionary elements.
  ConsumeBrace(); // consume the l_square.
  bool HasInvalidEltExpr = false;
  while (Tok.isNot(tok::r_brace)) {
    // Parse the comma separated key : value expressions.
    ExprResult KeyExpr;
    {
      ColonProtectionRAIIObject X(*this);
      KeyExpr = ParseAssignmentExpression();
      if (KeyExpr.isInvalid()) {
        // We must manually skip to a '}', otherwise the expression skipper will
        // stop at the '}' when it skips to the ';'.  We want it to skip beyond
        // the enclosing expression.
        SkipUntil(tok::r_brace, StopAtSemi);
        return KeyExpr;
      }
    }

    if (ExpectAndConsume(tok::colon)) {
      SkipUntil(tok::r_brace, StopAtSemi);
      return ExprError();
    }

    ExprResult ValueExpr(ParseAssignmentExpression());
    if (ValueExpr.isInvalid()) {
      // We must manually skip to a '}', otherwise the expression skipper will
      // stop at the '}' when it skips to the ';'.  We want it to skip beyond
      // the enclosing expression.
      SkipUntil(tok::r_brace, StopAtSemi);
      return ValueExpr;
    }

    // Check the key and value for possible typos
    KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
    ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
    if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
      HasInvalidEltExpr = true;

    // Parse the ellipsis that designates this as a pack expansion. Do not
    // ActOnPackExpansion here, leave it to template instantiation time where
    // we can get better diagnostics.
    SourceLocation EllipsisLoc;
    if (getLangOpts().CPlusPlus)
      TryConsumeToken(tok::ellipsis, EllipsisLoc);

    // We have a valid expression. Collect it in a vector so we can
    // build the argument list.
    ObjCDictionaryElement Element = {
      KeyExpr.get(), ValueExpr.get(), EllipsisLoc, None
    };
    Elements.push_back(Element);

    if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
      return ExprError(Diag(Tok, diag::err_expected_either) << tok::r_brace
                                                            << tok::comma);
  }
  SourceLocation EndLoc = ConsumeBrace();

  if (HasInvalidEltExpr)
    return ExprError();

  // Create the ObjCDictionaryLiteral.
  return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc),
                                            Elements);
}

///    objc-encode-expression:
///      \@encode ( type-name )
ExprResult
Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
  assert(Tok.isObjCAtKeyword(tok::objc_encode) && "Not an @encode expression!");

  SourceLocation EncLoc = ConsumeToken();

  if (Tok.isNot(tok::l_paren))
    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@encode");

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

  TypeResult Ty = ParseTypeName();

  T.consumeClose();

  if (Ty.isInvalid())
    return ExprError();

  return Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, T.getOpenLocation(),
                                           Ty.get(), T.getCloseLocation());
}

///     objc-protocol-expression
///       \@protocol ( protocol-name )
ExprResult
Parser::ParseObjCProtocolExpression(SourceLocation AtLoc) {
  SourceLocation ProtoLoc = ConsumeToken();

  if (Tok.isNot(tok::l_paren))
    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@protocol");

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

  if (expectIdentifier())
    return ExprError();

  IdentifierInfo *protocolId = Tok.getIdentifierInfo();
  SourceLocation ProtoIdLoc = ConsumeToken();

  T.consumeClose();

  return Actions.ParseObjCProtocolExpression(protocolId, AtLoc, ProtoLoc,
                                             T.getOpenLocation(), ProtoIdLoc,
                                             T.getCloseLocation());
}

///     objc-selector-expression
///       @selector '(' '('[opt] objc-keyword-selector ')'[opt] ')'
ExprResult Parser::ParseObjCSelectorExpression(SourceLocation AtLoc) {
  SourceLocation SelectorLoc = ConsumeToken();

  if (Tok.isNot(tok::l_paren))
    return ExprError(Diag(Tok, diag::err_expected_lparen_after) << "@selector");

  SmallVector<IdentifierInfo *, 12> KeyIdents;
  SourceLocation sLoc;

  BalancedDelimiterTracker T(*this, tok::l_paren);
  T.consumeOpen();
  bool HasOptionalParen = Tok.is(tok::l_paren);
  if (HasOptionalParen)
    ConsumeParen();

  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
    cutOffParsing();
    return ExprError();
  }

  IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
  if (!SelIdent &&  // missing selector name.
      Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
    return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);

  KeyIdents.push_back(SelIdent);

  unsigned nColons = 0;
  if (Tok.isNot(tok::r_paren)) {
    while (1) {
      if (TryConsumeToken(tok::coloncolon)) { // Handle :: in C++.
        ++nColons;
        KeyIdents.push_back(nullptr);
      } else if (ExpectAndConsume(tok::colon)) // Otherwise expect ':'.
        return ExprError();
      ++nColons;

      if (Tok.is(tok::r_paren))
        break;

      if (Tok.is(tok::code_completion)) {
        Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
        cutOffParsing();
        return ExprError();
      }

      // Check for another keyword selector.
      SourceLocation Loc;
      SelIdent = ParseObjCSelectorPiece(Loc);
      KeyIdents.push_back(SelIdent);
      if (!SelIdent && Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
        break;
    }
  }
  if (HasOptionalParen && Tok.is(tok::r_paren))
    ConsumeParen(); // ')'
  T.consumeClose();
  Selector Sel = PP.getSelectorTable().getSelector(nColons, &KeyIdents[0]);
  return Actions.ParseObjCSelectorExpression(Sel, AtLoc, SelectorLoc,
                                             T.getOpenLocation(),
                                             T.getCloseLocation(),
                                             !HasOptionalParen);
}

void Parser::ParseLexedObjCMethodDefs(LexedMethod &LM, bool parseMethod) {
  // MCDecl might be null due to error in method or c-function  prototype, etc.
  Decl *MCDecl = LM.D;
  bool skip = MCDecl &&
              ((parseMethod && !Actions.isObjCMethodDecl(MCDecl)) ||
              (!parseMethod && Actions.isObjCMethodDecl(MCDecl)));
  if (skip)
    return;

  // Save the current token position.
  SourceLocation OrigLoc = Tok.getLocation();

  assert(!LM.Toks.empty() && "ParseLexedObjCMethodDef - Empty body!");
  // Store an artificial EOF token to ensure that we don't run off the end of
  // the method's body when we come to parse it.
  Token Eof;
  Eof.startToken();
  Eof.setKind(tok::eof);
  Eof.setEofData(MCDecl);
  Eof.setLocation(OrigLoc);
  LM.Toks.push_back(Eof);
  // Append the current token at the end of the new token stream so that it
  // doesn't get lost.
  LM.Toks.push_back(Tok);
  PP.EnterTokenStream(LM.Toks, true);

  // Consume the previously pushed token.
  ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);

  assert(Tok.isOneOf(tok::l_brace, tok::kw_try, tok::colon) &&
         "Inline objective-c method not starting with '{' or 'try' or ':'");
  // Enter a scope for the method or c-function body.
  ParseScope BodyScope(this, (parseMethod ? Scope::ObjCMethodScope : 0) |
                                 Scope::FnScope | Scope::DeclScope |
                                 Scope::CompoundStmtScope);

  // Tell the actions module that we have entered a method or c-function definition
  // with the specified Declarator for the method/function.
  if (parseMethod)
    Actions.ActOnStartOfObjCMethodDef(getCurScope(), MCDecl);
  else
    Actions.ActOnStartOfFunctionDef(getCurScope(), MCDecl);
  if (Tok.is(tok::kw_try))
    ParseFunctionTryBlock(MCDecl, BodyScope);
  else {
    if (Tok.is(tok::colon))
      ParseConstructorInitializer(MCDecl);
    else
      Actions.ActOnDefaultCtorInitializers(MCDecl);
    ParseFunctionStatementBody(MCDecl, BodyScope);
  }

  if (Tok.getLocation() != OrigLoc) {
    // Due to parsing error, we either went over the cached tokens or
    // there are still cached tokens left. If it's the latter case skip the
    // leftover tokens.
    // Since this is an uncommon situation that should be avoided, use the
    // expensive isBeforeInTranslationUnit call.
    if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(),
                                                     OrigLoc))
      while (Tok.getLocation() != OrigLoc && Tok.isNot(tok::eof))
        ConsumeAnyToken();
  }
  // Clean up the remaining EOF token.
  ConsumeAnyToken();
}
