//===--- ParseObjC.cpp - Objective C Parsing ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements the Objective-C portions of the Parser interface.
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/Parser.h"
#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/RAIIObjectsForParser.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/PrettyDeclStackTrace.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() {
  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: {
    ParsedAttributes attrs(AttrFactory);
    SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs);
    break;
  }
  case tok::objc_protocol: {
    ParsedAttributes attrs(AttrFactory);
    return ParseObjCAtProtocolDeclaration(AtLoc, attrs);
  }
  case tok::objc_implementation:
    return ParseObjCAtImplementationDeclaration(AtLoc);
  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)
      return ParseModuleImport(AtLoc);
    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->getLocStart(), 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().ObjC2) {
      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.getList());

    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.getList());

  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 = [&]() -> AttributeList * {
    return D.getAttributePool().create(
             P.getNullabilityKeyword(nullability),
             SourceRange(nullabilityLoc),
             nullptr, SourceLocation(),
             nullptr, 0,
             AttributeList::AS_ContextSensitiveKeyword);
  };

  if (D.getNumTypeObjects() > 0) {
    // Add the attribute to the declarator chunk nearest the declarator.
    auto nullabilityAttr = getNullabilityAttr();
    DeclaratorChunk &chunk = D.getTypeObject(0);
    nullabilityAttr->setNext(chunk.getAttrListRef());
    chunk.getAttrListRef() = nullabilityAttr;
  } else if (!addedToDeclSpec) {
    // Otherwise, just put it on the declaration specifiers (if one
    // isn't there already).
    D.getMutableDeclSpec().addAttributes(getNullabilityAttr());
    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)) {
      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);
      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->getLocStart(), diag::note_objc_container_start)
          << (int) Actions.getObjCContainerKind();
      ConsumeToken();
      break;
        
    case tok::objc_required:
    case tok::objc_optional:
      // This is only valid on protocols.
      // FIXME: Should this check for ObjC2 being enabled?
      if (contextKey != tok::objc_protocol)
        Diag(AtLoc, diag::err_objc_directive_only_in_protocol);
      else
        MethodImplKind = DirectiveKind;
      break;

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

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

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

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

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

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

        FD.complete(Property);
      };

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

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

  // We break out of the big loop in two cases: when we see @end or when we see
  // EOF.  In the former case, eat the @end.  In the later case, emit an error.
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCAtDirective(getCurScope());
    return cutOffParsing();
  } else if (Tok.isObjCAtKeyword(tok::objc_end)) {
    ConsumeToken(); // the "end" identifier
  } else {
    Diag(Tok, diag::err_objc_missing_end)
        << FixItHint::CreateInsertion(Tok.getLocation(), "\n@end\n");
    Diag(CDecl->getLocStart(), 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().ObjC2 && 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,
                                        Declarator::TheContext Context) {
  assert(Context == Declarator::ObjCParameterContext ||
         Context == Declarator::ObjCResultContext);

  while (1) {
    if (Tok.is(tok::code_completion)) {
      Actions.CodeCompleteObjCPassingType(getCurScope(), DS, 
                          Context == Declarator::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(ParsedAttributes &attrs,
                               AttributeList *list) {
  while (list) {
    AttributeList *cur = list;
    list = cur->getNext();

    if (!cur->isUsedAsTypeAttr()) {
      // Clear out the next pointer.  We're really completely
      // destroying the internal invariants of the declarator here,
      // but it doesn't matter because we're done with it.
      cur->setNext(nullptr);
      attrs.add(cur);
    }
  }
}

/// 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.getDeclSpec().getAttributes().getList());
  takeDeclAttributes(attrs, D.getAttributes());
  for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i)
    takeDeclAttributes(attrs,
                  const_cast<AttributeList*>(D.getTypeObject(i).getAttrs()));
}

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

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

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

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

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

  ParsedType Ty;
  if (isTypeSpecifierQualifier() || isObjCInstancetype()) {
    // Parse an abstract declarator.
    DeclSpec declSpec(AttrFactory);
    declSpec.setObjCQualifiers(&DS);
    DeclSpecContext dsContext = DSC_normal;
    if (context == Declarator::ObjCResultContext)
      dsContext = 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 == Declarator::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, Declarator::ObjCResultContext,
                                   nullptr);

  // If attributes exist before the method, parse them.
  ParsedAttributes methodAttrs(AttrFactory);
  if (getLangOpts().ObjC2)
    MaybeParseGNUAttributes(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().ObjC2)
      MaybeParseGNUAttributes(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.getList(), 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,
                                       Declarator::ObjCParameterContext,
                                       &paramAttrs);

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

    // 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, Declarator::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().ObjC2)
    MaybeParseGNUAttributes(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.getList(),
                                        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().ObjC1 && "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, Declarator::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(), nullptr);
}

///   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 ';'
///
///   objc-visibility-spec:
///     @private
///     @protected
///     @public
///     @package [OBJC2]
///
///   objc-instance-variable-decl:
///     struct-declaration
///
void Parser::ParseObjCClassInstanceVariables(Decl *interfaceDecl,
                                             tok::ObjCKeywordKind visibility,
                                             SourceLocation atLoc) {
  assert(Tok.is(tok::l_brace) && "expected {");
  SmallVector<Decl *, 32> AllIvarDecls;
    
  ParseScope ClassScope(this, Scope::DeclScope|Scope::ClassScope);
  ObjCDeclContextSwitch ObjCDC(*this);

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

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

    // Set the default visibility to private.
    if (TryConsumeToken(tok::at)) { // parse objc-visibility-spec
      if (Tok.is(tok::code_completion)) {
        Actions.CodeCompleteObjCAtVisibility(getCurScope());
        return cutOffParsing();
      }
      
      switch (Tok.getObjCKeywordID()) {
      case tok::objc_private:
      case tok::objc_public:
      case tok::objc_protected:
      case tok::objc_package:
        visibility = Tok.getObjCKeywordID();
        ConsumeToken();
        continue;

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

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

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

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

  // 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.getList());

  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) {
  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);

  } 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);
  
    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->getLocStart(), 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*/);
  
  /// \brief 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, Declarator::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);

      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());
      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, 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) {
  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 Actions.ActOnExprStmt(Res);
}

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

