//===--- 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.
      if (contextKey != tok::objc_protocol)
        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
      else
        MethodImplKind = DirectiveKind;
      break;

    case tok::objc_property:
      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();

  ObjCDeclContextSwitch ObjCDC(*this);

  // Parse type qualifiers, in, inout, etc.
  ParseObjCTypeQualifierList(DS, context);
  SourceLocation TypeStartLoc = Tok.getLocation();

  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, /*IsReinject*/true);
        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,
                                               /*AtArgumentExpression=*/true);
        else if (ReceiverType)
          Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
                                               KeyIdents,
                                               /*AtArgumentExpression=*/true);
        else
          Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                                  KeyIdents,
                                                  /*AtArgumentExpression=*/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,
                                               /*AtArgumentExpression=*/false);
        else if (ReceiverType)
          Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType,
                                               KeyIdents,
                                               /*AtArgumentExpression=*/false);
        else
          Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                                  KeyIdents,
                                                /*AtArgumentExpression=*/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, /*IsReinject*/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();
}