/// \brief 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, Declarator::TypeNameContext);
  TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo);
  if (Type.isInvalid())
    return true;

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

/// \brief 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().ObjC1 &&
         "Incorrect start for isSimpleObjCMessageExpression");
  return GetLookAheadToken(1).is(tok::identifier) &&
         GetLookAheadToken(2).is(tok::identifier);
}

bool Parser::isStartOfObjCClassMessageMissingOpenBracket() {
  if (!getLangOpts().ObjC1 || !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());
}

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

  if (Tok.is(tok::code_completion)) {
    if (SuperLoc.isValid())
      Actions.CodeCompleteObjCSuperMessage(getCurScope(), SuperLoc, None,
                                           false);
    else if (ReceiverType)
      Actions.CodeCompleteObjCClassMessage(getCurScope(), ReceiverType, None,
                                           false);
    else
      Actions.CodeCompleteObjCInstanceMessage(getCurScope(), ReceiverExpr,
                                              None, false);
    cutOffParsing();
    return ExprError();
  }
  
  // Parse objc-selector
  SourceLocation Loc;
  IdentifierInfo *selIdent = ParseObjCSelectorPiece(Loc);
  
  SmallVector<IdentifierInfo *, 12> KeyIdents;
  SmallVector<SourceLocation, 12> KeyLocs;
  ExprVector KeyExprs;

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

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

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

        cutOffParsing();
        return ExprError();
      }
      
      ExprResult Expr;
      if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
        Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
        Expr = ParseBraceInitializer();
      } else
        Expr = ParseAssignmentExpression();
      
      ExprResult Res(Expr);
      if (Res.isInvalid()) {
        // We must manually skip to a ']', otherwise the expression skipper will
        // stop at the ']' when it skips to the ';'.  We want it to skip beyond
        // the enclosing expression.
        SkipUntil(tok::r_square, StopAtSemi);
        return Res;
      }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    ElementExprs.push_back(Res.get());

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

  if (HasInvalidEltExpr)
    return ExprError();

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

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

    if (ExpectAndConsume(tok::colon)) {
      SkipUntil(tok::r_brace, StopAtSemi);
      return ExprError();
    }
    
    ExprResult ValueExpr(ParseAssignmentExpression());
    if (ValueExpr.isInvalid()) {
      // We must manually skip to a '}', otherwise the expression skipper will
      // stop at the '}' when it skips to the ';'.  We want it to skip beyond
      // the enclosing expression.
      SkipUntil(tok::r_brace, StopAtSemi);
      return ValueExpr;
    }
    
    // Check the key and value for possible typos
    KeyExpr = Actions.CorrectDelayedTyposInExpr(KeyExpr.get());
    ValueExpr = Actions.CorrectDelayedTyposInExpr(ValueExpr.get());
    if (KeyExpr.isInvalid() || ValueExpr.isInvalid())
      HasInvalidEltExpr = true;

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

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

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

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

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

  SourceLocation EncLoc = ConsumeToken();

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

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

  TypeResult Ty = ParseTypeName();

  T.consumeClose();

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

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

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

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

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

  if (expectIdentifier())
    return ExprError();

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

  T.consumeClose();

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

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

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

  SmallVector<IdentifierInfo *, 12> KeyIdents;
  SourceLocation sLoc;
  
  BalancedDelimiterTracker T(*this, tok::l_paren);
  T.consumeOpen();
  bool HasOptionalParen = Tok.is(tok::l_paren);
  if (HasOptionalParen)
    ConsumeParen();
  
  if (Tok.is(tok::code_completion)) {
    Actions.CodeCompleteObjCSelector(getCurScope(), KeyIdents);
    cutOffParsing();
    return ExprError();
  }
  
  IdentifierInfo *SelIdent = ParseObjCSelectorPiece(sLoc);
  if (!SelIdent &&  // missing selector name.
      Tok.isNot(tok::colon) && Tok.isNot(tok::coloncolon))
    return ExprError(Diag(Tok, diag::err_expected) << tok::identifier);

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

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

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

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

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

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

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

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