//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file implements semantic analysis for Objective C declarations.
//
//===----------------------------------------------------------------------===//

#include "TypeLocBuilder.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Initialization.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/Scope.h"
#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaObjC.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"

using namespace clang;

/// Check whether the given method, which must be in the 'init'
/// family, is a valid member of that family.
///
/// \param receiverTypeIfCall - if null, check this as if declaring it;
///   if non-null, check this as if making a call to it with the given
///   receiver type
///
/// \return true to indicate that there was an error and appropriate
///   actions were taken
bool SemaObjC::checkInitMethod(ObjCMethodDecl *method,
                               QualType receiverTypeIfCall) {
  ASTContext &Context = getASTContext();
  if (method->isInvalidDecl()) return true;

  // This castAs is safe: methods that don't return an object
  // pointer won't be inferred as inits and will reject an explicit
  // objc_method_family(init).

  // We ignore protocols here.  Should we?  What about Class?

  const ObjCObjectType *result =
      method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType();

  if (result->isObjCId()) {
    return false;
  } else if (result->isObjCClass()) {
    // fall through: always an error
  } else {
    ObjCInterfaceDecl *resultClass = result->getInterface();
    assert(resultClass && "unexpected object type!");

    // It's okay for the result type to still be a forward declaration
    // if we're checking an interface declaration.
    if (!resultClass->hasDefinition()) {
      if (receiverTypeIfCall.isNull() &&
          !isa<ObjCImplementationDecl>(method->getDeclContext()))
        return false;

    // Otherwise, we try to compare class types.
    } else {
      // If this method was declared in a protocol, we can't check
      // anything unless we have a receiver type that's an interface.
      const ObjCInterfaceDecl *receiverClass = nullptr;
      if (isa<ObjCProtocolDecl>(method->getDeclContext())) {
        if (receiverTypeIfCall.isNull())
          return false;

        receiverClass = receiverTypeIfCall->castAs<ObjCObjectPointerType>()
          ->getInterfaceDecl();

        // This can be null for calls to e.g. id<Foo>.
        if (!receiverClass) return false;
      } else {
        receiverClass = method->getClassInterface();
        assert(receiverClass && "method not associated with a class!");
      }

      // If either class is a subclass of the other, it's fine.
      if (receiverClass->isSuperClassOf(resultClass) ||
          resultClass->isSuperClassOf(receiverClass))
        return false;
    }
  }

  SourceLocation loc = method->getLocation();

  // If we're in a system header, and this is not a call, just make
  // the method unusable.
  if (receiverTypeIfCall.isNull() &&
      SemaRef.getSourceManager().isInSystemHeader(loc)) {
    method->addAttr(UnavailableAttr::CreateImplicit(Context, "",
                      UnavailableAttr::IR_ARCInitReturnsUnrelated, loc));
    return true;
  }

  // Otherwise, it's an error.
  Diag(loc, diag::err_arc_init_method_unrelated_result_type);
  method->setInvalidDecl();
  return true;
}

/// Issue a warning if the parameter of the overridden method is non-escaping
/// but the parameter of the overriding method is not.
static bool diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
                             Sema &S) {
  if (OldD->hasAttr<NoEscapeAttr>() && !NewD->hasAttr<NoEscapeAttr>()) {
    S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape);
    S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape);
    return false;
  }

  return true;
}

/// Produce additional diagnostics if a category conforms to a protocol that
/// defines a method taking a non-escaping parameter.
static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,
                             const ObjCCategoryDecl *CD,
                             const ObjCProtocolDecl *PD, Sema &S) {
  if (!diagnoseNoescape(NewD, OldD, S))
    S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot)
        << CD->IsClassExtension() << PD
        << cast<ObjCMethodDecl>(NewD->getDeclContext());
}

void SemaObjC::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
                                       const ObjCMethodDecl *Overridden) {
  ASTContext &Context = getASTContext();
  if (Overridden->hasRelatedResultType() &&
      !NewMethod->hasRelatedResultType()) {
    // This can only happen when the method follows a naming convention that
    // implies a related result type, and the original (overridden) method has
    // a suitable return type, but the new (overriding) method does not have
    // a suitable return type.
    QualType ResultType = NewMethod->getReturnType();
    SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange();

    // Figure out which class this method is part of, if any.
    ObjCInterfaceDecl *CurrentClass
      = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext());
    if (!CurrentClass) {
      DeclContext *DC = NewMethod->getDeclContext();
      if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC))
        CurrentClass = Cat->getClassInterface();
      else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC))
        CurrentClass = Impl->getClassInterface();
      else if (ObjCCategoryImplDecl *CatImpl
               = dyn_cast<ObjCCategoryImplDecl>(DC))
        CurrentClass = CatImpl->getClassInterface();
    }

    if (CurrentClass) {
      Diag(NewMethod->getLocation(),
           diag::warn_related_result_type_compatibility_class)
        << Context.getObjCInterfaceType(CurrentClass)
        << ResultType
        << ResultTypeRange;
    } else {
      Diag(NewMethod->getLocation(),
           diag::warn_related_result_type_compatibility_protocol)
        << ResultType
        << ResultTypeRange;
    }

    if (ObjCMethodFamily Family = Overridden->getMethodFamily())
      Diag(Overridden->getLocation(),
           diag::note_related_result_type_family)
        << /*overridden method*/ 0
        << Family;
    else
      Diag(Overridden->getLocation(),
           diag::note_related_result_type_overridden);
  }

  if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
       Overridden->hasAttr<NSReturnsRetainedAttr>())) {
    Diag(NewMethod->getLocation(),
         getLangOpts().ObjCAutoRefCount
             ? diag::err_nsreturns_retained_attribute_mismatch
             : diag::warn_nsreturns_retained_attribute_mismatch)
        << 1;
    Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
  }
  if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
       Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
    Diag(NewMethod->getLocation(),
         getLangOpts().ObjCAutoRefCount
             ? diag::err_nsreturns_retained_attribute_mismatch
             : diag::warn_nsreturns_retained_attribute_mismatch)
        << 0;
    Diag(Overridden->getLocation(), diag::note_previous_decl)  << "method";
  }

  ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),
                                       oe = Overridden->param_end();
  for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(),
                                      ne = NewMethod->param_end();
       ni != ne && oi != oe; ++ni, ++oi) {
    const ParmVarDecl *oldDecl = (*oi);
    ParmVarDecl *newDecl = (*ni);
    if (newDecl->hasAttr<NSConsumedAttr>() !=
        oldDecl->hasAttr<NSConsumedAttr>()) {
      Diag(newDecl->getLocation(),
           getLangOpts().ObjCAutoRefCount
               ? diag::err_nsconsumed_attribute_mismatch
               : diag::warn_nsconsumed_attribute_mismatch);
      Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";
    }

    diagnoseNoescape(newDecl, oldDecl, SemaRef);
  }
}

/// Check a method declaration for compatibility with the Objective-C
/// ARC conventions.
bool SemaObjC::CheckARCMethodDecl(ObjCMethodDecl *method) {
  ASTContext &Context = getASTContext();
  ObjCMethodFamily family = method->getMethodFamily();
  switch (family) {
  case OMF_None:
  case OMF_finalize:
  case OMF_retain:
  case OMF_release:
  case OMF_autorelease:
  case OMF_retainCount:
  case OMF_self:
  case OMF_initialize:
  case OMF_performSelector:
    return false;

  case OMF_dealloc:
    if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {
      SourceRange ResultTypeRange = method->getReturnTypeSourceRange();
      if (ResultTypeRange.isInvalid())
        Diag(method->getLocation(), diag::err_dealloc_bad_result_type)
            << method->getReturnType()
            << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
      else
        Diag(method->getLocation(), diag::err_dealloc_bad_result_type)
            << method->getReturnType()
            << FixItHint::CreateReplacement(ResultTypeRange, "void");
      return true;
    }
    return false;

  case OMF_init:
    // If the method doesn't obey the init rules, don't bother annotating it.
    if (checkInitMethod(method, QualType()))
      return true;

    method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));

    // Don't add a second copy of this attribute, but otherwise don't
    // let it be suppressed.
    if (method->hasAttr<NSReturnsRetainedAttr>())
      return false;
    break;

  case OMF_alloc:
  case OMF_copy:
  case OMF_mutableCopy:
  case OMF_new:
    if (method->hasAttr<NSReturnsRetainedAttr>() ||
        method->hasAttr<NSReturnsNotRetainedAttr>() ||
        method->hasAttr<NSReturnsAutoreleasedAttr>())
      return false;
    break;
  }

  method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));
  return false;
}

static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,
                                                SourceLocation ImplLoc) {
  if (!ND)
    return;
  bool IsCategory = false;
  StringRef RealizedPlatform;
  AvailabilityResult Availability = ND->getAvailability(
      /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),
      &RealizedPlatform);
  if (Availability != AR_Deprecated) {
    if (isa<ObjCMethodDecl>(ND)) {
      if (Availability != AR_Unavailable)
        return;
      if (RealizedPlatform.empty())
        RealizedPlatform = S.Context.getTargetInfo().getPlatformName();
      // Warn about implementing unavailable methods, unless the unavailable
      // is for an app extension.
      if (RealizedPlatform.ends_with("_app_extension"))
        return;
      S.Diag(ImplLoc, diag::warn_unavailable_def);
      S.Diag(ND->getLocation(), diag::note_method_declared_at)
          << ND->getDeclName();
      return;
    }
    if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND)) {
      if (!CD->getClassInterface()->isDeprecated())
        return;
      ND = CD->getClassInterface();
      IsCategory = true;
    } else
      return;
  }
  S.Diag(ImplLoc, diag::warn_deprecated_def)
      << (isa<ObjCMethodDecl>(ND)
              ? /*Method*/ 0
              : isa<ObjCCategoryDecl>(ND) || IsCategory ? /*Category*/ 2
                                                        : /*Class*/ 1);
  if (isa<ObjCMethodDecl>(ND))
    S.Diag(ND->getLocation(), diag::note_method_declared_at)
        << ND->getDeclName();
  else
    S.Diag(ND->getLocation(), diag::note_previous_decl)
        << (isa<ObjCCategoryDecl>(ND) ? "category" : "class");
}

/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global
/// pool.
void SemaObjC::AddAnyMethodToGlobalPool(Decl *D) {
  ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);

  // If we don't have a valid method decl, simply return.
  if (!MDecl)
    return;
  if (MDecl->isInstanceMethod())
    AddInstanceMethodToGlobalPool(MDecl, true);
  else
    AddFactoryMethodToGlobalPool(MDecl, true);
}

/// HasExplicitOwnershipAttr - returns true when pointer to ObjC pointer
/// has explicit ownership attribute; false otherwise.
static bool
HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {
  QualType T = Param->getType();

  if (const PointerType *PT = T->getAs<PointerType>()) {
    T = PT->getPointeeType();
  } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {
    T = RT->getPointeeType();
  } else {
    return true;
  }

  // If we have a lifetime qualifier, but it's local, we must have
  // inferred it. So, it is implicit.
  return !T.getLocalQualifiers().hasObjCLifetime();
}

/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible
/// and user declared, in the method definition's AST.
void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {
  ASTContext &Context = getASTContext();
  SemaRef.ImplicitlyRetainedSelfLocs.clear();
  assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused");
  ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);

  SemaRef.PushExpressionEvaluationContext(
      SemaRef.ExprEvalContexts.back().Context);

  // If we don't have a valid method decl, simply return.
  if (!MDecl)
    return;

  QualType ResultType = MDecl->getReturnType();
  if (!ResultType->isDependentType() && !ResultType->isVoidType() &&
      !MDecl->isInvalidDecl() &&
      SemaRef.RequireCompleteType(MDecl->getLocation(), ResultType,
                                  diag::err_func_def_incomplete_result))
    MDecl->setInvalidDecl();

  // Allow all of Sema to see that we are entering a method definition.
  SemaRef.PushDeclContext(FnBodyScope, MDecl);
  SemaRef.PushFunctionScope();

  // Create Decl objects for each parameter, entrring them in the scope for
  // binding to their use.

  // Insert the invisible arguments, self and _cmd!
  MDecl->createImplicitParams(Context, MDecl->getClassInterface());

  SemaRef.PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);
  SemaRef.PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);

  // The ObjC parser requires parameter names so there's no need to check.
  SemaRef.CheckParmsForFunctionDef(MDecl->parameters(),
                                   /*CheckParameterNames=*/false);

  // Introduce all of the other parameters into this scope.
  for (auto *Param : MDecl->parameters()) {
    if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount &&
        !HasExplicitOwnershipAttr(SemaRef, Param))
      Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<
            Param->getType();

    if (Param->getIdentifier())
      SemaRef.PushOnScopeChains(Param, FnBodyScope);
  }

  // In ARC, disallow definition of retain/release/autorelease/retainCount
  if (getLangOpts().ObjCAutoRefCount) {
    switch (MDecl->getMethodFamily()) {
    case OMF_retain:
    case OMF_retainCount:
    case OMF_release:
    case OMF_autorelease:
      Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def)
        << 0 << MDecl->getSelector();
      break;

    case OMF_None:
    case OMF_dealloc:
    case OMF_finalize:
    case OMF_alloc:
    case OMF_init:
    case OMF_mutableCopy:
    case OMF_copy:
    case OMF_new:
    case OMF_self:
    case OMF_initialize:
    case OMF_performSelector:
      break;
    }
  }

  // Warn on deprecated methods under -Wdeprecated-implementations,
  // and prepare for warning on missing super calls.
  if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {
    ObjCMethodDecl *IMD =
      IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());

    if (IMD) {
      ObjCImplDecl *ImplDeclOfMethodDef =
        dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());
      ObjCContainerDecl *ContDeclOfMethodDecl =
        dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());
      ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;
      if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))
        ImplDeclOfMethodDecl = OID->getImplementation();
      else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {
        if (CD->IsClassExtension()) {
          if (ObjCInterfaceDecl *OID = CD->getClassInterface())
            ImplDeclOfMethodDecl = OID->getImplementation();
        } else
            ImplDeclOfMethodDecl = CD->getImplementation();
      }
      // No need to issue deprecated warning if deprecated mehod in class/category
      // is being implemented in its own implementation (no overriding is involved).
      if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)
        DiagnoseObjCImplementedDeprecations(SemaRef, IMD, MDecl->getLocation());
    }

    if (MDecl->getMethodFamily() == OMF_init) {
      if (MDecl->isDesignatedInitializerForTheInterface()) {
        SemaRef.getCurFunction()->ObjCIsDesignatedInit = true;
        SemaRef.getCurFunction()->ObjCWarnForNoDesignatedInitChain =
            IC->getSuperClass() != nullptr;
      } else if (IC->hasDesignatedInitializers()) {
        SemaRef.getCurFunction()->ObjCIsSecondaryInit = true;
        SemaRef.getCurFunction()->ObjCWarnForNoInitDelegation = true;
      }
    }

    // If this is "dealloc" or "finalize", set some bit here.
    // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.
    // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.
    // Only do this if the current class actually has a superclass.
    if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) {
      ObjCMethodFamily Family = MDecl->getMethodFamily();
      if (Family == OMF_dealloc) {
        if (!(getLangOpts().ObjCAutoRefCount ||
              getLangOpts().getGC() == LangOptions::GCOnly))
          SemaRef.getCurFunction()->ObjCShouldCallSuper = true;

      } else if (Family == OMF_finalize) {
        if (Context.getLangOpts().getGC() != LangOptions::NonGC)
          SemaRef.getCurFunction()->ObjCShouldCallSuper = true;

      } else {
        const ObjCMethodDecl *SuperMethod =
          SuperClass->lookupMethod(MDecl->getSelector(),
                                   MDecl->isInstanceMethod());
        SemaRef.getCurFunction()->ObjCShouldCallSuper =
            (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());
      }
    }
  }

  // Some function attributes (like OptimizeNoneAttr) need actions before
  // parsing body started.
  SemaRef.applyFunctionAttributesBeforeParsingBody(D);
}

namespace {

// Callback to only accept typo corrections that are Objective-C classes.
// If an ObjCInterfaceDecl* is given to the constructor, then the validation
// function will reject corrections to that class.
class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback {
 public:
  ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}
  explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)
      : CurrentIDecl(IDecl) {}

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();
    return ID && !declaresSameEntity(ID, CurrentIDecl);
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return std::make_unique<ObjCInterfaceValidatorCCC>(*this);
  }

 private:
  ObjCInterfaceDecl *CurrentIDecl;
};

} // end anonymous namespace

static void diagnoseUseOfProtocols(Sema &TheSema,
                                   ObjCContainerDecl *CD,
                                   ObjCProtocolDecl *const *ProtoRefs,
                                   unsigned NumProtoRefs,
                                   const SourceLocation *ProtoLocs) {
  assert(ProtoRefs);
  // Diagnose availability in the context of the ObjC container.
  Sema::ContextRAII SavedContext(TheSema, CD);
  for (unsigned i = 0; i < NumProtoRefs; ++i) {
    (void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i],
                                    /*UnknownObjCClass=*/nullptr,
                                    /*ObjCPropertyAccess=*/false,
                                    /*AvoidPartialAvailabilityChecks=*/true);
  }
}

void SemaObjC::ActOnSuperClassOfClassInterface(
    Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,
    IdentifierInfo *ClassName, SourceLocation ClassLoc,
    IdentifierInfo *SuperName, SourceLocation SuperLoc,
    ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange) {
  ASTContext &Context = getASTContext();
  // Check if a different kind of symbol declared in this scope.
  NamedDecl *PrevDecl = SemaRef.LookupSingleName(
      SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);

  if (!PrevDecl) {
    // Try to correct for a typo in the superclass name without correcting
    // to the class we're defining.
    ObjCInterfaceValidatorCCC CCC(IDecl);
    if (TypoCorrection Corrected = SemaRef.CorrectTypo(
            DeclarationNameInfo(SuperName, SuperLoc), Sema::LookupOrdinaryName,
            SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::ErrorRecovery)) {
      SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)
                                          << SuperName << ClassName);
      PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();
    }
  }

  if (declaresSameEntity(PrevDecl, IDecl)) {
    Diag(SuperLoc, diag::err_recursive_superclass)
      << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
    IDecl->setEndOfDefinitionLoc(ClassLoc);
  } else {
    ObjCInterfaceDecl *SuperClassDecl =
    dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
    QualType SuperClassType;

    // Diagnose classes that inherit from deprecated classes.
    if (SuperClassDecl) {
      (void)SemaRef.DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);
      SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);
    }

    if (PrevDecl && !SuperClassDecl) {
      // The previous declaration was not a class decl. Check if we have a
      // typedef. If we do, get the underlying class type.
      if (const TypedefNameDecl *TDecl =
              dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
        QualType T = TDecl->getUnderlyingType();
        if (T->isObjCObjectType()) {
          if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {
            SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);
            SuperClassType = Context.getTypeDeclType(
                ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, TDecl);

            // This handles the following case:
            // @interface NewI @end
            // typedef NewI DeprI __attribute__((deprecated("blah")))
            // @interface SI : DeprI /* warn here */ @end
            (void)SemaRef.DiagnoseUseOfDecl(
                const_cast<TypedefNameDecl *>(TDecl), SuperLoc);
          }
        }
      }

      // This handles the following case:
      //
      // typedef int SuperClass;
      // @interface MyClass : SuperClass {} @end
      //
      if (!SuperClassDecl) {
        Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      }
    }

    if (!isa_and_nonnull<TypedefNameDecl>(PrevDecl)) {
      if (!SuperClassDecl)
        Diag(SuperLoc, diag::err_undef_superclass)
          << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);
      else if (SemaRef.RequireCompleteType(
                   SuperLoc, SuperClassType, diag::err_forward_superclass,
                   SuperClassDecl->getDeclName(), ClassName,
                   SourceRange(AtInterfaceLoc, ClassLoc))) {
        SuperClassDecl = nullptr;
        SuperClassType = QualType();
      }
    }

    if (SuperClassType.isNull()) {
      assert(!SuperClassDecl && "Failed to set SuperClassType?");
      return;
    }

    // Handle type arguments on the superclass.
    TypeSourceInfo *SuperClassTInfo = nullptr;
    if (!SuperTypeArgs.empty()) {
      TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(
          S, SuperLoc, SemaRef.CreateParsedType(SuperClassType, nullptr),
          SuperTypeArgsRange.getBegin(), SuperTypeArgs,
          SuperTypeArgsRange.getEnd(), SourceLocation(), {}, {},
          SourceLocation());
      if (!fullSuperClassType.isUsable())
        return;

      SuperClassType =
          SemaRef.GetTypeFromParser(fullSuperClassType.get(), &SuperClassTInfo);
    }

    if (!SuperClassTInfo) {
      SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,
                                                         SuperLoc);
    }

    IDecl->setSuperClass(SuperClassTInfo);
    IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc());
    getASTContext().addObjCSubClass(IDecl->getSuperClass(), IDecl);
  }
}

DeclResult SemaObjC::actOnObjCTypeParam(
    Scope *S, ObjCTypeParamVariance variance, SourceLocation varianceLoc,
    unsigned index, IdentifierInfo *paramName, SourceLocation paramLoc,
    SourceLocation colonLoc, ParsedType parsedTypeBound) {
  ASTContext &Context = getASTContext();
  // If there was an explicitly-provided type bound, check it.
  TypeSourceInfo *typeBoundInfo = nullptr;
  if (parsedTypeBound) {
    // The type bound can be any Objective-C pointer type.
    QualType typeBound =
        SemaRef.GetTypeFromParser(parsedTypeBound, &typeBoundInfo);
    if (typeBound->isObjCObjectPointerType()) {
      // okay
    } else if (typeBound->isObjCObjectType()) {
      // The user forgot the * on an Objective-C pointer type, e.g.,
      // "T : NSView".
      SourceLocation starLoc =
          SemaRef.getLocForEndOfToken(typeBoundInfo->getTypeLoc().getEndLoc());
      Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
           diag::err_objc_type_param_bound_missing_pointer)
        << typeBound << paramName
        << FixItHint::CreateInsertion(starLoc, " *");

      // Create a new type location builder so we can update the type
      // location information we have.
      TypeLocBuilder builder;
      builder.pushFullCopy(typeBoundInfo->getTypeLoc());

      // Create the Objective-C pointer type.
      typeBound = Context.getObjCObjectPointerType(typeBound);
      ObjCObjectPointerTypeLoc newT
        = builder.push<ObjCObjectPointerTypeLoc>(typeBound);
      newT.setStarLoc(starLoc);

      // Form the new type source information.
      typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);
    } else {
      // Not a valid type bound.
      Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),
           diag::err_objc_type_param_bound_nonobject)
        << typeBound << paramName;

      // Forget the bound; we'll default to id later.
      typeBoundInfo = nullptr;
    }

    // Type bounds cannot have qualifiers (even indirectly) or explicit
    // nullability.
    if (typeBoundInfo) {
      QualType typeBound = typeBoundInfo->getType();
      TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc();
      if (qual || typeBound.hasQualifiers()) {
        bool diagnosed = false;
        SourceRange rangeToRemove;
        if (qual) {
          if (auto attr = qual.getAs<AttributedTypeLoc>()) {
            rangeToRemove = attr.getLocalSourceRange();
            if (attr.getTypePtr()->getImmediateNullability()) {
              Diag(attr.getBeginLoc(),
                   diag::err_objc_type_param_bound_explicit_nullability)
                  << paramName << typeBound
                  << FixItHint::CreateRemoval(rangeToRemove);
              diagnosed = true;
            }
          }
        }

        if (!diagnosed) {
          Diag(qual ? qual.getBeginLoc()
                    : typeBoundInfo->getTypeLoc().getBeginLoc(),
               diag::err_objc_type_param_bound_qualified)
              << paramName << typeBound
              << typeBound.getQualifiers().getAsString()
              << FixItHint::CreateRemoval(rangeToRemove);
        }

        // If the type bound has qualifiers other than CVR, we need to strip
        // them or we'll probably assert later when trying to apply new
        // qualifiers.
        Qualifiers quals = typeBound.getQualifiers();
        quals.removeCVRQualifiers();
        if (!quals.empty()) {
          typeBoundInfo =
             Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType());
        }
      }
    }
  }

  // If there was no explicit type bound (or we removed it due to an error),
  // use 'id' instead.
  if (!typeBoundInfo) {
    colonLoc = SourceLocation();
    typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType());
  }

  // Create the type parameter.
  return ObjCTypeParamDecl::Create(Context, SemaRef.CurContext, variance,
                                   varianceLoc, index, paramLoc, paramName,
                                   colonLoc, typeBoundInfo);
}

ObjCTypeParamList *
SemaObjC::actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,
                                 ArrayRef<Decl *> typeParamsIn,
                                 SourceLocation rAngleLoc) {
  ASTContext &Context = getASTContext();
  // We know that the array only contains Objective-C type parameters.
  ArrayRef<ObjCTypeParamDecl *>
    typeParams(
      reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()),
      typeParamsIn.size());

  // Diagnose redeclarations of type parameters.
  // We do this now because Objective-C type parameters aren't pushed into
  // scope until later (after the instance variable block), but we want the
  // diagnostics to occur right after we parse the type parameter list.
  llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams;
  for (auto *typeParam : typeParams) {
    auto known = knownParams.find(typeParam->getIdentifier());
    if (known != knownParams.end()) {
      Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl)
        << typeParam->getIdentifier()
        << SourceRange(known->second->getLocation());

      typeParam->setInvalidDecl();
    } else {
      knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam));

      // Push the type parameter into scope.
      SemaRef.PushOnScopeChains(typeParam, S, /*AddToContext=*/false);
    }
  }

  // Create the parameter list.
  return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc);
}

void SemaObjC::popObjCTypeParamList(Scope *S,
                                    ObjCTypeParamList *typeParamList) {
  for (auto *typeParam : *typeParamList) {
    if (!typeParam->isInvalidDecl()) {
      S->RemoveDecl(typeParam);
      SemaRef.IdResolver.RemoveDecl(typeParam);
    }
  }
}

namespace {
  /// The context in which an Objective-C type parameter list occurs, for use
  /// in diagnostics.
  enum class TypeParamListContext {
    ForwardDeclaration,
    Definition,
    Category,
    Extension
  };
} // end anonymous namespace

/// Check consistency between two Objective-C type parameter lists, e.g.,
/// between a category/extension and an \@interface or between an \@class and an
/// \@interface.
static bool checkTypeParamListConsistency(Sema &S,
                                          ObjCTypeParamList *prevTypeParams,
                                          ObjCTypeParamList *newTypeParams,
                                          TypeParamListContext newContext) {
  // If the sizes don't match, complain about that.
  if (prevTypeParams->size() != newTypeParams->size()) {
    SourceLocation diagLoc;
    if (newTypeParams->size() > prevTypeParams->size()) {
      diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();
    } else {
      diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc());
    }

    S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)
      << static_cast<unsigned>(newContext)
      << (newTypeParams->size() > prevTypeParams->size())
      << prevTypeParams->size()
      << newTypeParams->size();

    return true;
  }

  // Match up the type parameters.
  for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) {
    ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i];
    ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i];

    // Check for consistency of the variance.
    if (newTypeParam->getVariance() != prevTypeParam->getVariance()) {
      if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant &&
          newContext != TypeParamListContext::Definition) {
        // When the new type parameter is invariant and is not part
        // of the definition, just propagate the variance.
        newTypeParam->setVariance(prevTypeParam->getVariance());
      } else if (prevTypeParam->getVariance()
                   == ObjCTypeParamVariance::Invariant &&
                 !(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&
                   cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())
                     ->getDefinition() == prevTypeParam->getDeclContext())) {
        // When the old parameter is invariant and was not part of the
        // definition, just ignore the difference because it doesn't
        // matter.
      } else {
        {
          // Diagnose the conflict and update the second declaration.
          SourceLocation diagLoc = newTypeParam->getVarianceLoc();
          if (diagLoc.isInvalid())
            diagLoc = newTypeParam->getBeginLoc();

          auto diag = S.Diag(diagLoc,
                             diag::err_objc_type_param_variance_conflict)
                        << static_cast<unsigned>(newTypeParam->getVariance())
                        << newTypeParam->getDeclName()
                        << static_cast<unsigned>(prevTypeParam->getVariance())
                        << prevTypeParam->getDeclName();
          switch (prevTypeParam->getVariance()) {
          case ObjCTypeParamVariance::Invariant:
            diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc());
            break;

          case ObjCTypeParamVariance::Covariant:
          case ObjCTypeParamVariance::Contravariant: {
            StringRef newVarianceStr
               = prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant
                   ? "__covariant"
                   : "__contravariant";
            if (newTypeParam->getVariance()
                  == ObjCTypeParamVariance::Invariant) {
              diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(),
                                                 (newVarianceStr + " ").str());
            } else {
              diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),
                                               newVarianceStr);
            }
          }
          }
        }

        S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
          << prevTypeParam->getDeclName();

        // Override the variance.
        newTypeParam->setVariance(prevTypeParam->getVariance());
      }
    }

    // If the bound types match, there's nothing to do.
    if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(),
                              newTypeParam->getUnderlyingType()))
      continue;

    // If the new type parameter's bound was explicit, complain about it being
    // different from the original.
    if (newTypeParam->hasExplicitBound()) {
      SourceRange newBoundRange = newTypeParam->getTypeSourceInfo()
                                    ->getTypeLoc().getSourceRange();
      S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict)
        << newTypeParam->getUnderlyingType()
        << newTypeParam->getDeclName()
        << prevTypeParam->hasExplicitBound()
        << prevTypeParam->getUnderlyingType()
        << (newTypeParam->getDeclName() == prevTypeParam->getDeclName())
        << prevTypeParam->getDeclName()
        << FixItHint::CreateReplacement(
             newBoundRange,
             prevTypeParam->getUnderlyingType().getAsString(
               S.Context.getPrintingPolicy()));

      S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
        << prevTypeParam->getDeclName();

      // Override the new type parameter's bound type with the previous type,
      // so that it's consistent.
      S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);
      continue;
    }

    // The new type parameter got the implicit bound of 'id'. That's okay for
    // categories and extensions (overwrite it later), but not for forward
    // declarations and @interfaces, because those must be standalone.
    if (newContext == TypeParamListContext::ForwardDeclaration ||
        newContext == TypeParamListContext::Definition) {
      // Diagnose this problem for forward declarations and definitions.
      SourceLocation insertionLoc
        = S.getLocForEndOfToken(newTypeParam->getLocation());
      std::string newCode
        = " : " + prevTypeParam->getUnderlyingType().getAsString(
                    S.Context.getPrintingPolicy());
      S.Diag(newTypeParam->getLocation(),
             diag::err_objc_type_param_bound_missing)
        << prevTypeParam->getUnderlyingType()
        << newTypeParam->getDeclName()
        << (newContext == TypeParamListContext::ForwardDeclaration)
        << FixItHint::CreateInsertion(insertionLoc, newCode);

      S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)
        << prevTypeParam->getDeclName();
    }

    // Update the new type parameter's bound to match the previous one.
    S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);
  }

  return false;
}

ObjCInterfaceDecl *SemaObjC::ActOnStartClassInterface(
    Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,
    SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
    IdentifierInfo *SuperName, SourceLocation SuperLoc,
    ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,
    Decl *const *ProtoRefs, unsigned NumProtoRefs,
    const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
    const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {
  assert(ClassName && "Missing class identifier");

  ASTContext &Context = getASTContext();
  // Check for another declaration kind with the same name.
  NamedDecl *PrevDecl = SemaRef.LookupSingleName(
      SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,
      SemaRef.forRedeclarationInCurContext());

  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
  }

  // Create a declaration to describe this @interface.
  ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);

  if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
    // A previous decl with a different name is because of
    // @compatibility_alias, for example:
    // \code
    //   @class NewImage;
    //   @compatibility_alias OldImage NewImage;
    // \endcode
    // A lookup for 'OldImage' will return the 'NewImage' decl.
    //
    // In such a case use the real declaration name, instead of the alias one,
    // otherwise we will break IdentifierResolver and redecls-chain invariants.
    // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
    // has been aliased.
    ClassName = PrevIDecl->getIdentifier();
  }

  // If there was a forward declaration with type parameters, check
  // for consistency.
  if (PrevIDecl) {
    if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {
      if (typeParamList) {
        // Both have type parameter lists; check for consistency.
        if (checkTypeParamListConsistency(SemaRef, prevTypeParamList,
                                          typeParamList,
                                          TypeParamListContext::Definition)) {
          typeParamList = nullptr;
        }
      } else {
        Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first)
          << ClassName;
        Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl)
          << ClassName;

        // Clone the type parameter list.
        SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams;
        for (auto *typeParam : *prevTypeParamList) {
          clonedTypeParams.push_back(ObjCTypeParamDecl::Create(
              Context, SemaRef.CurContext, typeParam->getVariance(),
              SourceLocation(), typeParam->getIndex(), SourceLocation(),
              typeParam->getIdentifier(), SourceLocation(),
              Context.getTrivialTypeSourceInfo(
                  typeParam->getUnderlyingType())));
        }

        typeParamList = ObjCTypeParamList::create(Context,
                                                  SourceLocation(),
                                                  clonedTypeParams,
                                                  SourceLocation());
      }
    }
  }

  ObjCInterfaceDecl *IDecl =
      ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,
                                ClassName, typeParamList, PrevIDecl, ClassLoc);
  if (PrevIDecl) {
    // Class already seen. Was it a definition?
    if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
      if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {
        SkipBody->CheckSameAsPrevious = true;
        SkipBody->New = IDecl;
        SkipBody->Previous = Def;
      } else {
        Diag(AtInterfaceLoc, diag::err_duplicate_class_def)
            << PrevIDecl->getDeclName();
        Diag(Def->getLocation(), diag::note_previous_definition);
        IDecl->setInvalidDecl();
      }
    }
  }

  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IDecl, AttrList);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);
  SemaRef.ProcessAPINotes(IDecl);

  // Merge attributes from previous declarations.
  if (PrevIDecl)
    SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);

  SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);

  // Start the definition of this class. If we're in a redefinition case, there
  // may already be a definition, so we'll end up adding to it.
  if (SkipBody && SkipBody->CheckSameAsPrevious)
    IDecl->startDuplicateDefinitionForComparison();
  else if (!IDecl->hasDefinition())
    IDecl->startDefinition();

  if (SuperName) {
    // Diagnose availability in the context of the @interface.
    Sema::ContextRAII SavedContext(SemaRef, IDecl);

    ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,
                                    ClassName, ClassLoc,
                                    SuperName, SuperLoc, SuperTypeArgs,
                                    SuperTypeArgsRange);
  } else { // we have a root class.
    IDecl->setEndOfDefinitionLoc(ClassLoc);
  }

  // Check then save referenced protocols.
  if (NumProtoRefs) {
    diagnoseUseOfProtocols(SemaRef, IDecl, (ObjCProtocolDecl *const *)ProtoRefs,
                           NumProtoRefs, ProtoLocs);
    IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
                           ProtoLocs, Context);
    IDecl->setEndOfDefinitionLoc(EndProtoLoc);
  }

  CheckObjCDeclScope(IDecl);
  ActOnObjCContainerStartDefinition(IDecl);
  return IDecl;
}

/// ActOnTypedefedProtocols - this action finds protocol list as part of the
/// typedef'ed use for a qualified super class and adds them to the list
/// of the protocols.
void SemaObjC::ActOnTypedefedProtocols(
    SmallVectorImpl<Decl *> &ProtocolRefs,
    SmallVectorImpl<SourceLocation> &ProtocolLocs, IdentifierInfo *SuperName,
    SourceLocation SuperLoc) {
  if (!SuperName)
    return;
  NamedDecl *IDecl = SemaRef.LookupSingleName(
      SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);
  if (!IDecl)
    return;

  if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {
    QualType T = TDecl->getUnderlyingType();
    if (T->isObjCObjectType())
      if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) {
        ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());
        // FIXME: Consider whether this should be an invalid loc since the loc
        // is not actually pointing to a protocol name reference but to the
        // typedef reference. Note that the base class name loc is also pointing
        // at the typedef.
        ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc);
      }
  }
}

/// ActOnCompatibilityAlias - this action is called after complete parsing of
/// a \@compatibility_alias declaration. It sets up the alias relationships.
Decl *SemaObjC::ActOnCompatibilityAlias(SourceLocation AtLoc,
                                        IdentifierInfo *AliasName,
                                        SourceLocation AliasLocation,
                                        IdentifierInfo *ClassName,
                                        SourceLocation ClassLocation) {
  ASTContext &Context = getASTContext();
  // Look for previous declaration of alias name
  NamedDecl *ADecl = SemaRef.LookupSingleName(
      SemaRef.TUScope, AliasName, AliasLocation, Sema::LookupOrdinaryName,
      SemaRef.forRedeclarationInCurContext());
  if (ADecl) {
    Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;
    Diag(ADecl->getLocation(), diag::note_previous_declaration);
    return nullptr;
  }
  // Check for class declaration
  NamedDecl *CDeclU = SemaRef.LookupSingleName(
      SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,
      SemaRef.forRedeclarationInCurContext());
  if (const TypedefNameDecl *TDecl =
        dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
    QualType T = TDecl->getUnderlyingType();
    if (T->isObjCObjectType()) {
      if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {
        ClassName = IDecl->getIdentifier();
        CDeclU = SemaRef.LookupSingleName(
            SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,
            SemaRef.forRedeclarationInCurContext());
      }
    }
  }
  ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);
  if (!CDecl) {
    Diag(ClassLocation, diag::warn_undef_interface) << ClassName;
    if (CDeclU)
      Diag(CDeclU->getLocation(), diag::note_previous_declaration);
    return nullptr;
  }

  // Everything checked out, instantiate a new alias declaration AST.
  ObjCCompatibleAliasDecl *AliasDecl = ObjCCompatibleAliasDecl::Create(
      Context, SemaRef.CurContext, AtLoc, AliasName, CDecl);

  if (!CheckObjCDeclScope(AliasDecl))
    SemaRef.PushOnScopeChains(AliasDecl, SemaRef.TUScope);

  return AliasDecl;
}

bool SemaObjC::CheckForwardProtocolDeclarationForCircularDependency(
    IdentifierInfo *PName, SourceLocation &Ploc, SourceLocation PrevLoc,
    const ObjCList<ObjCProtocolDecl> &PList) {

  bool res = false;
  for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),
       E = PList.end(); I != E; ++I) {
    if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), Ploc)) {
      if (PDecl->getIdentifier() == PName) {
        Diag(Ploc, diag::err_protocol_has_circular_dependency);
        Diag(PrevLoc, diag::note_previous_definition);
        res = true;
      }

      if (!PDecl->hasDefinition())
        continue;

      if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,
            PDecl->getLocation(), PDecl->getReferencedProtocols()))
        res = true;
    }
  }
  return res;
}

ObjCProtocolDecl *SemaObjC::ActOnStartProtocolInterface(
    SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,
    SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,
    const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
    const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {
  ASTContext &Context = getASTContext();
  bool err = false;
  // FIXME: Deal with AttrList.
  assert(ProtocolName && "Missing protocol identifier");
  ObjCProtocolDecl *PrevDecl = LookupProtocol(
      ProtocolName, ProtocolLoc, SemaRef.forRedeclarationInCurContext());
  ObjCProtocolDecl *PDecl = nullptr;
  if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {
    // Create a new protocol that is completely distinct from previous
    // declarations, and do not make this protocol available for name lookup.
    // That way, we'll end up completely ignoring the duplicate.
    // FIXME: Can we turn this into an error?
    PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,
                                     ProtocolLoc, AtProtoInterfaceLoc,
                                     /*PrevDecl=*/Def);

    if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {
      SkipBody->CheckSameAsPrevious = true;
      SkipBody->New = PDecl;
      SkipBody->Previous = Def;
    } else {
      // If we already have a definition, complain.
      Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;
      Diag(Def->getLocation(), diag::note_previous_definition);
    }

    // If we are using modules, add the decl to the context in order to
    // serialize something meaningful.
    if (getLangOpts().Modules)
      SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);
    PDecl->startDuplicateDefinitionForComparison();
  } else {
    if (PrevDecl) {
      // Check for circular dependencies among protocol declarations. This can
      // only happen if this protocol was forward-declared.
      ObjCList<ObjCProtocolDecl> PList;
      PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);
      err = CheckForwardProtocolDeclarationForCircularDependency(
              ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList);
    }

    // Create the new declaration.
    PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,
                                     ProtocolLoc, AtProtoInterfaceLoc,
                                     /*PrevDecl=*/PrevDecl);

    SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);
    PDecl->startDefinition();
  }

  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, AttrList);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);
  SemaRef.ProcessAPINotes(PDecl);

  // Merge attributes from previous declarations.
  if (PrevDecl)
    SemaRef.mergeDeclAttributes(PDecl, PrevDecl);

  if (!err && NumProtoRefs ) {
    /// Check then save referenced protocols.
    diagnoseUseOfProtocols(SemaRef, PDecl, (ObjCProtocolDecl *const *)ProtoRefs,
                           NumProtoRefs, ProtoLocs);
    PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
                           ProtoLocs, Context);
  }

  CheckObjCDeclScope(PDecl);
  ActOnObjCContainerStartDefinition(PDecl);
  return PDecl;
}

static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,
                                          ObjCProtocolDecl *&UndefinedProtocol) {
  if (!PDecl->hasDefinition() ||
      !PDecl->getDefinition()->isUnconditionallyVisible()) {
    UndefinedProtocol = PDecl;
    return true;
  }

  for (auto *PI : PDecl->protocols())
    if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {
      UndefinedProtocol = PI;
      return true;
    }
  return false;
}

/// FindProtocolDeclaration - This routine looks up protocols and
/// issues an error if they are not declared. It returns list of
/// protocol declarations in its 'Protocols' argument.
void SemaObjC::FindProtocolDeclaration(bool WarnOnDeclarations,
                                       bool ForObjCContainer,
                                       ArrayRef<IdentifierLoc> ProtocolId,
                                       SmallVectorImpl<Decl *> &Protocols) {
  for (const IdentifierLoc &Pair : ProtocolId) {
    ObjCProtocolDecl *PDecl =
        LookupProtocol(Pair.getIdentifierInfo(), Pair.getLoc());
    if (!PDecl) {
      DeclFilterCCC<ObjCProtocolDecl> CCC{};
      TypoCorrection Corrected = SemaRef.CorrectTypo(
          DeclarationNameInfo(Pair.getIdentifierInfo(), Pair.getLoc()),
          Sema::LookupObjCProtocolName, SemaRef.TUScope, nullptr, CCC,
          CorrectTypoKind::ErrorRecovery);
      if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
        SemaRef.diagnoseTypo(Corrected,
                             PDiag(diag::err_undeclared_protocol_suggest)
                                 << Pair.getIdentifierInfo());
    }

    if (!PDecl) {
      Diag(Pair.getLoc(), diag::err_undeclared_protocol)
          << Pair.getIdentifierInfo();
      continue;
    }
    // If this is a forward protocol declaration, get its definition.
    if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())
      PDecl = PDecl->getDefinition();

    // For an objc container, delay protocol reference checking until after we
    // can set the objc decl as the availability context, otherwise check now.
    if (!ForObjCContainer) {
      (void)SemaRef.DiagnoseUseOfDecl(PDecl, Pair.getLoc());
    }

    // If this is a forward declaration and we are supposed to warn in this
    // case, do it.
    // FIXME: Recover nicely in the hidden case.
    ObjCProtocolDecl *UndefinedProtocol;

    if (WarnOnDeclarations &&
        NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {
      Diag(Pair.getLoc(), diag::warn_undef_protocolref)
          << Pair.getIdentifierInfo();
      Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)
        << UndefinedProtocol;
    }
    Protocols.push_back(PDecl);
  }
}

namespace {
// Callback to only accept typo corrections that are either
// Objective-C protocols or valid Objective-C type arguments.
class ObjCTypeArgOrProtocolValidatorCCC final
    : public CorrectionCandidateCallback {
  ASTContext &Context;
  Sema::LookupNameKind LookupKind;
 public:
  ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,
                                    Sema::LookupNameKind lookupKind)
    : Context(context), LookupKind(lookupKind) { }

  bool ValidateCandidate(const TypoCorrection &candidate) override {
    // If we're allowed to find protocols and we have a protocol, accept it.
    if (LookupKind != Sema::LookupOrdinaryName) {
      if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())
        return true;
    }

    // If we're allowed to find type names and we have one, accept it.
    if (LookupKind != Sema::LookupObjCProtocolName) {
      // If we have a type declaration, we might accept this result.
      if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {
        // If we found a tag declaration outside of C++, skip it. This
        // can happy because we look for any name when there is no
        // bias to protocol or type names.
        if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)
          return false;

        // Make sure the type is something we would accept as a type
        // argument.
        if (CanQualType type = Context.getCanonicalTypeDeclType(typeDecl);
            type->isDependentType() ||
            isa<ObjCObjectPointerType, BlockPointerType, ObjCObjectType>(type))
          return true;

        return false;
      }

      // If we have an Objective-C class type, accept it; there will
      // be another fix to add the '*'.
      if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())
        return true;

      return false;
    }

    return false;
  }

  std::unique_ptr<CorrectionCandidateCallback> clone() override {
    return std::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this);
  }
};
} // end anonymous namespace

void SemaObjC::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,
                                            SourceLocation ProtocolLoc,
                                            IdentifierInfo *TypeArgId,
                                            SourceLocation TypeArgLoc,
                                            bool SelectProtocolFirst) {
  Diag(TypeArgLoc, diag::err_objc_type_args_and_protocols)
      << SelectProtocolFirst << TypeArgId << ProtocolId
      << SourceRange(ProtocolLoc);
}

void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers(
    Scope *S, ParsedType baseType, SourceLocation lAngleLoc,
    ArrayRef<IdentifierInfo *> identifiers,
    ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc,
    SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs,
    SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc,
    SmallVectorImpl<Decl *> &protocols, SourceLocation &protocolRAngleLoc,
    bool warnOnIncompleteProtocols) {
  ASTContext &Context = getASTContext();
  // Local function that updates the declaration specifiers with
  // protocol information.
  unsigned numProtocolsResolved = 0;
  auto resolvedAsProtocols = [&] {
    assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");

    // Determine whether the base type is a parameterized class, in
    // which case we want to warn about typos such as
    // "NSArray<NSObject>" (that should be NSArray<NSObject *>).
    ObjCInterfaceDecl *baseClass = nullptr;
    QualType base = SemaRef.GetTypeFromParser(baseType, nullptr);
    bool allAreTypeNames = false;
    SourceLocation firstClassNameLoc;
    if (!base.isNull()) {
      if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) {
        baseClass = objcObjectType->getInterface();
        if (baseClass) {
          if (auto typeParams = baseClass->getTypeParamList()) {
            if (typeParams->size() == numProtocolsResolved) {
              // Note that we should be looking for type names, too.
              allAreTypeNames = true;
            }
          }
        }
      }
    }

    for (unsigned i = 0, n = protocols.size(); i != n; ++i) {
      ObjCProtocolDecl *&proto
        = reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]);
      // For an objc container, delay protocol reference checking until after we
      // can set the objc decl as the availability context, otherwise check now.
      if (!warnOnIncompleteProtocols) {
        (void)SemaRef.DiagnoseUseOfDecl(proto, identifierLocs[i]);
      }

      // If this is a forward protocol declaration, get its definition.
      if (!proto->isThisDeclarationADefinition() && proto->getDefinition())
        proto = proto->getDefinition();

      // If this is a forward declaration and we are supposed to warn in this
      // case, do it.
      // FIXME: Recover nicely in the hidden case.
      ObjCProtocolDecl *forwardDecl = nullptr;
      if (warnOnIncompleteProtocols &&
          NestedProtocolHasNoDefinition(proto, forwardDecl)) {
        Diag(identifierLocs[i], diag::warn_undef_protocolref)
          << proto->getDeclName();
        Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)
          << forwardDecl;
      }

      // If everything this far has been a type name (and we care
      // about such things), check whether this name refers to a type
      // as well.
      if (allAreTypeNames) {
        if (auto *decl =
                SemaRef.LookupSingleName(S, identifiers[i], identifierLocs[i],
                                         Sema::LookupOrdinaryName)) {
          if (isa<ObjCInterfaceDecl>(decl)) {
            if (firstClassNameLoc.isInvalid())
              firstClassNameLoc = identifierLocs[i];
          } else if (!isa<TypeDecl>(decl)) {
            // Not a type.
            allAreTypeNames = false;
          }
        } else {
          allAreTypeNames = false;
        }
      }
    }

    // All of the protocols listed also have type names, and at least
    // one is an Objective-C class name. Check whether all of the
    // protocol conformances are declared by the base class itself, in
    // which case we warn.
    if (allAreTypeNames && firstClassNameLoc.isValid()) {
      llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols;
      Context.CollectInheritedProtocols(baseClass, knownProtocols);
      bool allProtocolsDeclared = true;
      for (auto *proto : protocols) {
        if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) {
          allProtocolsDeclared = false;
          break;
        }
      }

      if (allProtocolsDeclared) {
        Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)
            << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)
            << FixItHint::CreateInsertion(
                   SemaRef.getLocForEndOfToken(firstClassNameLoc), " *");
      }
    }

    protocolLAngleLoc = lAngleLoc;
    protocolRAngleLoc = rAngleLoc;
    assert(protocols.size() == identifierLocs.size());
  };

  // Attempt to resolve all of the identifiers as protocols.
  for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
    ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);
    protocols.push_back(proto);
    if (proto)
      ++numProtocolsResolved;
  }

  // If all of the names were protocols, these were protocol qualifiers.
  if (numProtocolsResolved == identifiers.size())
    return resolvedAsProtocols();

  // Attempt to resolve all of the identifiers as type names or
  // Objective-C class names. The latter is technically ill-formed,
  // but is probably something like \c NSArray<NSView *> missing the
  // \c*.
  typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;
  SmallVector<TypeOrClassDecl, 4> typeDecls;
  unsigned numTypeDeclsResolved = 0;
  for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
    NamedDecl *decl = SemaRef.LookupSingleName(
        S, identifiers[i], identifierLocs[i], Sema::LookupOrdinaryName);
    if (!decl) {
      typeDecls.push_back(TypeOrClassDecl());
      continue;
    }

    if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {
      typeDecls.push_back(typeDecl);
      ++numTypeDeclsResolved;
      continue;
    }

    if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {
      typeDecls.push_back(objcClass);
      ++numTypeDeclsResolved;
      continue;
    }

    typeDecls.push_back(TypeOrClassDecl());
  }

  AttributeFactory attrFactory;

  // Local function that forms a reference to the given type or
  // Objective-C class declaration.
  auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)
                                -> TypeResult {
    // Form declaration specifiers. They simply refer to the type.
    DeclSpec DS(attrFactory);
    const char* prevSpec; // unused
    unsigned diagID; // unused
    QualType type;
    if (auto *actualTypeDecl = dyn_cast<TypeDecl *>(typeDecl))
      type =
          Context.getTypeDeclType(ElaboratedTypeKeyword::None,
                                  /*Qualifier=*/std::nullopt, actualTypeDecl);
    else
      type = Context.getObjCInterfaceType(cast<ObjCInterfaceDecl *>(typeDecl));
    TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);
    ParsedType parsedType = SemaRef.CreateParsedType(type, parsedTSInfo);
    DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,
                       parsedType, Context.getPrintingPolicy());
    // Use the identifier location for the type source range.
    DS.SetRangeStart(loc);
    DS.SetRangeEnd(loc);

    // Form the declarator.
    Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName);

    // If we have a typedef of an Objective-C class type that is missing a '*',
    // add the '*'.
    if (type->getAs<ObjCInterfaceType>()) {
      SourceLocation starLoc = SemaRef.getLocForEndOfToken(loc);
      D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc,
                                                SourceLocation(),
                                                SourceLocation(),
                                                SourceLocation(),
                                                SourceLocation(),
                                                SourceLocation()),
                                                starLoc);

      // Diagnose the missing '*'.
      Diag(loc, diag::err_objc_type_arg_missing_star)
        << type
        << FixItHint::CreateInsertion(starLoc, " *");
    }

    // Convert this to a type.
    return SemaRef.ActOnTypeName(D);
  };

  // Local function that updates the declaration specifiers with
  // type argument information.
  auto resolvedAsTypeDecls = [&] {
    // We did not resolve these as protocols.
    protocols.clear();

    assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl");
    // Map type declarations to type arguments.
    for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
      // Map type reference to a type.
      TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]);
      if (!type.isUsable()) {
        typeArgs.clear();
        return;
      }

      typeArgs.push_back(type.get());
    }

    typeArgsLAngleLoc = lAngleLoc;
    typeArgsRAngleLoc = rAngleLoc;
  };

  // If all of the identifiers can be resolved as type names or
  // Objective-C class names, we have type arguments.
  if (numTypeDeclsResolved == identifiers.size())
    return resolvedAsTypeDecls();

  // Error recovery: some names weren't found, or we have a mix of
  // type and protocol names. Go resolve all of the unresolved names
  // and complain if we can't find a consistent answer.
  Sema::LookupNameKind lookupKind = Sema::LookupAnyName;
  for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {
    // If we already have a protocol or type. Check whether it is the
    // right thing.
    if (protocols[i] || typeDecls[i]) {
      // If we haven't figured out whether we want types or protocols
      // yet, try to figure it out from this name.
      if (lookupKind == Sema::LookupAnyName) {
        // If this name refers to both a protocol and a type (e.g., \c
        // NSObject), don't conclude anything yet.
        if (protocols[i] && typeDecls[i])
          continue;

        // Otherwise, let this name decide whether we'll be correcting
        // toward types or protocols.
        lookupKind = protocols[i] ? Sema::LookupObjCProtocolName
                                  : Sema::LookupOrdinaryName;
        continue;
      }

      // If we want protocols and we have a protocol, there's nothing
      // more to do.
      if (lookupKind == Sema::LookupObjCProtocolName && protocols[i])
        continue;

      // If we want types and we have a type declaration, there's
      // nothing more to do.
      if (lookupKind == Sema::LookupOrdinaryName && typeDecls[i])
        continue;

      // We have a conflict: some names refer to protocols and others
      // refer to types.
      DiagnoseTypeArgsAndProtocols(identifiers[0], identifierLocs[0],
                                   identifiers[i], identifierLocs[i],
                                   protocols[i] != nullptr);

      protocols.clear();
      typeArgs.clear();
      return;
    }

    // Perform typo correction on the name.
    ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind);
    TypoCorrection corrected = SemaRef.CorrectTypo(
        DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,
        nullptr, CCC, CorrectTypoKind::ErrorRecovery);
    if (corrected) {
      // Did we find a protocol?
      if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {
        SemaRef.diagnoseTypo(corrected,
                             PDiag(diag::err_undeclared_protocol_suggest)
                                 << identifiers[i]);
        lookupKind = Sema::LookupObjCProtocolName;
        protocols[i] = proto;
        ++numProtocolsResolved;
        continue;
      }

      // Did we find a type?
      if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {
        SemaRef.diagnoseTypo(corrected,
                             PDiag(diag::err_unknown_typename_suggest)
                                 << identifiers[i]);
        lookupKind = Sema::LookupOrdinaryName;
        typeDecls[i] = typeDecl;
        ++numTypeDeclsResolved;
        continue;
      }

      // Did we find an Objective-C class?
      if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
        SemaRef.diagnoseTypo(corrected,
                             PDiag(diag::err_unknown_type_or_class_name_suggest)
                                 << identifiers[i] << true);
        lookupKind = Sema::LookupOrdinaryName;
        typeDecls[i] = objcClass;
        ++numTypeDeclsResolved;
        continue;
      }
    }

    // We couldn't find anything.
    Diag(identifierLocs[i],
         (lookupKind == Sema::LookupAnyName ? diag::err_objc_type_arg_missing
          : lookupKind == Sema::LookupObjCProtocolName
              ? diag::err_undeclared_protocol
              : diag::err_unknown_typename))
        << identifiers[i];
    protocols.clear();
    typeArgs.clear();
    return;
  }

  // If all of the names were (corrected to) protocols, these were
  // protocol qualifiers.
  if (numProtocolsResolved == identifiers.size())
    return resolvedAsProtocols();

  // Otherwise, all of the names were (corrected to) types.
  assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");
  return resolvedAsTypeDecls();
}

/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of
/// a class method in its extension.
///
void SemaObjC::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,
                                                ObjCInterfaceDecl *ID) {
  if (!ID)
    return;  // Possibly due to previous error

  llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;
  for (auto *MD : ID->methods())
    MethodMap[MD->getSelector()] = MD;

  if (MethodMap.empty())
    return;
  for (const auto *Method : CAT->methods()) {
    const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];
    if (PrevMethod &&
        (PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) &&
        !MatchTwoMethodDeclarations(Method, PrevMethod)) {
      Diag(Method->getLocation(), diag::err_duplicate_method_decl)
            << Method->getDeclName();
      Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
    }
  }
}

/// ActOnForwardProtocolDeclaration - Handle \@protocol foo;
SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardProtocolDeclaration(
    SourceLocation AtProtocolLoc, ArrayRef<IdentifierLoc> IdentList,
    const ParsedAttributesView &attrList) {
  ASTContext &Context = getASTContext();
  SmallVector<Decl *, 8> DeclsInGroup;
  for (const IdentifierLoc &IdentPair : IdentList) {
    IdentifierInfo *Ident = IdentPair.getIdentifierInfo();
    ObjCProtocolDecl *PrevDecl = LookupProtocol(
        Ident, IdentPair.getLoc(), SemaRef.forRedeclarationInCurContext());
    ObjCProtocolDecl *PDecl =
        ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident,
                                 IdentPair.getLoc(), AtProtocolLoc, PrevDecl);

    SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);
    CheckObjCDeclScope(PDecl);

    SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, attrList);
    SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);

    if (PrevDecl)
      SemaRef.mergeDeclAttributes(PDecl, PrevDecl);

    DeclsInGroup.push_back(PDecl);
  }

  return SemaRef.BuildDeclaratorGroup(DeclsInGroup);
}

ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface(
    SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName,
    SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,
    const IdentifierInfo *CategoryName, SourceLocation CategoryLoc,
    Decl *const *ProtoRefs, unsigned NumProtoRefs,
    const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,
    const ParsedAttributesView &AttrList) {
  ASTContext &Context = getASTContext();
  ObjCCategoryDecl *CDecl;
  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);

  /// Check that class of this category is already completely declared.

  if (!IDecl ||
      SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
                                  diag::err_category_forward_interface,
                                  CategoryName == nullptr)) {
    // Create an invalid ObjCCategoryDecl to serve as context for
    // the enclosing method declarations.  We mark the decl invalid
    // to make it clear that this isn't a valid AST.
    CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext,
                                     AtInterfaceLoc, ClassLoc, CategoryLoc,
                                     CategoryName, IDecl, typeParamList);
    CDecl->setInvalidDecl();
    SemaRef.CurContext->addDecl(CDecl);

    if (!IDecl)
      Diag(ClassLoc, diag::err_undef_interface) << ClassName;
    ActOnObjCContainerStartDefinition(CDecl);
    return CDecl;
  }

  if (!CategoryName && IDecl->getImplementation()) {
    Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;
    Diag(IDecl->getImplementation()->getLocation(),
          diag::note_implementation_declared);
  }

  if (CategoryName) {
    /// Check for duplicate interface declaration for this category
    if (ObjCCategoryDecl *Previous
          = IDecl->FindCategoryDeclaration(CategoryName)) {
      // Class extensions can be declared multiple times, categories cannot.
      Diag(CategoryLoc, diag::warn_dup_category_def)
        << ClassName << CategoryName;
      Diag(Previous->getLocation(), diag::note_previous_definition);
    }
  }

  // If we have a type parameter list, check it.
  if (typeParamList) {
    if (auto prevTypeParamList = IDecl->getTypeParamList()) {
      if (checkTypeParamListConsistency(
              SemaRef, prevTypeParamList, typeParamList,
              CategoryName ? TypeParamListContext::Category
                           : TypeParamListContext::Extension))
        typeParamList = nullptr;
    } else {
      Diag(typeParamList->getLAngleLoc(),
           diag::err_objc_parameterized_category_nonclass)
        << (CategoryName != nullptr)
        << ClassName
        << typeParamList->getSourceRange();

      typeParamList = nullptr;
    }
  }

  CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,
                                   ClassLoc, CategoryLoc, CategoryName, IDecl,
                                   typeParamList);
  // FIXME: PushOnScopeChains?
  SemaRef.CurContext->addDecl(CDecl);

  // Process the attributes before looking at protocols to ensure that the
  // availability attribute is attached to the category to provide availability
  // checking for protocol uses.
  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);

  if (NumProtoRefs) {
    diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs,
                           NumProtoRefs, ProtoLocs);
    CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,
                           ProtoLocs, Context);
    // Protocols in the class extension belong to the class.
    if (CDecl->IsClassExtension())
     IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs,
                                            NumProtoRefs, Context);
  }

  CheckObjCDeclScope(CDecl);
  ActOnObjCContainerStartDefinition(CDecl);
  return CDecl;
}

/// ActOnStartCategoryImplementation - Perform semantic checks on the
/// category implementation declaration and build an ObjCCategoryImplDecl
/// object.
ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation(
    SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName,
    SourceLocation ClassLoc, const IdentifierInfo *CatName,
    SourceLocation CatLoc, const ParsedAttributesView &Attrs) {
  ASTContext &Context = getASTContext();
  ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);
  ObjCCategoryDecl *CatIDecl = nullptr;
  if (IDecl && IDecl->hasDefinition()) {
    CatIDecl = IDecl->FindCategoryDeclaration(CatName);
    if (!CatIDecl) {
      // Category @implementation with no corresponding @interface.
      // Create and install one.
      CatIDecl =
          ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtCatImplLoc,
                                   ClassLoc, CatLoc, CatName, IDecl,
                                   /*typeParamList=*/nullptr);
      CatIDecl->setImplicit();
    }
  }

  ObjCCategoryImplDecl *CDecl =
      ObjCCategoryImplDecl::Create(Context, SemaRef.CurContext, CatName, IDecl,
                                   ClassLoc, AtCatImplLoc, CatLoc);
  /// Check that class of this category is already completely declared.
  if (!IDecl) {
    Diag(ClassLoc, diag::err_undef_interface) << ClassName;
    CDecl->setInvalidDecl();
  } else if (SemaRef.RequireCompleteType(ClassLoc,
                                         Context.getObjCInterfaceType(IDecl),
                                         diag::err_undef_interface)) {
    CDecl->setInvalidDecl();
  }

  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);

  // FIXME: PushOnScopeChains?
  SemaRef.CurContext->addDecl(CDecl);

  // If the interface has the objc_runtime_visible attribute, we
  // cannot implement a category for it.
  if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) {
    Diag(ClassLoc, diag::err_objc_runtime_visible_category)
      << IDecl->getDeclName();
  }

  /// Check that CatName, category name, is not used in another implementation.
  if (CatIDecl) {
    if (CatIDecl->getImplementation()) {
      Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName
        << CatName;
      Diag(CatIDecl->getImplementation()->getLocation(),
           diag::note_previous_definition);
      CDecl->setInvalidDecl();
    } else {
      CatIDecl->setImplementation(CDecl);
      // Warn on implementating category of deprecated class under
      // -Wdeprecated-implementations flag.
      DiagnoseObjCImplementedDeprecations(SemaRef, CatIDecl,
                                          CDecl->getLocation());
    }
  }

  CheckObjCDeclScope(CDecl);
  ActOnObjCContainerStartDefinition(CDecl);
  return CDecl;
}

ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation(
    SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName,
    SourceLocation ClassLoc, const IdentifierInfo *SuperClassname,
    SourceLocation SuperClassLoc, const ParsedAttributesView &Attrs) {
  ASTContext &Context = getASTContext();
  ObjCInterfaceDecl *IDecl = nullptr;
  // Check for another declaration kind with the same name.
  NamedDecl *PrevDecl = SemaRef.LookupSingleName(
      SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,
      SemaRef.forRedeclarationInCurContext());
  if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
    Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
    Diag(PrevDecl->getLocation(), diag::note_previous_definition);
  } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {
    // FIXME: This will produce an error if the definition of the interface has
    // been imported from a module but is not visible.
    SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),
                                diag::warn_undef_interface);
  } else {
    // We did not find anything with the name ClassName; try to correct for
    // typos in the class name.
    ObjCInterfaceValidatorCCC CCC{};
    TypoCorrection Corrected = SemaRef.CorrectTypo(
        DeclarationNameInfo(ClassName, ClassLoc), Sema::LookupOrdinaryName,
        SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::NonError);
    if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {
      // Suggest the (potentially) correct interface name. Don't provide a
      // code-modification hint or use the typo name for recovery, because
      // this is just a warning. The program may actually be correct.
      SemaRef.diagnoseTypo(
          Corrected, PDiag(diag::warn_undef_interface_suggest) << ClassName,
          /*ErrorRecovery*/ false);
    } else {
      Diag(ClassLoc, diag::warn_undef_interface) << ClassName;
    }
  }

  // Check that super class name is valid class name
  ObjCInterfaceDecl *SDecl = nullptr;
  if (SuperClassname) {
    // Check if a different kind of symbol declared in this scope.
    PrevDecl =
        SemaRef.LookupSingleName(SemaRef.TUScope, SuperClassname, SuperClassLoc,
                                 Sema::LookupOrdinaryName);
    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
      Diag(SuperClassLoc, diag::err_redefinition_different_kind)
        << SuperClassname;
      Diag(PrevDecl->getLocation(), diag::note_previous_definition);
    } else {
      SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);
      if (SDecl && !SDecl->hasDefinition())
        SDecl = nullptr;
      if (!SDecl)
        Diag(SuperClassLoc, diag::err_undef_superclass)
          << SuperClassname << ClassName;
      else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) {
        // This implementation and its interface do not have the same
        // super class.
        Diag(SuperClassLoc, diag::err_conflicting_super_class)
          << SDecl->getDeclName();
        Diag(SDecl->getLocation(), diag::note_previous_definition);
      }
    }
  }

  if (!IDecl) {
    // Legacy case of @implementation with no corresponding @interface.
    // Build, chain & install the interface decl into the identifier.

    // FIXME: Do we support attributes on the @implementation? If so we should
    // copy them over.
    IDecl =
        ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtClassImplLoc,
                                  ClassName, /*typeParamList=*/nullptr,
                                  /*PrevDecl=*/nullptr, ClassLoc, true);
    SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);
    IDecl->startDefinition();
    if (SDecl) {
      IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(
                             Context.getObjCInterfaceType(SDecl),
                             SuperClassLoc));
      IDecl->setEndOfDefinitionLoc(SuperClassLoc);
    } else {
      IDecl->setEndOfDefinitionLoc(ClassLoc);
    }

    SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);
  } else {
    // Mark the interface as being completed, even if it was just as
    //   @class ....;
    // declaration; the user cannot reopen it.
    if (!IDecl->hasDefinition())
      IDecl->startDefinition();
  }

  ObjCImplementationDecl *IMPDecl =
      ObjCImplementationDecl::Create(Context, SemaRef.CurContext, IDecl, SDecl,
                                     ClassLoc, AtClassImplLoc, SuperClassLoc);

  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl);

  if (CheckObjCDeclScope(IMPDecl)) {
    ActOnObjCContainerStartDefinition(IMPDecl);
    return IMPDecl;
  }

  // Check that there is no duplicate implementation of this class.
  if (IDecl->getImplementation()) {
    // FIXME: Don't leak everything!
    Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;
    Diag(IDecl->getImplementation()->getLocation(),
         diag::note_previous_definition);
    IMPDecl->setInvalidDecl();
  } else { // add it to the list.
    IDecl->setImplementation(IMPDecl);
    SemaRef.PushOnScopeChains(IMPDecl, SemaRef.TUScope);
    // Warn on implementating deprecated class under
    // -Wdeprecated-implementations flag.
    DiagnoseObjCImplementedDeprecations(SemaRef, IDecl, IMPDecl->getLocation());
  }

  // If the superclass has the objc_runtime_visible attribute, we
  // cannot implement a subclass of it.
  if (IDecl->getSuperClass() &&
      IDecl->getSuperClass()->hasAttr<ObjCRuntimeVisibleAttr>()) {
    Diag(ClassLoc, diag::err_objc_runtime_visible_subclass)
      << IDecl->getDeclName()
      << IDecl->getSuperClass()->getDeclName();
  }

  ActOnObjCContainerStartDefinition(IMPDecl);
  return IMPDecl;
}

SemaObjC::DeclGroupPtrTy
SemaObjC::ActOnFinishObjCImplementation(Decl *ObjCImpDecl,
                                        ArrayRef<Decl *> Decls) {
  SmallVector<Decl *, 64> DeclsInGroup;
  DeclsInGroup.reserve(Decls.size() + 1);

  for (unsigned i = 0, e = Decls.size(); i != e; ++i) {
    Decl *Dcl = Decls[i];
    if (!Dcl)
      continue;
    if (Dcl->getDeclContext()->isFileContext())
      Dcl->setTopLevelDeclInObjCContainer();
    DeclsInGroup.push_back(Dcl);
  }

  DeclsInGroup.push_back(ObjCImpDecl);

  // Reset the cached layout if there are any ivars added to
  // the implementation.
  if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))
    if (!ImplD->ivar_empty())
      getASTContext().ResetObjCLayout(ImplD->getClassInterface());

  return SemaRef.BuildDeclaratorGroup(DeclsInGroup);
}

void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,
                                        ObjCIvarDecl **ivars, unsigned numIvars,
                                        SourceLocation RBrace) {
  assert(ImpDecl && "missing implementation decl");
  ASTContext &Context = getASTContext();
  ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();
  if (!IDecl)
    return;
  /// Check case of non-existing \@interface decl.
  /// (legacy objective-c \@implementation decl without an \@interface decl).
  /// Add implementations's ivar to the synthesize class's ivar list.
  if (IDecl->isImplicitInterfaceDecl()) {
    IDecl->setEndOfDefinitionLoc(RBrace);
    // Add ivar's to class's DeclContext.
    for (unsigned i = 0, e = numIvars; i != e; ++i) {
      ivars[i]->setLexicalDeclContext(ImpDecl);
      // In a 'fragile' runtime the ivar was added to the implicit
      // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is
      // only in the ObjCImplementationDecl. In the non-fragile case the ivar
      // therefore also needs to be propagated to the ObjCInterfaceDecl.
      if (!getLangOpts().ObjCRuntime.isFragile())
        IDecl->makeDeclVisibleInContext(ivars[i]);
      ImpDecl->addDecl(ivars[i]);
    }

    return;
  }
  // If implementation has empty ivar list, just return.
  if (numIvars == 0)
    return;

  assert(ivars && "missing @implementation ivars");
  if (getLangOpts().ObjCRuntime.isNonFragile()) {
    if (ImpDecl->getSuperClass())
      Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);
    for (unsigned i = 0; i < numIvars; i++) {
      ObjCIvarDecl* ImplIvar = ivars[i];
      if (const ObjCIvarDecl *ClsIvar =
            IDecl->getIvarDecl(ImplIvar->getIdentifier())) {
        Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
        Diag(ClsIvar->getLocation(), diag::note_previous_definition);
        continue;
      }
      // Check class extensions (unnamed categories) for duplicate ivars.
      for (const auto *CDecl : IDecl->visible_extensions()) {
        if (const ObjCIvarDecl *ClsExtIvar =
            CDecl->getIvarDecl(ImplIvar->getIdentifier())) {
          Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);
          Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);
          continue;
        }
      }
      // Instance ivar to Implementation's DeclContext.
      ImplIvar->setLexicalDeclContext(ImpDecl);
      IDecl->makeDeclVisibleInContext(ImplIvar);
      ImpDecl->addDecl(ImplIvar);
    }
    return;
  }
  // Check interface's Ivar list against those in the implementation.
  // names and types must match.
  //
  unsigned j = 0;
  ObjCInterfaceDecl::ivar_iterator
    IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();
  for (; numIvars > 0 && IVI != IVE; ++IVI) {
    ObjCIvarDecl* ImplIvar = ivars[j++];
    ObjCIvarDecl* ClsIvar = *IVI;
    assert (ImplIvar && "missing implementation ivar");
    assert (ClsIvar && "missing class ivar");

    // First, make sure the types match.
    if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) {
      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)
        << ImplIvar->getIdentifier()
        << ImplIvar->getType() << ClsIvar->getType();
      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
    } else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&
               ImplIvar->getBitWidthValue() != ClsIvar->getBitWidthValue()) {
      Diag(ImplIvar->getBitWidth()->getBeginLoc(),
           diag::err_conflicting_ivar_bitwidth)
          << ImplIvar->getIdentifier();
      Diag(ClsIvar->getBitWidth()->getBeginLoc(),
           diag::note_previous_definition);
    }
    // Make sure the names are identical.
    if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {
      Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)
        << ImplIvar->getIdentifier() << ClsIvar->getIdentifier();
      Diag(ClsIvar->getLocation(), diag::note_previous_definition);
    }
    --numIvars;
  }

  if (numIvars > 0)
    Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count);
  else if (IVI != IVE)
    Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);
}

static bool shouldWarnUndefinedMethod(const ObjCMethodDecl *M) {
  // No point warning no definition of method which is 'unavailable'.
  return M->getAvailability() != AR_Unavailable;
}

static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl,
                                ObjCMethodDecl *method, bool &IncompleteImpl,
                                unsigned DiagID,
                                NamedDecl *NeededFor = nullptr) {
  if (!shouldWarnUndefinedMethod(method))
    return;

  // FIXME: For now ignore 'IncompleteImpl'.
  // Previously we grouped all unimplemented methods under a single
  // warning, but some users strongly voiced that they would prefer
  // separate warnings.  We will give that approach a try, as that
  // matches what we do with protocols.
  {
    const SemaBase::SemaDiagnosticBuilder &B =
        S.Diag(Impl->getLocation(), DiagID);
    B << method;
    if (NeededFor)
      B << NeededFor;

    // Add an empty definition at the end of the @implementation.
    std::string FixItStr;
    llvm::raw_string_ostream Out(FixItStr);
    method->print(Out, Impl->getASTContext().getPrintingPolicy());
    Out << " {\n}\n\n";

    SourceLocation Loc = Impl->getAtEndRange().getBegin();
    B << FixItHint::CreateInsertion(Loc, FixItStr);
  }

  // Issue a note to the original declaration.
  SourceLocation MethodLoc = method->getBeginLoc();
  if (MethodLoc.isValid())
    S.Diag(MethodLoc, diag::note_method_declared_at) << method;
}

/// Determines if type B can be substituted for type A.  Returns true if we can
/// guarantee that anything that the user will do to an object of type A can
/// also be done to an object of type B.  This is trivially true if the two
/// types are the same, or if B is a subclass of A.  It becomes more complex
/// in cases where protocols are involved.
///
/// Object types in Objective-C describe the minimum requirements for an
/// object, rather than providing a complete description of a type.  For
/// example, if A is a subclass of B, then B* may refer to an instance of A.
/// The principle of substitutability means that we may use an instance of A
/// anywhere that we may use an instance of B - it will implement all of the
/// ivars of B and all of the methods of B.
///
/// This substitutability is important when type checking methods, because
/// the implementation may have stricter type definitions than the interface.
/// The interface specifies minimum requirements, but the implementation may
/// have more accurate ones.  For example, a method may privately accept
/// instances of B, but only publish that it accepts instances of A.  Any
/// object passed to it will be type checked against B, and so will implicitly
/// by a valid A*.  Similarly, a method may return a subclass of the class that
/// it is declared as returning.
///
/// This is most important when considering subclassing.  A method in a
/// subclass must accept any object as an argument that its superclass's
/// implementation accepts.  It may, however, accept a more general type
/// without breaking substitutability (i.e. you can still use the subclass
/// anywhere that you can use the superclass, but not vice versa).  The
/// converse requirement applies to return types: the return type for a
/// subclass method must be a valid object of the kind that the superclass
/// advertises, but it may be specified more accurately.  This avoids the need
/// for explicit down-casting by callers.
///
/// Note: This is a stricter requirement than for assignment.
static bool isObjCTypeSubstitutable(ASTContext &Context,
                                    const ObjCObjectPointerType *A,
                                    const ObjCObjectPointerType *B,
                                    bool rejectId) {
  // Reject a protocol-unqualified id.
  if (rejectId && B->isObjCIdType()) return false;

  // If B is a qualified id, then A must also be a qualified id and it must
  // implement all of the protocols in B.  It may not be a qualified class.
  // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a
  // stricter definition so it is not substitutable for id<A>.
  if (B->isObjCQualifiedIdType()) {
    return A->isObjCQualifiedIdType() &&
           Context.ObjCQualifiedIdTypesAreCompatible(A, B, false);
  }

  /*
  // id is a special type that bypasses type checking completely.  We want a
  // warning when it is used in one place but not another.
  if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false;


  // If B is a qualified id, then A must also be a qualified id (which it isn't
  // if we've got this far)
  if (B->isObjCQualifiedIdType()) return false;
  */

  // Now we know that A and B are (potentially-qualified) class types.  The
  // normal rules for assignment apply.
  return Context.canAssignObjCInterfaces(A, B);
}

static SourceRange getTypeRange(TypeSourceInfo *TSI) {
  return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());
}

/// Determine whether two set of Objective-C declaration qualifiers conflict.
static bool objcModifiersConflict(Decl::ObjCDeclQualifier x,
                                  Decl::ObjCDeclQualifier y) {
  return (x & ~Decl::OBJC_TQ_CSNullability) !=
         (y & ~Decl::OBJC_TQ_CSNullability);
}

static bool CheckMethodOverrideReturn(Sema &S,
                                      ObjCMethodDecl *MethodImpl,
                                      ObjCMethodDecl *MethodDecl,
                                      bool IsProtocolMethodDecl,
                                      bool IsOverridingMode,
                                      bool Warn) {
  if (IsProtocolMethodDecl &&
      objcModifiersConflict(MethodDecl->getObjCDeclQualifier(),
                            MethodImpl->getObjCDeclQualifier())) {
    if (Warn) {
      S.Diag(MethodImpl->getLocation(),
             (IsOverridingMode
                  ? diag::warn_conflicting_overriding_ret_type_modifiers
                  : diag::warn_conflicting_ret_type_modifiers))
          << MethodImpl->getDeclName()
          << MethodImpl->getReturnTypeSourceRange();
      S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)
          << MethodDecl->getReturnTypeSourceRange();
    }
    else
      return false;
  }
  if (Warn && IsOverridingMode &&
      !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
      !S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),
                                                 MethodDecl->getReturnType(),
                                                 false)) {
    auto nullabilityMethodImpl = *MethodImpl->getReturnType()->getNullability();
    auto nullabilityMethodDecl = *MethodDecl->getReturnType()->getNullability();
    S.Diag(MethodImpl->getLocation(),
           diag::warn_conflicting_nullability_attr_overriding_ret_types)
        << DiagNullabilityKind(nullabilityMethodImpl,
                               ((MethodImpl->getObjCDeclQualifier() &
                                 Decl::OBJC_TQ_CSNullability) != 0))
        << DiagNullabilityKind(nullabilityMethodDecl,
                               ((MethodDecl->getObjCDeclQualifier() &
                                 Decl::OBJC_TQ_CSNullability) != 0));
    S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
  }

  if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),
                                       MethodDecl->getReturnType()))
    return true;
  if (!Warn)
    return false;

  unsigned DiagID =
    IsOverridingMode ? diag::warn_conflicting_overriding_ret_types
                     : diag::warn_conflicting_ret_types;

  // Mismatches between ObjC pointers go into a different warning
  // category, and sometimes they're even completely explicitly allowed.
  if (const ObjCObjectPointerType *ImplPtrTy =
          MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) {
    if (const ObjCObjectPointerType *IfacePtrTy =
            MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) {
      // Allow non-matching return types as long as they don't violate
      // the principle of substitutability.  Specifically, we permit
      // return types that are subclasses of the declared return type,
      // or that are more-qualified versions of the declared type.
      if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))
        return false;

      DiagID =
        IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types
                         : diag::warn_non_covariant_ret_types;
    }
  }

  S.Diag(MethodImpl->getLocation(), DiagID)
      << MethodImpl->getDeclName() << MethodDecl->getReturnType()
      << MethodImpl->getReturnType()
      << MethodImpl->getReturnTypeSourceRange();
  S.Diag(MethodDecl->getLocation(), IsOverridingMode
                                        ? diag::note_previous_declaration
                                        : diag::note_previous_definition)
      << MethodDecl->getReturnTypeSourceRange();
  return false;
}

static bool CheckMethodOverrideParam(Sema &S,
                                     ObjCMethodDecl *MethodImpl,
                                     ObjCMethodDecl *MethodDecl,
                                     ParmVarDecl *ImplVar,
                                     ParmVarDecl *IfaceVar,
                                     bool IsProtocolMethodDecl,
                                     bool IsOverridingMode,
                                     bool Warn) {
  if (IsProtocolMethodDecl &&
      objcModifiersConflict(ImplVar->getObjCDeclQualifier(),
                            IfaceVar->getObjCDeclQualifier())) {
    if (Warn) {
      if (IsOverridingMode)
        S.Diag(ImplVar->getLocation(),
               diag::warn_conflicting_overriding_param_modifiers)
            << getTypeRange(ImplVar->getTypeSourceInfo())
            << MethodImpl->getDeclName();
      else S.Diag(ImplVar->getLocation(),
             diag::warn_conflicting_param_modifiers)
          << getTypeRange(ImplVar->getTypeSourceInfo())
          << MethodImpl->getDeclName();
      S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)
          << getTypeRange(IfaceVar->getTypeSourceInfo());
    }
    else
      return false;
  }

  QualType ImplTy = ImplVar->getType();
  QualType IfaceTy = IfaceVar->getType();
  if (Warn && IsOverridingMode &&
      !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&
      !S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {
    S.Diag(ImplVar->getLocation(),
           diag::warn_conflicting_nullability_attr_overriding_param_types)
        << DiagNullabilityKind(*ImplTy->getNullability(),
                               ((ImplVar->getObjCDeclQualifier() &
                                 Decl::OBJC_TQ_CSNullability) != 0))
        << DiagNullabilityKind(*IfaceTy->getNullability(),
                               ((IfaceVar->getObjCDeclQualifier() &
                                 Decl::OBJC_TQ_CSNullability) != 0));
    S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);
  }
  if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))
    return true;

  if (!Warn)
    return false;
  unsigned DiagID =
    IsOverridingMode ? diag::warn_conflicting_overriding_param_types
                     : diag::warn_conflicting_param_types;

  // Mismatches between ObjC pointers go into a different warning
  // category, and sometimes they're even completely explicitly allowed..
  if (const ObjCObjectPointerType *ImplPtrTy =
        ImplTy->getAs<ObjCObjectPointerType>()) {
    if (const ObjCObjectPointerType *IfacePtrTy =
          IfaceTy->getAs<ObjCObjectPointerType>()) {
      // Allow non-matching argument types as long as they don't
      // violate the principle of substitutability.  Specifically, the
      // implementation must accept any objects that the superclass
      // accepts, however it may also accept others.
      if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))
        return false;

      DiagID =
      IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types
                       : diag::warn_non_contravariant_param_types;
    }
  }

  S.Diag(ImplVar->getLocation(), DiagID)
    << getTypeRange(ImplVar->getTypeSourceInfo())
    << MethodImpl->getDeclName() << IfaceTy << ImplTy;
  S.Diag(IfaceVar->getLocation(),
         (IsOverridingMode ? diag::note_previous_declaration
                           : diag::note_previous_definition))
    << getTypeRange(IfaceVar->getTypeSourceInfo());
  return false;
}

/// In ARC, check whether the conventional meanings of the two methods
/// match.  If they don't, it's a hard error.
static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,
                                      ObjCMethodDecl *decl) {
  ObjCMethodFamily implFamily = impl->getMethodFamily();
  ObjCMethodFamily declFamily = decl->getMethodFamily();
  if (implFamily == declFamily) return false;

  // Since conventions are sorted by selector, the only possibility is
  // that the types differ enough to cause one selector or the other
  // to fall out of the family.
  assert(implFamily == OMF_None || declFamily == OMF_None);

  // No further diagnostics required on invalid declarations.
  if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true;

  const ObjCMethodDecl *unmatched = impl;
  ObjCMethodFamily family = declFamily;
  unsigned errorID = diag::err_arc_lost_method_convention;
  unsigned noteID = diag::note_arc_lost_method_convention;
  if (declFamily == OMF_None) {
    unmatched = decl;
    family = implFamily;
    errorID = diag::err_arc_gained_method_convention;
    noteID = diag::note_arc_gained_method_convention;
  }

  // Indexes into a %select clause in the diagnostic.
  enum FamilySelector {
    F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new
  };
  FamilySelector familySelector = FamilySelector();

  switch (family) {
  case OMF_None: llvm_unreachable("logic error, no method convention");
  case OMF_retain:
  case OMF_release:
  case OMF_autorelease:
  case OMF_dealloc:
  case OMF_finalize:
  case OMF_retainCount:
  case OMF_self:
  case OMF_initialize:
  case OMF_performSelector:
    // Mismatches for these methods don't change ownership
    // conventions, so we don't care.
    return false;

  case OMF_init: familySelector = F_init; break;
  case OMF_alloc: familySelector = F_alloc; break;
  case OMF_copy: familySelector = F_copy; break;
  case OMF_mutableCopy: familySelector = F_mutableCopy; break;
  case OMF_new: familySelector = F_new; break;
  }

  enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn };
  ReasonSelector reasonSelector;

  // The only reason these methods don't fall within their families is
  // due to unusual result types.
  if (unmatched->getReturnType()->isObjCObjectPointerType()) {
    reasonSelector = R_UnrelatedReturn;
  } else {
    reasonSelector = R_NonObjectReturn;
  }

  S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector);
  S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector);

  return true;
}

void SemaObjC::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,
                                           ObjCMethodDecl *MethodDecl,
                                           bool IsProtocolMethodDecl) {
  if (getLangOpts().ObjCAutoRefCount &&
      checkMethodFamilyMismatch(SemaRef, ImpMethodDecl, MethodDecl))
    return;

  CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,
                            IsProtocolMethodDecl, false, true);

  for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
       IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),
       EF = MethodDecl->param_end();
       IM != EM && IF != EF; ++IM, ++IF) {
    CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, *IF,
                             IsProtocolMethodDecl, false, true);
  }

  if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {
    Diag(ImpMethodDecl->getLocation(),
         diag::warn_conflicting_variadic);
    Diag(MethodDecl->getLocation(), diag::note_previous_declaration);
  }
}

void SemaObjC::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,
                                                ObjCMethodDecl *Overridden,
                                                bool IsProtocolMethodDecl) {

  CheckMethodOverrideReturn(SemaRef, Method, Overridden, IsProtocolMethodDecl,
                            true, true);

  for (ObjCMethodDecl::param_iterator IM = Method->param_begin(),
       IF = Overridden->param_begin(), EM = Method->param_end(),
       EF = Overridden->param_end();
       IM != EM && IF != EF; ++IM, ++IF) {
    CheckMethodOverrideParam(SemaRef, Method, Overridden, *IM, *IF,
                             IsProtocolMethodDecl, true, true);
  }

  if (Method->isVariadic() != Overridden->isVariadic()) {
    Diag(Method->getLocation(),
         diag::warn_conflicting_overriding_variadic);
    Diag(Overridden->getLocation(), diag::note_previous_declaration);
  }
}

/// WarnExactTypedMethods - This routine issues a warning if method
/// implementation declaration matches exactly that of its declaration.
void SemaObjC::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,
                                     ObjCMethodDecl *MethodDecl,
                                     bool IsProtocolMethodDecl) {
  ASTContext &Context = getASTContext();
  // don't issue warning when protocol method is optional because primary
  // class is not required to implement it and it is safe for protocol
  // to implement it.
  if (MethodDecl->getImplementationControl() ==
      ObjCImplementationControl::Optional)
    return;
  // don't issue warning when primary class's method is
  // deprecated/unavailable.
  if (MethodDecl->hasAttr<UnavailableAttr>() ||
      MethodDecl->hasAttr<DeprecatedAttr>())
    return;

  bool match = CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,
                                         IsProtocolMethodDecl, false, false);
  if (match)
    for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),
         IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),
         EF = MethodDecl->param_end();
         IM != EM && IF != EF; ++IM, ++IF) {
      match = CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM,
                                       *IF, IsProtocolMethodDecl, false, false);
      if (!match)
        break;
    }
  if (match)
    match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic());
  if (match)
    match = !(MethodDecl->isClassMethod() &&
              MethodDecl->getSelector() == GetNullarySelector("load", Context));

  if (match) {
    Diag(ImpMethodDecl->getLocation(),
         diag::warn_category_method_impl_match);
    Diag(MethodDecl->getLocation(), diag::note_method_declared_at)
      << MethodDecl->getDeclName();
  }
}

/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely
/// improve the efficiency of selector lookups and type checking by associating
/// with each protocol / interface / category the flattened instance tables. If
/// we used an immutable set to keep the table then it wouldn't add significant
/// memory cost and it would be handy for lookups.

typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet;
typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet;

static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl,
                                           ProtocolNameSet &PNS) {
  if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
    PNS.insert(PDecl->getIdentifier());
  for (const auto *PI : PDecl->protocols())
    findProtocolsWithExplicitImpls(PI, PNS);
}

/// Recursively populates a set with all conformed protocols in a class
/// hierarchy that have the 'objc_protocol_requires_explicit_implementation'
/// attribute.
static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super,
                                           ProtocolNameSet &PNS) {
  if (!Super)
    return;

  for (const auto *I : Super->all_referenced_protocols())
    findProtocolsWithExplicitImpls(I, PNS);

  findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS);
}

/// CheckProtocolMethodDefs - This routine checks unimplemented methods
/// Declared in protocol, and those referenced by it.
static void CheckProtocolMethodDefs(
    Sema &S, ObjCImplDecl *Impl, ObjCProtocolDecl *PDecl, bool &IncompleteImpl,
    const SemaObjC::SelectorSet &InsMap, const SemaObjC::SelectorSet &ClsMap,
    ObjCContainerDecl *CDecl, LazyProtocolNameSet &ProtocolsExplictImpl) {
  ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);
  ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()
                               : dyn_cast<ObjCInterfaceDecl>(CDecl);
  assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");

  ObjCInterfaceDecl *Super = IDecl->getSuperClass();
  ObjCInterfaceDecl *NSIDecl = nullptr;

  // If this protocol is marked 'objc_protocol_requires_explicit_implementation'
  // then we should check if any class in the super class hierarchy also
  // conforms to this protocol, either directly or via protocol inheritance.
  // If so, we can skip checking this protocol completely because we
  // know that a parent class already satisfies this protocol.
  //
  // Note: we could generalize this logic for all protocols, and merely
  // add the limit on looking at the super class chain for just
  // specially marked protocols.  This may be a good optimization.  This
  // change is restricted to 'objc_protocol_requires_explicit_implementation'
  // protocols for now for controlled evaluation.
  if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) {
    if (!ProtocolsExplictImpl) {
      ProtocolsExplictImpl.reset(new ProtocolNameSet);
      findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl);
    }
    if (ProtocolsExplictImpl->contains(PDecl->getIdentifier()))
      return;

    // If no super class conforms to the protocol, we should not search
    // for methods in the super class to implicitly satisfy the protocol.
    Super = nullptr;
  }

  if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {
    // check to see if class implements forwardInvocation method and objects
    // of this class are derived from 'NSProxy' so that to forward requests
    // from one object to another.
    // Under such conditions, which means that every method possible is
    // implemented in the class, we should not issue "Method definition not
    // found" warnings.
    // FIXME: Use a general GetUnarySelector method for this.
    const IdentifierInfo *II = &S.Context.Idents.get("forwardInvocation");
    Selector fISelector = S.Context.Selectors.getSelector(1, &II);
    if (InsMap.count(fISelector))
      // Is IDecl derived from 'NSProxy'? If so, no instance methods
      // need be implemented in the implementation.
      NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy"));
  }

  // If this is a forward protocol declaration, get its definition.
  if (!PDecl->isThisDeclarationADefinition() &&
      PDecl->getDefinition())
    PDecl = PDecl->getDefinition();

  // If a method lookup fails locally we still need to look and see if
  // the method was implemented by a base class or an inherited
  // protocol. This lookup is slow, but occurs rarely in correct code
  // and otherwise would terminate in a warning.

  // check unimplemented instance methods.
  if (!NSIDecl)
    for (auto *method : PDecl->instance_methods()) {
      if (method->getImplementationControl() !=
              ObjCImplementationControl::Optional &&
          !method->isPropertyAccessor() &&
          !InsMap.count(method->getSelector()) &&
          (!Super || !Super->lookupMethod(
                         method->getSelector(), true /* instance */,
                         false /* shallowCategory */, true /* followsSuper */,
                         nullptr /* category */))) {
        // If a method is not implemented in the category implementation but
        // has been declared in its primary class, superclass,
        // or in one of their protocols, no need to issue the warning.
        // This is because method will be implemented in the primary class
        // or one of its super class implementation.

        // Ugly, but necessary. Method declared in protocol might have
        // have been synthesized due to a property declared in the class which
        // uses the protocol.
        if (ObjCMethodDecl *MethodInClass = IDecl->lookupMethod(
                method->getSelector(), true /* instance */,
                true /* shallowCategoryLookup */, false /* followSuper */))
          if (C || MethodInClass->isPropertyAccessor())
            continue;
        unsigned DIAG = diag::warn_unimplemented_protocol_method;
        if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {
          WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);
        }
      }
    }
  // check unimplemented class methods
  for (auto *method : PDecl->class_methods()) {
    if (method->getImplementationControl() !=
            ObjCImplementationControl::Optional &&
        !ClsMap.count(method->getSelector()) &&
        (!Super || !Super->lookupMethod(
                       method->getSelector(), false /* class method */,
                       false /* shallowCategoryLookup */,
                       true /* followSuper */, nullptr /* category */))) {
      // See above comment for instance method lookups.
      if (C && IDecl->lookupMethod(method->getSelector(),
                                   false /* class */,
                                   true /* shallowCategoryLookup */,
                                   false /* followSuper */))
        continue;

      unsigned DIAG = diag::warn_unimplemented_protocol_method;
      if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {
        WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);
      }
    }
  }
  // Check on this protocols's referenced protocols, recursively.
  for (auto *PI : PDecl->protocols())
    CheckProtocolMethodDefs(S, Impl, PI, IncompleteImpl, InsMap, ClsMap, CDecl,
                            ProtocolsExplictImpl);
}

/// MatchAllMethodDeclarations - Check methods declared in interface
/// or protocol against those declared in their implementations.
///
void SemaObjC::MatchAllMethodDeclarations(
    const SelectorSet &InsMap, const SelectorSet &ClsMap,
    SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl,
    ObjCContainerDecl *CDecl, bool &IncompleteImpl, bool ImmediateClass,
    bool WarnCategoryMethodImpl) {
  // Check and see if instance methods in class interface have been
  // implemented in the implementation class. If so, their types match.
  for (auto *I : CDecl->instance_methods()) {
    if (!InsMapSeen.insert(I->getSelector()).second)
      continue;
    if (!I->isPropertyAccessor() &&
        !InsMap.count(I->getSelector())) {
      if (ImmediateClass)
        WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,
                            diag::warn_undef_method_impl);
      continue;
    } else {
      ObjCMethodDecl *ImpMethodDecl =
        IMPDecl->getInstanceMethod(I->getSelector());
      assert(CDecl->getInstanceMethod(I->getSelector(), true/*AllowHidden*/) &&
             "Expected to find the method through lookup as well");
      // ImpMethodDecl may be null as in a @dynamic property.
      if (ImpMethodDecl) {
        // Skip property accessor function stubs.
        if (ImpMethodDecl->isSynthesizedAccessorStub())
          continue;
        if (!WarnCategoryMethodImpl)
          WarnConflictingTypedMethods(ImpMethodDecl, I,
                                      isa<ObjCProtocolDecl>(CDecl));
        else if (!I->isPropertyAccessor())
          WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));
      }
    }
  }

  // Check and see if class methods in class interface have been
  // implemented in the implementation class. If so, their types match.
  for (auto *I : CDecl->class_methods()) {
    if (!ClsMapSeen.insert(I->getSelector()).second)
      continue;
    if (!I->isPropertyAccessor() &&
        !ClsMap.count(I->getSelector())) {
      if (ImmediateClass)
        WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,
                            diag::warn_undef_method_impl);
    } else {
      ObjCMethodDecl *ImpMethodDecl =
        IMPDecl->getClassMethod(I->getSelector());
      assert(CDecl->getClassMethod(I->getSelector(), true/*AllowHidden*/) &&
             "Expected to find the method through lookup as well");
      // ImpMethodDecl may be null as in a @dynamic property.
      if (ImpMethodDecl) {
        // Skip property accessor function stubs.
        if (ImpMethodDecl->isSynthesizedAccessorStub())
          continue;
        if (!WarnCategoryMethodImpl)
          WarnConflictingTypedMethods(ImpMethodDecl, I,
                                      isa<ObjCProtocolDecl>(CDecl));
        else if (!I->isPropertyAccessor())
          WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));
      }
    }
  }

  if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {
    // Also, check for methods declared in protocols inherited by
    // this protocol.
    for (auto *PI : PD->protocols())
      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                 IMPDecl, PI, IncompleteImpl, false,
                                 WarnCategoryMethodImpl);
  }

  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
    // when checking that methods in implementation match their declaration,
    // i.e. when WarnCategoryMethodImpl is false, check declarations in class
    // extension; as well as those in categories.
    if (!WarnCategoryMethodImpl) {
      for (auto *Cat : I->visible_categories())
        MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                   IMPDecl, Cat, IncompleteImpl,
                                   ImmediateClass && Cat->IsClassExtension(),
                                   WarnCategoryMethodImpl);
    } else {
      // Also methods in class extensions need be looked at next.
      for (auto *Ext : I->visible_extensions())
        MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                   IMPDecl, Ext, IncompleteImpl, false,
                                   WarnCategoryMethodImpl);
    }

    // Check for any implementation of a methods declared in protocol.
    for (auto *PI : I->all_referenced_protocols())
      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                 IMPDecl, PI, IncompleteImpl, false,
                                 WarnCategoryMethodImpl);

    // FIXME. For now, we are not checking for exact match of methods
    // in category implementation and its primary class's super class.
    if (!WarnCategoryMethodImpl && I->getSuperClass())
      MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                 IMPDecl,
                                 I->getSuperClass(), IncompleteImpl, false);
  }
}

/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in
/// category matches with those implemented in its primary class and
/// warns each time an exact match is found.
void SemaObjC::CheckCategoryVsClassMethodMatches(
    ObjCCategoryImplDecl *CatIMPDecl) {
  // Get category's primary class.
  ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();
  if (!CatDecl)
    return;
  ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();
  if (!IDecl)
    return;
  ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();
  SelectorSet InsMap, ClsMap;

  for (const auto *I : CatIMPDecl->instance_methods()) {
    Selector Sel = I->getSelector();
    // When checking for methods implemented in the category, skip over
    // those declared in category class's super class. This is because
    // the super class must implement the method.
    if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))
      continue;
    InsMap.insert(Sel);
  }

  for (const auto *I : CatIMPDecl->class_methods()) {
    Selector Sel = I->getSelector();
    if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))
      continue;
    ClsMap.insert(Sel);
  }
  if (InsMap.empty() && ClsMap.empty())
    return;

  SelectorSet InsMapSeen, ClsMapSeen;
  bool IncompleteImpl = false;
  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                             CatIMPDecl, IDecl,
                             IncompleteImpl, false,
                             true /*WarnCategoryMethodImpl*/);
}

void SemaObjC::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl,
                                         ObjCContainerDecl *CDecl,
                                         bool IncompleteImpl) {
  SelectorSet InsMap;
  // Check and see if instance methods in class interface have been
  // implemented in the implementation class.
  for (const auto *I : IMPDecl->instance_methods())
    InsMap.insert(I->getSelector());

  // Add the selectors for getters/setters of @dynamic properties.
  for (const auto *PImpl : IMPDecl->property_impls()) {
    // We only care about @dynamic implementations.
    if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)
      continue;

    const auto *P = PImpl->getPropertyDecl();
    if (!P) continue;

    InsMap.insert(P->getGetterName());
    if (!P->getSetterName().isNull())
      InsMap.insert(P->getSetterName());
  }

  // Check and see if properties declared in the interface have either 1)
  // an implementation or 2) there is a @synthesize/@dynamic implementation
  // of the property in the @implementation.
  if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
    bool SynthesizeProperties = getLangOpts().ObjCDefaultSynthProperties &&
                                getLangOpts().ObjCRuntime.isNonFragile() &&
                                !IDecl->isObjCRequiresPropertyDefs();
    DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);
  }

  // Diagnose null-resettable synthesized setters.
  diagnoseNullResettableSynthesizedSetters(IMPDecl);

  SelectorSet ClsMap;
  for (const auto *I : IMPDecl->class_methods())
    ClsMap.insert(I->getSelector());

  // Check for type conflict of methods declared in a class/protocol and
  // its implementation; if any.
  SelectorSet InsMapSeen, ClsMapSeen;
  MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                             IMPDecl, CDecl,
                             IncompleteImpl, true);

  // check all methods implemented in category against those declared
  // in its primary class.
  if (ObjCCategoryImplDecl *CatDecl =
        dyn_cast<ObjCCategoryImplDecl>(IMPDecl))
    CheckCategoryVsClassMethodMatches(CatDecl);

  // Check the protocol list for unimplemented methods in the @implementation
  // class.
  // Check and see if class methods in class interface have been
  // implemented in the implementation class.

  LazyProtocolNameSet ExplicitImplProtocols;

  if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
    for (auto *PI : I->all_referenced_protocols())
      CheckProtocolMethodDefs(SemaRef, IMPDecl, PI, IncompleteImpl, InsMap,
                              ClsMap, I, ExplicitImplProtocols);
  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {
    // For extended class, unimplemented methods in its protocols will
    // be reported in the primary class.
    if (!C->IsClassExtension()) {
      for (auto *P : C->protocols())
        CheckProtocolMethodDefs(SemaRef, IMPDecl, P, IncompleteImpl, InsMap,
                                ClsMap, CDecl, ExplicitImplProtocols);
      DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,
                                      /*SynthesizeProperties=*/false);
    }
  } else
    llvm_unreachable("invalid ObjCContainerDecl type.");
}

SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardClassDeclaration(
    SourceLocation AtClassLoc, IdentifierInfo **IdentList,
    SourceLocation *IdentLocs, ArrayRef<ObjCTypeParamList *> TypeParamLists,
    unsigned NumElts) {
  ASTContext &Context = getASTContext();
  SmallVector<Decl *, 8> DeclsInGroup;
  for (unsigned i = 0; i != NumElts; ++i) {
    // Check for another declaration kind with the same name.
    NamedDecl *PrevDecl = SemaRef.LookupSingleName(
        SemaRef.TUScope, IdentList[i], IdentLocs[i], Sema::LookupOrdinaryName,
        SemaRef.forRedeclarationInCurContext());
    if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
      // GCC apparently allows the following idiom:
      //
      // typedef NSObject < XCElementTogglerP > XCElementToggler;
      // @class XCElementToggler;
      //
      // Here we have chosen to ignore the forward class declaration
      // with a warning. Since this is the implied behavior.
      TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);
      if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
        Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
        Diag(PrevDecl->getLocation(), diag::note_previous_definition);
      } else {
        // a forward class declaration matching a typedef name of a class refers
        // to the underlying class. Just ignore the forward class with a warning
        // as this will force the intended behavior which is to lookup the
        // typedef name.
        if (isa<ObjCObjectType>(TDD->getUnderlyingType())) {
          Diag(AtClassLoc, diag::warn_forward_class_redefinition)
              << IdentList[i];
          Diag(PrevDecl->getLocation(), diag::note_previous_definition);
          continue;
        }
      }
    }

    // Create a declaration to describe this forward declaration.
    ObjCInterfaceDecl *PrevIDecl
      = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);

    IdentifierInfo *ClassName = IdentList[i];
    if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {
      // A previous decl with a different name is because of
      // @compatibility_alias, for example:
      // \code
      //   @class NewImage;
      //   @compatibility_alias OldImage NewImage;
      // \endcode
      // A lookup for 'OldImage' will return the 'NewImage' decl.
      //
      // In such a case use the real declaration name, instead of the alias one,
      // otherwise we will break IdentifierResolver and redecls-chain invariants.
      // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl
      // has been aliased.
      ClassName = PrevIDecl->getIdentifier();
    }

    // If this forward declaration has type parameters, compare them with the
    // type parameters of the previous declaration.
    ObjCTypeParamList *TypeParams = TypeParamLists[i];
    if (PrevIDecl && TypeParams) {
      if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) {
        // Check for consistency with the previous declaration.
        if (checkTypeParamListConsistency(
                SemaRef, PrevTypeParams, TypeParams,
                TypeParamListContext::ForwardDeclaration)) {
          TypeParams = nullptr;
        }
      } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {
        // The @interface does not have type parameters. Complain.
        Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class)
          << ClassName
          << TypeParams->getSourceRange();
        Diag(Def->getLocation(), diag::note_defined_here)
          << ClassName;

        TypeParams = nullptr;
      }
    }

    ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(
        Context, SemaRef.CurContext, AtClassLoc, ClassName, TypeParams,
        PrevIDecl, IdentLocs[i]);
    IDecl->setAtEndRange(IdentLocs[i]);

    if (PrevIDecl)
      SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);

    SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);
    CheckObjCDeclScope(IDecl);
    DeclsInGroup.push_back(IDecl);
  }

  return SemaRef.BuildDeclaratorGroup(DeclsInGroup);
}

static bool tryMatchRecordTypes(ASTContext &Context,
                                SemaObjC::MethodMatchStrategy strategy,
                                const Type *left, const Type *right);

static bool matchTypes(ASTContext &Context,
                       SemaObjC::MethodMatchStrategy strategy, QualType leftQT,
                       QualType rightQT) {
  const Type *left =
    Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr();
  const Type *right =
    Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr();

  if (left == right) return true;

  // If we're doing a strict match, the types have to match exactly.
  if (strategy == SemaObjC::MMS_strict)
    return false;

  if (left->isIncompleteType() || right->isIncompleteType()) return false;

  // Otherwise, use this absurdly complicated algorithm to try to
  // validate the basic, low-level compatibility of the two types.

  // As a minimum, require the sizes and alignments to match.
  TypeInfo LeftTI = Context.getTypeInfo(left);
  TypeInfo RightTI = Context.getTypeInfo(right);
  if (LeftTI.Width != RightTI.Width)
    return false;

  if (LeftTI.Align != RightTI.Align)
    return false;

  // Consider all the kinds of non-dependent canonical types:
  // - functions and arrays aren't possible as return and parameter types

  // - vector types of equal size can be arbitrarily mixed
  if (isa<VectorType>(left)) return isa<VectorType>(right);
  if (isa<VectorType>(right)) return false;

  // - references should only match references of identical type
  // - structs, unions, and Objective-C objects must match more-or-less
  //   exactly
  // - everything else should be a scalar
  if (!left->isScalarType() || !right->isScalarType())
    return tryMatchRecordTypes(Context, strategy, left, right);

  // Make scalars agree in kind, except count bools as chars, and group
  // all non-member pointers together.
  Type::ScalarTypeKind leftSK = left->getScalarTypeKind();
  Type::ScalarTypeKind rightSK = right->getScalarTypeKind();
  if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral;
  if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral;
  if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer)
    leftSK = Type::STK_ObjCObjectPointer;
  if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer)
    rightSK = Type::STK_ObjCObjectPointer;

  // Note that data member pointers and function member pointers don't
  // intermix because of the size differences.

  return (leftSK == rightSK);
}

static bool tryMatchRecordTypes(ASTContext &Context,
                                SemaObjC::MethodMatchStrategy strategy,
                                const Type *lt, const Type *rt) {
  assert(lt && rt && lt != rt);

  if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false;
  RecordDecl *left =
      cast<RecordType>(lt)->getOriginalDecl()->getDefinitionOrSelf();
  RecordDecl *right =
      cast<RecordType>(rt)->getOriginalDecl()->getDefinitionOrSelf();

  // Require union-hood to match.
  if (left->isUnion() != right->isUnion()) return false;

  // Require an exact match if either is non-POD.
  if ((isa<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) ||
      (isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(right)->isPOD()))
    return false;

  // Require size and alignment to match.
  TypeInfo LeftTI = Context.getTypeInfo(lt);
  TypeInfo RightTI = Context.getTypeInfo(rt);
  if (LeftTI.Width != RightTI.Width)
    return false;

  if (LeftTI.Align != RightTI.Align)
    return false;

  // Require fields to match.
  RecordDecl::field_iterator li = left->field_begin(), le = left->field_end();
  RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end();
  for (; li != le && ri != re; ++li, ++ri) {
    if (!matchTypes(Context, strategy, li->getType(), ri->getType()))
      return false;
  }
  return (li == le && ri == re);
}

/// MatchTwoMethodDeclarations - Checks that two methods have matching type and
/// returns true, or false, accordingly.
/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons
bool SemaObjC::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,
                                          const ObjCMethodDecl *right,
                                          MethodMatchStrategy strategy) {
  ASTContext &Context = getASTContext();
  if (!matchTypes(Context, strategy, left->getReturnType(),
                  right->getReturnType()))
    return false;

  // If either is hidden, it is not considered to match.
  if (!left->isUnconditionallyVisible() || !right->isUnconditionallyVisible())
    return false;

  if (left->isDirectMethod() != right->isDirectMethod())
    return false;

  if (getLangOpts().ObjCAutoRefCount &&
      (left->hasAttr<NSReturnsRetainedAttr>()
         != right->hasAttr<NSReturnsRetainedAttr>() ||
       left->hasAttr<NSConsumesSelfAttr>()
         != right->hasAttr<NSConsumesSelfAttr>()))
    return false;

  ObjCMethodDecl::param_const_iterator
    li = left->param_begin(), le = left->param_end(), ri = right->param_begin(),
    re = right->param_end();

  for (; li != le && ri != re; ++li, ++ri) {
    assert(ri != right->param_end() && "Param mismatch");
    const ParmVarDecl *lparm = *li, *rparm = *ri;

    if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType()))
      return false;

    if (getLangOpts().ObjCAutoRefCount &&
        lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>())
      return false;
  }
  return true;
}

static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method,
                                               ObjCMethodDecl *MethodInList) {
  auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());
  auto *MethodInListProtocol =
      dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext());
  // If this method belongs to a protocol but the method in list does not, or
  // vice versa, we say the context is not the same.
  if ((MethodProtocol && !MethodInListProtocol) ||
      (!MethodProtocol && MethodInListProtocol))
    return false;

  if (MethodProtocol && MethodInListProtocol)
    return true;

  ObjCInterfaceDecl *MethodInterface = Method->getClassInterface();
  ObjCInterfaceDecl *MethodInListInterface =
      MethodInList->getClassInterface();
  return MethodInterface == MethodInListInterface;
}

void SemaObjC::addMethodToGlobalList(ObjCMethodList *List,
                                     ObjCMethodDecl *Method) {
  // Record at the head of the list whether there were 0, 1, or >= 2 methods
  // inside categories.
  if (ObjCCategoryDecl *CD =
          dyn_cast<ObjCCategoryDecl>(Method->getDeclContext()))
    if (!CD->IsClassExtension() && List->getBits() < 2)
      List->setBits(List->getBits() + 1);

  // If the list is empty, make it a singleton list.
  if (List->getMethod() == nullptr) {
    List->setMethod(Method);
    List->setNext(nullptr);
    return;
  }

  // We've seen a method with this name, see if we have already seen this type
  // signature.
  ObjCMethodList *Previous = List;
  ObjCMethodList *ListWithSameDeclaration = nullptr;
  for (; List; Previous = List, List = List->getNext()) {
    // If we are building a module, keep all of the methods.
    if (getLangOpts().isCompilingModule())
      continue;

    bool SameDeclaration = MatchTwoMethodDeclarations(Method,
                                                      List->getMethod());
    // Looking for method with a type bound requires the correct context exists.
    // We need to insert a method into the list if the context is different.
    // If the method's declaration matches the list
    // a> the method belongs to a different context: we need to insert it, in
    //    order to emit the availability message, we need to prioritize over
    //    availability among the methods with the same declaration.
    // b> the method belongs to the same context: there is no need to insert a
    //    new entry.
    // If the method's declaration does not match the list, we insert it to the
    // end.
    if (!SameDeclaration ||
        !isMethodContextSameForKindofLookup(Method, List->getMethod())) {
      // Even if two method types do not match, we would like to say
      // there is more than one declaration so unavailability/deprecated
      // warning is not too noisy.
      if (!Method->isDefined())
        List->setHasMoreThanOneDecl(true);

      // For methods with the same declaration, the one that is deprecated
      // should be put in the front for better diagnostics.
      if (Method->isDeprecated() && SameDeclaration &&
          !ListWithSameDeclaration && !List->getMethod()->isDeprecated())
        ListWithSameDeclaration = List;

      if (Method->isUnavailable() && SameDeclaration &&
          !ListWithSameDeclaration &&
          List->getMethod()->getAvailability() < AR_Deprecated)
        ListWithSameDeclaration = List;
      continue;
    }

    ObjCMethodDecl *PrevObjCMethod = List->getMethod();

    // Propagate the 'defined' bit.
    if (Method->isDefined())
      PrevObjCMethod->setDefined(true);
    else {
      // Objective-C doesn't allow an @interface for a class after its
      // @implementation. So if Method is not defined and there already is
      // an entry for this type signature, Method has to be for a different
      // class than PrevObjCMethod.
      List->setHasMoreThanOneDecl(true);
    }

    // If a method is deprecated, push it in the global pool.
    // This is used for better diagnostics.
    if (Method->isDeprecated()) {
      if (!PrevObjCMethod->isDeprecated())
        List->setMethod(Method);
    }
    // If the new method is unavailable, push it into global pool
    // unless previous one is deprecated.
    if (Method->isUnavailable()) {
      if (PrevObjCMethod->getAvailability() < AR_Deprecated)
        List->setMethod(Method);
    }

    return;
  }

  // We have a new signature for an existing method - add it.
  // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
  ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate<ObjCMethodList>();

  // We insert it right before ListWithSameDeclaration.
  if (ListWithSameDeclaration) {
    auto *List = new (Mem) ObjCMethodList(*ListWithSameDeclaration);
    // FIXME: should we clear the other bits in ListWithSameDeclaration?
    ListWithSameDeclaration->setMethod(Method);
    ListWithSameDeclaration->setNext(List);
    return;
  }

  Previous->setNext(new (Mem) ObjCMethodList(Method));
}

/// Read the contents of the method pool for a given selector from
/// external storage.
void SemaObjC::ReadMethodPool(Selector Sel) {
  assert(SemaRef.ExternalSource && "We need an external AST source");
  SemaRef.ExternalSource->ReadMethodPool(Sel);
}

void SemaObjC::updateOutOfDateSelector(Selector Sel) {
  if (!SemaRef.ExternalSource)
    return;
  SemaRef.ExternalSource->updateOutOfDateSelector(Sel);
}

void SemaObjC::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,
                                     bool instance) {
  // Ignore methods of invalid containers.
  if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())
    return;

  if (SemaRef.ExternalSource)
    ReadMethodPool(Method->getSelector());

  auto &Lists = MethodPool[Method->getSelector()];

  Method->setDefined(impl);

  ObjCMethodList &Entry = instance ? Lists.first : Lists.second;
  addMethodToGlobalList(&Entry, Method);
}

/// Determines if this is an "acceptable" loose mismatch in the global
/// method pool.  This exists mostly as a hack to get around certain
/// global mismatches which we can't afford to make warnings / errors.
/// Really, what we want is a way to take a method out of the global
/// method pool.
static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,
                                       ObjCMethodDecl *other) {
  if (!chosen->isInstanceMethod())
    return false;

  if (chosen->isDirectMethod() != other->isDirectMethod())
    return false;

  Selector sel = chosen->getSelector();
  if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length")
    return false;

  // Don't complain about mismatches for -length if the method we
  // chose has an integral result type.
  return (chosen->getReturnType()->isIntegerType());
}

/// Return true if the given method is wthin the type bound.
static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method,
                                     const ObjCObjectType *TypeBound) {
  if (!TypeBound)
    return true;

  if (TypeBound->isObjCId())
    // FIXME: should we handle the case of bounding to id<A, B> differently?
    return true;

  auto *BoundInterface = TypeBound->getInterface();
  assert(BoundInterface && "unexpected object type!");

  // Check if the Method belongs to a protocol. We should allow any method
  // defined in any protocol, because any subclass could adopt the protocol.
  auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());
  if (MethodProtocol) {
    return true;
  }

  // If the Method belongs to a class, check if it belongs to the class
  // hierarchy of the class bound.
  if (ObjCInterfaceDecl *MethodInterface = Method->getClassInterface()) {
    // We allow methods declared within classes that are part of the hierarchy
    // of the class bound (superclass of, subclass of, or the same as the class
    // bound).
    return MethodInterface == BoundInterface ||
           MethodInterface->isSuperClassOf(BoundInterface) ||
           BoundInterface->isSuperClassOf(MethodInterface);
  }
  llvm_unreachable("unknown method context");
}

/// We first select the type of the method: Instance or Factory, then collect
/// all methods with that type.
bool SemaObjC::CollectMultipleMethodsInGlobalPool(
    Selector Sel, SmallVectorImpl<ObjCMethodDecl *> &Methods,
    bool InstanceFirst, bool CheckTheOther, const ObjCObjectType *TypeBound) {
  if (SemaRef.ExternalSource)
    ReadMethodPool(Sel);

  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
  if (Pos == MethodPool.end())
    return false;

  // Gather the non-hidden methods.
  ObjCMethodList &MethList = InstanceFirst ? Pos->second.first :
                             Pos->second.second;
  for (ObjCMethodList *M = &MethList; M; M = M->getNext())
    if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {
      if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))
        Methods.push_back(M->getMethod());
    }

  // Return if we find any method with the desired kind.
  if (!Methods.empty())
    return Methods.size() > 1;

  if (!CheckTheOther)
    return false;

  // Gather the other kind.
  ObjCMethodList &MethList2 = InstanceFirst ? Pos->second.second :
                              Pos->second.first;
  for (ObjCMethodList *M = &MethList2; M; M = M->getNext())
    if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {
      if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))
        Methods.push_back(M->getMethod());
    }

  return Methods.size() > 1;
}

bool SemaObjC::AreMultipleMethodsInGlobalPool(
    Selector Sel, ObjCMethodDecl *BestMethod, SourceRange R,
    bool receiverIdOrClass, SmallVectorImpl<ObjCMethodDecl *> &Methods) {
  // Diagnose finding more than one method in global pool.
  SmallVector<ObjCMethodDecl *, 4> FilteredMethods;
  FilteredMethods.push_back(BestMethod);

  for (auto *M : Methods)
    if (M != BestMethod && !M->hasAttr<UnavailableAttr>())
      FilteredMethods.push_back(M);

  if (FilteredMethods.size() > 1)
    DiagnoseMultipleMethodInGlobalPool(FilteredMethods, Sel, R,
                                       receiverIdOrClass);

  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
  // Test for no method in the pool which should not trigger any warning by
  // caller.
  if (Pos == MethodPool.end())
    return true;
  ObjCMethodList &MethList =
    BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;
  return MethList.hasMoreThanOneDecl();
}

ObjCMethodDecl *SemaObjC::LookupMethodInGlobalPool(Selector Sel, SourceRange R,
                                                   bool receiverIdOrClass,
                                                   bool instance) {
  if (SemaRef.ExternalSource)
    ReadMethodPool(Sel);

  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
  if (Pos == MethodPool.end())
    return nullptr;

  // Gather the non-hidden methods.
  ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;
  for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {
    if (M->getMethod() && M->getMethod()->isUnconditionallyVisible())
      return M->getMethod();
  }
  return nullptr;
}

void SemaObjC::DiagnoseMultipleMethodInGlobalPool(
    SmallVectorImpl<ObjCMethodDecl *> &Methods, Selector Sel, SourceRange R,
    bool receiverIdOrClass) {
  // We found multiple methods, so we may have to complain.
  bool issueDiagnostic = false, issueError = false;

  // We support a warning which complains about *any* difference in
  // method signature.
  bool strictSelectorMatch =
      receiverIdOrClass &&
      !getDiagnostics().isIgnored(diag::warn_strict_multiple_method_decl,
                                  R.getBegin());
  if (strictSelectorMatch) {
    for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
      if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {
        issueDiagnostic = true;
        break;
      }
    }
  }

  // If we didn't see any strict differences, we won't see any loose
  // differences.  In ARC, however, we also need to check for loose
  // mismatches, because most of them are errors.
  if (!strictSelectorMatch ||
      (issueDiagnostic && getLangOpts().ObjCAutoRefCount))
    for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
      // This checks if the methods differ in type mismatch.
      if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) &&
          !isAcceptableMethodMismatch(Methods[0], Methods[I])) {
        issueDiagnostic = true;
        if (getLangOpts().ObjCAutoRefCount)
          issueError = true;
        break;
      }
    }

  if (issueDiagnostic) {
    if (issueError)
      Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;
    else if (strictSelectorMatch)
      Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;
    else
      Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;

    Diag(Methods[0]->getBeginLoc(),
         issueError ? diag::note_possibility : diag::note_using)
        << Methods[0]->getSourceRange();
    for (unsigned I = 1, N = Methods.size(); I != N; ++I) {
      Diag(Methods[I]->getBeginLoc(), diag::note_also_found)
          << Methods[I]->getSourceRange();
    }
  }
}

ObjCMethodDecl *SemaObjC::LookupImplementedMethodInGlobalPool(Selector Sel) {
  GlobalMethodPool::iterator Pos = MethodPool.find(Sel);
  if (Pos == MethodPool.end())
    return nullptr;

  auto &Methods = Pos->second;
  for (const ObjCMethodList *Method = &Methods.first; Method;
       Method = Method->getNext())
    if (Method->getMethod() &&
        (Method->getMethod()->isDefined() ||
         Method->getMethod()->isPropertyAccessor()))
      return Method->getMethod();

  for (const ObjCMethodList *Method = &Methods.second; Method;
       Method = Method->getNext())
    if (Method->getMethod() &&
        (Method->getMethod()->isDefined() ||
         Method->getMethod()->isPropertyAccessor()))
      return Method->getMethod();
  return nullptr;
}

static void
HelperSelectorsForTypoCorrection(
                      SmallVectorImpl<const ObjCMethodDecl *> &BestMethod,
                      StringRef Typo, const ObjCMethodDecl * Method) {
  const unsigned MaxEditDistance = 1;
  unsigned BestEditDistance = MaxEditDistance + 1;
  std::string MethodName = Method->getSelector().getAsString();

  unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size());
  if (MinPossibleEditDistance > 0 &&
      Typo.size() / MinPossibleEditDistance < 1)
    return;
  unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance);
  if (EditDistance > MaxEditDistance)
    return;
  if (EditDistance == BestEditDistance)
    BestMethod.push_back(Method);
  else if (EditDistance < BestEditDistance) {
    BestMethod.clear();
    BestMethod.push_back(Method);
  }
}

static bool HelperIsMethodInObjCType(Sema &S, Selector Sel,
                                     QualType ObjectType) {
  if (ObjectType.isNull())
    return true;
  if (S.ObjC().LookupMethodInObjectType(Sel, ObjectType,
                                        true /*Instance method*/))
    return true;
  return S.ObjC().LookupMethodInObjectType(Sel, ObjectType,
                                           false /*Class method*/) != nullptr;
}

const ObjCMethodDecl *
SemaObjC::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) {
  unsigned NumArgs = Sel.getNumArgs();
  SmallVector<const ObjCMethodDecl *, 8> Methods;
  bool ObjectIsId = true, ObjectIsClass = true;
  if (ObjectType.isNull())
    ObjectIsId = ObjectIsClass = false;
  else if (!ObjectType->isObjCObjectPointerType())
    return nullptr;
  else if (const ObjCObjectPointerType *ObjCPtr =
           ObjectType->getAsObjCInterfacePointerType()) {
    ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
    ObjectIsId = ObjectIsClass = false;
  }
  else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType())
    ObjectIsClass = false;
  else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())
    ObjectIsId = false;
  else
    return nullptr;

  for (GlobalMethodPool::iterator b = MethodPool.begin(),
       e = MethodPool.end(); b != e; b++) {
    // instance methods
    for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())
      if (M->getMethod() &&
          (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&
          (M->getMethod()->getSelector() != Sel)) {
        if (ObjectIsId)
          Methods.push_back(M->getMethod());
        else if (!ObjectIsClass &&
                 HelperIsMethodInObjCType(
                     SemaRef, M->getMethod()->getSelector(), ObjectType))
          Methods.push_back(M->getMethod());
      }
    // class methods
    for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())
      if (M->getMethod() &&
          (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&
          (M->getMethod()->getSelector() != Sel)) {
        if (ObjectIsClass)
          Methods.push_back(M->getMethod());
        else if (!ObjectIsId &&
                 HelperIsMethodInObjCType(
                     SemaRef, M->getMethod()->getSelector(), ObjectType))
          Methods.push_back(M->getMethod());
      }
  }

  SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;
  for (unsigned i = 0, e = Methods.size(); i < e; i++) {
    HelperSelectorsForTypoCorrection(SelectedMethods,
                                     Sel.getAsString(), Methods[i]);
  }
  return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr;
}

/// DiagnoseDuplicateIvars -
/// Check for duplicate ivars in the entire class at the start of
/// \@implementation. This becomes necessary because class extension can
/// add ivars to a class in random order which will not be known until
/// class's \@implementation is seen.
void SemaObjC::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,
                                      ObjCInterfaceDecl *SID) {
  for (auto *Ivar : ID->ivars()) {
    if (Ivar->isInvalidDecl())
      continue;
    if (IdentifierInfo *II = Ivar->getIdentifier()) {
      ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II);
      if (prevIvar) {
        Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;
        Diag(prevIvar->getLocation(), diag::note_previous_declaration);
        Ivar->setInvalidDecl();
      }
    }
  }
}

/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled.
static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {
  if (S.getLangOpts().ObjCWeak) return;

  for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin();
         ivar; ivar = ivar->getNextIvar()) {
    if (ivar->isInvalidDecl()) continue;
    if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {
      if (S.getLangOpts().ObjCWeakRuntime) {
        S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled);
      } else {
        S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime);
      }
    }
  }
}

/// Diagnose attempts to use flexible array member with retainable object type.
static void DiagnoseRetainableFlexibleArrayMember(Sema &S,
                                                  ObjCInterfaceDecl *ID) {
  if (!S.getLangOpts().ObjCAutoRefCount)
    return;

  for (auto ivar = ID->all_declared_ivar_begin(); ivar;
       ivar = ivar->getNextIvar()) {
    if (ivar->isInvalidDecl())
      continue;
    QualType IvarTy = ivar->getType();
    if (IvarTy->isIncompleteArrayType() &&
        (IvarTy.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) &&
        IvarTy->isObjCLifetimeType()) {
      S.Diag(ivar->getLocation(), diag::err_flexible_array_arc_retainable);
      ivar->setInvalidDecl();
    }
  }
}

SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const {
  switch (SemaRef.CurContext->getDeclKind()) {
  case Decl::ObjCInterface:
    return SemaObjC::OCK_Interface;
  case Decl::ObjCProtocol:
    return SemaObjC::OCK_Protocol;
  case Decl::ObjCCategory:
    if (cast<ObjCCategoryDecl>(SemaRef.CurContext)->IsClassExtension())
      return SemaObjC::OCK_ClassExtension;
    return SemaObjC::OCK_Category;
  case Decl::ObjCImplementation:
    return SemaObjC::OCK_Implementation;
  case Decl::ObjCCategoryImpl:
    return SemaObjC::OCK_CategoryImplementation;

  default:
    return SemaObjC::OCK_None;
  }
}

static bool IsVariableSizedType(QualType T) {
  if (T->isIncompleteArrayType())
    return true;
  const auto *RD = T->getAsRecordDecl();
  return RD && RD->hasFlexibleArrayMember();
}

static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {
  ObjCInterfaceDecl *IntfDecl = nullptr;
  ObjCInterfaceDecl::ivar_range Ivars = llvm::make_range(
      ObjCInterfaceDecl::ivar_iterator(), ObjCInterfaceDecl::ivar_iterator());
  if ((IntfDecl = dyn_cast<ObjCInterfaceDecl>(OCD))) {
    Ivars = IntfDecl->ivars();
  } else if (auto *ImplDecl = dyn_cast<ObjCImplementationDecl>(OCD)) {
    IntfDecl = ImplDecl->getClassInterface();
    Ivars = ImplDecl->ivars();
  } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(OCD)) {
    if (CategoryDecl->IsClassExtension()) {
      IntfDecl = CategoryDecl->getClassInterface();
      Ivars = CategoryDecl->ivars();
    }
  }

  // Check if variable sized ivar is in interface and visible to subclasses.
  if (!isa<ObjCInterfaceDecl>(OCD)) {
    for (auto *ivar : Ivars) {
      if (!ivar->isInvalidDecl() && IsVariableSizedType(ivar->getType())) {
        S.Diag(ivar->getLocation(), diag::warn_variable_sized_ivar_visibility)
            << ivar->getDeclName() << ivar->getType();
      }
    }
  }

  // Subsequent checks require interface decl.
  if (!IntfDecl)
    return;

  // Check if variable sized ivar is followed by another ivar.
  for (ObjCIvarDecl *ivar = IntfDecl->all_declared_ivar_begin(); ivar;
       ivar = ivar->getNextIvar()) {
    if (ivar->isInvalidDecl() || !ivar->getNextIvar())
      continue;
    QualType IvarTy = ivar->getType();
    bool IsInvalidIvar = false;
    if (IvarTy->isIncompleteArrayType()) {
      S.Diag(ivar->getLocation(), diag::err_flexible_array_not_at_end)
          << ivar->getDeclName() << IvarTy
          << TagTypeKind::Class; // Use "class" for Obj-C.
      IsInvalidIvar = true;
    } else if (const auto *RD = IvarTy->getAsRecordDecl();
               RD && RD->hasFlexibleArrayMember()) {
      S.Diag(ivar->getLocation(), diag::err_objc_variable_sized_type_not_at_end)
          << ivar->getDeclName() << IvarTy;
      IsInvalidIvar = true;
    }
    if (IsInvalidIvar) {
      S.Diag(ivar->getNextIvar()->getLocation(),
             diag::note_next_ivar_declaration)
          << ivar->getNextIvar()->getSynthesize();
      ivar->setInvalidDecl();
    }
  }

  // Check if ObjC container adds ivars after variable sized ivar in superclass.
  // Perform the check only if OCD is the first container to declare ivars to
  // avoid multiple warnings for the same ivar.
  ObjCIvarDecl *FirstIvar =
      (Ivars.begin() == Ivars.end()) ? nullptr : *Ivars.begin();
  if (FirstIvar && (FirstIvar == IntfDecl->all_declared_ivar_begin())) {
    const ObjCInterfaceDecl *SuperClass = IntfDecl->getSuperClass();
    while (SuperClass && SuperClass->ivar_empty())
      SuperClass = SuperClass->getSuperClass();
    if (SuperClass) {
      auto IvarIter = SuperClass->ivar_begin();
      std::advance(IvarIter, SuperClass->ivar_size() - 1);
      const ObjCIvarDecl *LastIvar = *IvarIter;
      if (IsVariableSizedType(LastIvar->getType())) {
        S.Diag(FirstIvar->getLocation(),
               diag::warn_superclass_variable_sized_type_not_at_end)
            << FirstIvar->getDeclName() << LastIvar->getDeclName()
            << LastIvar->getType() << SuperClass->getDeclName();
        S.Diag(LastIvar->getLocation(), diag::note_entity_declared_at)
            << LastIvar->getDeclName();
      }
    }
  }
}

static void DiagnoseCategoryDirectMembersProtocolConformance(
    Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl);

static void DiagnoseCategoryDirectMembersProtocolConformance(
    Sema &S, ObjCCategoryDecl *CDecl,
    const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) {
  for (auto *PI : Protocols)
    DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl);
}

static void DiagnoseCategoryDirectMembersProtocolConformance(
    Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) {
  if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())
    PDecl = PDecl->getDefinition();

  llvm::SmallVector<const Decl *, 4> DirectMembers;
  const auto *IDecl = CDecl->getClassInterface();
  for (auto *MD : PDecl->methods()) {
    if (!MD->isPropertyAccessor()) {
      if (const auto *CMD =
              IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) {
        if (CMD->isDirectMethod())
          DirectMembers.push_back(CMD);
      }
    }
  }
  for (auto *PD : PDecl->properties()) {
    if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass(
            PD->getIdentifier(),
            PD->isClassProperty()
                ? ObjCPropertyQueryKind::OBJC_PR_query_class
                : ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
      if (CPD->isDirectProperty())
        DirectMembers.push_back(CPD);
    }
  }
  if (!DirectMembers.empty()) {
    S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance)
        << CDecl->IsClassExtension() << CDecl << PDecl << IDecl;
    for (const auto *MD : DirectMembers)
      S.Diag(MD->getLocation(), diag::note_direct_member_here);
    return;
  }

  // Check on this protocols's referenced protocols, recursively.
  DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl,
                                                   PDecl->protocols());
}

// Note: For class/category implementations, allMethods is always null.
Decl *SemaObjC::ActOnAtEnd(Scope *S, SourceRange AtEnd,
                           ArrayRef<Decl *> allMethods,
                           ArrayRef<DeclGroupPtrTy> allTUVars) {
  ASTContext &Context = getASTContext();
  if (getObjCContainerKind() == SemaObjC::OCK_None)
    return nullptr;

  assert(AtEnd.isValid() && "Invalid location for '@end'");

  auto *OCD = cast<ObjCContainerDecl>(SemaRef.CurContext);
  Decl *ClassDecl = OCD;

  bool isInterfaceDeclKind =
        isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)
         || isa<ObjCProtocolDecl>(ClassDecl);
  bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);

  // Make synthesized accessor stub functions visible.
  // ActOnPropertyImplDecl() creates them as not visible in case
  // they are overridden by an explicit method that is encountered
  // later.
  if (auto *OID = dyn_cast<ObjCImplementationDecl>(SemaRef.CurContext)) {
    for (auto *PropImpl : OID->property_impls()) {
      if (auto *Getter = PropImpl->getGetterMethodDecl())
        if (Getter->isSynthesizedAccessorStub())
          OID->addDecl(Getter);
      if (auto *Setter = PropImpl->getSetterMethodDecl())
        if (Setter->isSynthesizedAccessorStub())
          OID->addDecl(Setter);
    }
  }

  // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.
  llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;
  llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;

  for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) {
    ObjCMethodDecl *Method =
      cast_or_null<ObjCMethodDecl>(allMethods[i]);

    if (!Method) continue;  // Already issued a diagnostic.
    if (Method->isInstanceMethod()) {
      /// Check for instance method of the same name with incompatible types
      const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];
      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
                              : false;
      if ((isInterfaceDeclKind && PrevMethod && !match)
          || (checkIdenticalMethods && match)) {
          Diag(Method->getLocation(), diag::err_duplicate_method_decl)
            << Method->getDeclName();
          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
        Method->setInvalidDecl();
      } else {
        if (PrevMethod) {
          Method->setAsRedeclaration(PrevMethod);
          if (!Context.getSourceManager().isInSystemHeader(
                 Method->getLocation()))
            Diag(Method->getLocation(), diag::warn_duplicate_method_decl)
              << Method->getDeclName();
          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
        }
        InsMap[Method->getSelector()] = Method;
        /// The following allows us to typecheck messages to "id".
        AddInstanceMethodToGlobalPool(Method);
      }
    } else {
      /// Check for class method of the same name with incompatible types
      const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];
      bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)
                              : false;
      if ((isInterfaceDeclKind && PrevMethod && !match)
          || (checkIdenticalMethods && match)) {
        Diag(Method->getLocation(), diag::err_duplicate_method_decl)
          << Method->getDeclName();
        Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
        Method->setInvalidDecl();
      } else {
        if (PrevMethod) {
          Method->setAsRedeclaration(PrevMethod);
          if (!Context.getSourceManager().isInSystemHeader(
                 Method->getLocation()))
            Diag(Method->getLocation(), diag::warn_duplicate_method_decl)
              << Method->getDeclName();
          Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
        }
        ClsMap[Method->getSelector()] = Method;
        AddFactoryMethodToGlobalPool(Method);
      }
    }
  }
  if (isa<ObjCInterfaceDecl>(ClassDecl)) {
    // Nothing to do here.
  } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {
    // Categories are used to extend the class by declaring new methods.
    // By the same token, they are also used to add new properties. No
    // need to compare the added property to those in the class.

    if (C->IsClassExtension()) {
      ObjCInterfaceDecl *CCPrimary = C->getClassInterface();
      DiagnoseClassExtensionDupMethods(C, CCPrimary);
    }

    DiagnoseCategoryDirectMembersProtocolConformance(SemaRef, C,
                                                     C->protocols());
  }
  if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {
    if (CDecl->getIdentifier())
      // ProcessPropertyDecl is responsible for diagnosing conflicts with any
      // user-defined setter/getter. It also synthesizes setter/getter methods
      // and adds them to the DeclContext and global method pools.
      for (auto *I : CDecl->properties())
        ProcessPropertyDecl(I);
    CDecl->setAtEndRange(AtEnd);
  }
  if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {
    IC->setAtEndRange(AtEnd);
    if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {
      // Any property declared in a class extension might have user
      // declared setter or getter in current class extension or one
      // of the other class extensions. Mark them as synthesized as
      // property will be synthesized when property with same name is
      // seen in the @implementation.
      for (const auto *Ext : IDecl->visible_extensions()) {
        for (const auto *Property : Ext->instance_properties()) {
          // Skip over properties declared @dynamic
          if (const ObjCPropertyImplDecl *PIDecl
              = IC->FindPropertyImplDecl(Property->getIdentifier(),
                                         Property->getQueryKind()))
            if (PIDecl->getPropertyImplementation()
                  == ObjCPropertyImplDecl::Dynamic)
              continue;

          for (const auto *Ext : IDecl->visible_extensions()) {
            if (ObjCMethodDecl *GetterMethod =
                    Ext->getInstanceMethod(Property->getGetterName()))
              GetterMethod->setPropertyAccessor(true);
            if (!Property->isReadOnly())
              if (ObjCMethodDecl *SetterMethod
                    = Ext->getInstanceMethod(Property->getSetterName()))
                SetterMethod->setPropertyAccessor(true);
          }
        }
      }
      ImplMethodsVsClassMethods(S, IC, IDecl);
      AtomicPropertySetterGetterRules(IC, IDecl);
      DiagnoseOwningPropertyGetterSynthesis(IC);
      DiagnoseUnusedBackingIvarInAccessor(S, IC);
      if (IDecl->hasDesignatedInitializers())
        DiagnoseMissingDesignatedInitOverrides(IC, IDecl);
      DiagnoseWeakIvars(SemaRef, IC);
      DiagnoseRetainableFlexibleArrayMember(SemaRef, IDecl);

      bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();
      if (IDecl->getSuperClass() == nullptr) {
        // This class has no superclass, so check that it has been marked with
        // __attribute((objc_root_class)).
        if (!HasRootClassAttr) {
          SourceLocation DeclLoc(IDecl->getLocation());
          SourceLocation SuperClassLoc(SemaRef.getLocForEndOfToken(DeclLoc));
          Diag(DeclLoc, diag::warn_objc_root_class_missing)
            << IDecl->getIdentifier();
          // See if NSObject is in the current scope, and if it is, suggest
          // adding " : NSObject " to the class declaration.
          NamedDecl *IF = SemaRef.LookupSingleName(
              SemaRef.TUScope, NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject),
              DeclLoc, Sema::LookupOrdinaryName);
          ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);
          if (NSObjectDecl && NSObjectDecl->getDefinition()) {
            Diag(SuperClassLoc, diag::note_objc_needs_superclass)
              << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject ");
          } else {
            Diag(SuperClassLoc, diag::note_objc_needs_superclass);
          }
        }
      } else if (HasRootClassAttr) {
        // Complain that only root classes may have this attribute.
        Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);
      }

      if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) {
        // An interface can subclass another interface with a
        // objc_subclassing_restricted attribute when it has that attribute as
        // well (because of interfaces imported from Swift). Therefore we have
        // to check if we can subclass in the implementation as well.
        if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
            Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
          Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch);
          Diag(Super->getLocation(), diag::note_class_declared);
        }
      }

      if (IDecl->hasAttr<ObjCClassStubAttr>())
        Diag(IC->getLocation(), diag::err_implementation_of_class_stub);

      if (getLangOpts().ObjCRuntime.isNonFragile()) {
        while (IDecl->getSuperClass()) {
          DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());
          IDecl = IDecl->getSuperClass();
        }
      }
    }
    SetIvarInitializers(IC);
  } else if (ObjCCategoryImplDecl* CatImplClass =
                                   dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {
    CatImplClass->setAtEndRange(AtEnd);

    // Find category interface decl and then check that all methods declared
    // in this interface are implemented in the category @implementation.
    if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {
      if (ObjCCategoryDecl *Cat
            = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) {
        ImplMethodsVsClassMethods(S, CatImplClass, Cat);
      }
    }
  } else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
    if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) {
      if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&
          Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {
        Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch);
        Diag(Super->getLocation(), diag::note_class_declared);
      }
    }

    if (IntfDecl->hasAttr<ObjCClassStubAttr>() &&
        !IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>())
      Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch);
  }
  DiagnoseVariableSizedIvars(SemaRef, OCD);
  if (isInterfaceDeclKind) {
    // Reject invalid vardecls.
    for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {
      DeclGroupRef DG = allTUVars[i].get();
      for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
        if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {
          if (!VDecl->hasExternalStorage())
            Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);
        }
    }
  }
  ActOnObjCContainerFinishDefinition();

  for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {
    DeclGroupRef DG = allTUVars[i].get();
    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
      (*I)->setTopLevelDeclInObjCContainer();
    SemaRef.Consumer.HandleTopLevelDeclInObjCContainer(DG);
  }

  SemaRef.ActOnDocumentableDecl(ClassDecl);
  return ClassDecl;
}

/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for
/// objective-c's type qualifier from the parser version of the same info.
static Decl::ObjCDeclQualifier
CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {
  return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;
}

/// Check whether the declared result type of the given Objective-C
/// method declaration is compatible with the method's class.
///
static SemaObjC::ResultTypeCompatibilityKind
CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,
                                    ObjCInterfaceDecl *CurrentClass) {
  QualType ResultType = Method->getReturnType();

  // If an Objective-C method inherits its related result type, then its
  // declared result type must be compatible with its own class type. The
  // declared result type is compatible if:
  if (const ObjCObjectPointerType *ResultObjectType
                                = ResultType->getAs<ObjCObjectPointerType>()) {
    //   - it is id or qualified id, or
    if (ResultObjectType->isObjCIdType() ||
        ResultObjectType->isObjCQualifiedIdType())
      return SemaObjC::RTC_Compatible;

    if (CurrentClass) {
      if (ObjCInterfaceDecl *ResultClass
                                      = ResultObjectType->getInterfaceDecl()) {
        //   - it is the same as the method's class type, or
        if (declaresSameEntity(CurrentClass, ResultClass))
          return SemaObjC::RTC_Compatible;

        //   - it is a superclass of the method's class type
        if (ResultClass->isSuperClassOf(CurrentClass))
          return SemaObjC::RTC_Compatible;
      }
    } else {
      // Any Objective-C pointer type might be acceptable for a protocol
      // method; we just don't know.
      return SemaObjC::RTC_Unknown;
    }
  }

  return SemaObjC::RTC_Incompatible;
}

namespace {
/// A helper class for searching for methods which a particular method
/// overrides.
class OverrideSearch {
public:
  const ObjCMethodDecl *Method;
  llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;
  bool Recursive;

public:
  OverrideSearch(Sema &S, const ObjCMethodDecl *method) : Method(method) {
    Selector selector = method->getSelector();

    // Bypass this search if we've never seen an instance/class method
    // with this selector before.
    SemaObjC::GlobalMethodPool::iterator it =
        S.ObjC().MethodPool.find(selector);
    if (it == S.ObjC().MethodPool.end()) {
      if (!S.getExternalSource()) return;
      S.ObjC().ReadMethodPool(selector);

      it = S.ObjC().MethodPool.find(selector);
      if (it == S.ObjC().MethodPool.end())
        return;
    }
    const ObjCMethodList &list =
      method->isInstanceMethod() ? it->second.first : it->second.second;
    if (!list.getMethod()) return;

    const ObjCContainerDecl *container
      = cast<ObjCContainerDecl>(method->getDeclContext());

    // Prevent the search from reaching this container again.  This is
    // important with categories, which override methods from the
    // interface and each other.
    if (const ObjCCategoryDecl *Category =
            dyn_cast<ObjCCategoryDecl>(container)) {
      searchFromContainer(container);
      if (const ObjCInterfaceDecl *Interface = Category->getClassInterface())
        searchFromContainer(Interface);
    } else {
      searchFromContainer(container);
    }
  }

  typedef decltype(Overridden)::iterator iterator;
  iterator begin() const { return Overridden.begin(); }
  iterator end() const { return Overridden.end(); }

private:
  void searchFromContainer(const ObjCContainerDecl *container) {
    if (container->isInvalidDecl()) return;

    switch (container->getDeclKind()) {
#define OBJCCONTAINER(type, base) \
    case Decl::type: \
      searchFrom(cast<type##Decl>(container)); \
      break;
#define ABSTRACT_DECL(expansion)
#define DECL(type, base) \
    case Decl::type:
#include "clang/AST/DeclNodes.inc"
      llvm_unreachable("not an ObjC container!");
    }
  }

  void searchFrom(const ObjCProtocolDecl *protocol) {
    if (!protocol->hasDefinition())
      return;

    // A method in a protocol declaration overrides declarations from
    // referenced ("parent") protocols.
    search(protocol->getReferencedProtocols());
  }

  void searchFrom(const ObjCCategoryDecl *category) {
    // A method in a category declaration overrides declarations from
    // the main class and from protocols the category references.
    // The main class is handled in the constructor.
    search(category->getReferencedProtocols());
  }

  void searchFrom(const ObjCCategoryImplDecl *impl) {
    // A method in a category definition that has a category
    // declaration overrides declarations from the category
    // declaration.
    if (ObjCCategoryDecl *category = impl->getCategoryDecl()) {
      search(category);
      if (ObjCInterfaceDecl *Interface = category->getClassInterface())
        search(Interface);

    // Otherwise it overrides declarations from the class.
    } else if (const auto *Interface = impl->getClassInterface()) {
      search(Interface);
    }
  }

  void searchFrom(const ObjCInterfaceDecl *iface) {
    // A method in a class declaration overrides declarations from
    if (!iface->hasDefinition())
      return;

    //   - categories,
    for (auto *Cat : iface->known_categories())
      search(Cat);

    //   - the super class, and
    if (ObjCInterfaceDecl *super = iface->getSuperClass())
      search(super);

    //   - any referenced protocols.
    search(iface->getReferencedProtocols());
  }

  void searchFrom(const ObjCImplementationDecl *impl) {
    // A method in a class implementation overrides declarations from
    // the class interface.
    if (const auto *Interface = impl->getClassInterface())
      search(Interface);
  }

  void search(const ObjCProtocolList &protocols) {
    for (const auto *Proto : protocols)
      search(Proto);
  }

  void search(const ObjCContainerDecl *container) {
    // Check for a method in this container which matches this selector.
    ObjCMethodDecl *meth = container->getMethod(Method->getSelector(),
                                                Method->isInstanceMethod(),
                                                /*AllowHidden=*/true);

    // If we find one, record it and bail out.
    if (meth) {
      Overridden.insert(meth);
      return;
    }

    // Otherwise, search for methods that a hypothetical method here
    // would have overridden.

    // Note that we're now in a recursive case.
    Recursive = true;

    searchFromContainer(container);
  }
};
} // end anonymous namespace

void SemaObjC::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
                                              ObjCMethodDecl *overridden) {
  if (overridden->isDirectMethod()) {
    const auto *attr = overridden->getAttr<ObjCDirectAttr>();
    Diag(method->getLocation(), diag::err_objc_override_direct_method);
    Diag(attr->getLocation(), diag::note_previous_declaration);
  } else if (method->isDirectMethod()) {
    const auto *attr = method->getAttr<ObjCDirectAttr>();
    Diag(attr->getLocation(), diag::err_objc_direct_on_override)
        << isa<ObjCProtocolDecl>(overridden->getDeclContext());
    Diag(overridden->getLocation(), diag::note_previous_declaration);
  }
}

void SemaObjC::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,
                                        ObjCInterfaceDecl *CurrentClass,
                                        ResultTypeCompatibilityKind RTC) {
  ASTContext &Context = getASTContext();
  if (!ObjCMethod)
    return;
  auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) {
    // Checking canonical decl works across modules.
    return M->getClassInterface()->getCanonicalDecl() ==
           CurrentClass->getCanonicalDecl();
  };
  // Search for overridden methods and merge information down from them.
  OverrideSearch overrides(SemaRef, ObjCMethod);
  // Keep track if the method overrides any method in the class's base classes,
  // its protocols, or its categories' protocols; we will keep that info
  // in the ObjCMethodDecl.
  // For this info, a method in an implementation is not considered as
  // overriding the same method in the interface or its categories.
  bool hasOverriddenMethodsInBaseOrProtocol = false;
  for (ObjCMethodDecl *overridden : overrides) {
    if (!hasOverriddenMethodsInBaseOrProtocol) {
      if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) ||
          !IsMethodInCurrentClass(overridden) || overridden->isOverriding()) {
        CheckObjCMethodDirectOverrides(ObjCMethod, overridden);
        hasOverriddenMethodsInBaseOrProtocol = true;
      } else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) {
        // OverrideSearch will return as "overridden" the same method in the
        // interface. For hasOverriddenMethodsInBaseOrProtocol, we need to
        // check whether a category of a base class introduced a method with the
        // same selector, after the interface method declaration.
        // To avoid unnecessary lookups in the majority of cases, we use the
        // extra info bits in GlobalMethodPool to check whether there were any
        // category methods with this selector.
        GlobalMethodPool::iterator It =
            MethodPool.find(ObjCMethod->getSelector());
        if (It != MethodPool.end()) {
          ObjCMethodList &List =
            ObjCMethod->isInstanceMethod()? It->second.first: It->second.second;
          unsigned CategCount = List.getBits();
          if (CategCount > 0) {
            // If the method is in a category we'll do lookup if there were at
            // least 2 category methods recorded, otherwise only one will do.
            if (CategCount > 1 ||
                !isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) {
              OverrideSearch overrides(SemaRef, overridden);
              for (ObjCMethodDecl *SuperOverridden : overrides) {
                if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) ||
                    !IsMethodInCurrentClass(SuperOverridden)) {
                  CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden);
                  hasOverriddenMethodsInBaseOrProtocol = true;
                  overridden->setOverriding(true);
                  break;
                }
              }
            }
          }
        }
      }
    }

    // Propagate down the 'related result type' bit from overridden methods.
    if (RTC != SemaObjC::RTC_Incompatible && overridden->hasRelatedResultType())
      ObjCMethod->setRelatedResultType();

    // Then merge the declarations.
    SemaRef.mergeObjCMethodDecls(ObjCMethod, overridden);

    if (ObjCMethod->isImplicit() && overridden->isImplicit())
      continue; // Conflicting properties are detected elsewhere.

    // Check for overriding methods
    if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||
        isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext()))
      CheckConflictingOverridingMethod(ObjCMethod, overridden,
              isa<ObjCProtocolDecl>(overridden->getDeclContext()));

    if (CurrentClass && overridden->getDeclContext() != CurrentClass &&
        isa<ObjCInterfaceDecl>(overridden->getDeclContext()) &&
        !overridden->isImplicit() /* not meant for properties */) {
      ObjCMethodDecl::param_iterator ParamI = ObjCMethod->param_begin(),
                                          E = ObjCMethod->param_end();
      ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(),
                                     PrevE = overridden->param_end();
      for (; ParamI != E && PrevI != PrevE; ++ParamI, ++PrevI) {
        assert(PrevI != overridden->param_end() && "Param mismatch");
        QualType T1 = Context.getCanonicalType((*ParamI)->getType());
        QualType T2 = Context.getCanonicalType((*PrevI)->getType());
        // If type of argument of method in this class does not match its
        // respective argument type in the super class method, issue warning;
        if (!Context.typesAreCompatible(T1, T2)) {
          Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)
            << T1 << T2;
          Diag(overridden->getLocation(), diag::note_previous_declaration);
          break;
        }
      }
    }
  }

  ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol);
}

/// Merge type nullability from for a redeclaration of the same entity,
/// producing the updated type of the redeclared entity.
static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,
                                              QualType type,
                                              bool usesCSKeyword,
                                              SourceLocation prevLoc,
                                              QualType prevType,
                                              bool prevUsesCSKeyword) {
  // Determine the nullability of both types.
  auto nullability = type->getNullability();
  auto prevNullability = prevType->getNullability();

  // Easy case: both have nullability.
  if (nullability.has_value() == prevNullability.has_value()) {
    // Neither has nullability; continue.
    if (!nullability)
      return type;

    // The nullabilities are equivalent; do nothing.
    if (*nullability == *prevNullability)
      return type;

    // Complain about mismatched nullability.
    S.Diag(loc, diag::err_nullability_conflicting)
      << DiagNullabilityKind(*nullability, usesCSKeyword)
      << DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);
    return type;
  }

  // If it's the redeclaration that has nullability, don't change anything.
  if (nullability)
    return type;

  // Otherwise, provide the result with the same nullability.
  return S.Context.getAttributedType(*prevNullability, type, type);
}

/// Merge information from the declaration of a method in the \@interface
/// (or a category/extension) into the corresponding method in the
/// @implementation (for a class or category).
static void mergeInterfaceMethodToImpl(Sema &S,
                                       ObjCMethodDecl *method,
                                       ObjCMethodDecl *prevMethod) {
  // Merge the objc_requires_super attribute.
  if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() &&
      !method->hasAttr<ObjCRequiresSuperAttr>()) {
    // merge the attribute into implementation.
    method->addAttr(
      ObjCRequiresSuperAttr::CreateImplicit(S.Context,
                                            method->getLocation()));
  }

  // Merge nullability of the result type.
  QualType newReturnType
    = mergeTypeNullabilityForRedecl(
        S, method->getReturnTypeSourceRange().getBegin(),
        method->getReturnType(),
        method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,
        prevMethod->getReturnTypeSourceRange().getBegin(),
        prevMethod->getReturnType(),
        prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);
  method->setReturnType(newReturnType);

  // Handle each of the parameters.
  unsigned numParams = method->param_size();
  unsigned numPrevParams = prevMethod->param_size();
  for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) {
    ParmVarDecl *param = method->param_begin()[i];
    ParmVarDecl *prevParam = prevMethod->param_begin()[i];

    // Merge nullability.
    QualType newParamType
      = mergeTypeNullabilityForRedecl(
          S, param->getLocation(), param->getType(),
          param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,
          prevParam->getLocation(), prevParam->getType(),
          prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);
    param->setType(newParamType);
  }
}

/// Verify that the method parameters/return value have types that are supported
/// by the x86 target.
static void checkObjCMethodX86VectorTypes(Sema &SemaRef,
                                          const ObjCMethodDecl *Method) {
  assert(SemaRef.getASTContext().getTargetInfo().getTriple().getArch() ==
             llvm::Triple::x86 &&
         "x86-specific check invoked for a different target");
  SourceLocation Loc;
  QualType T;
  for (const ParmVarDecl *P : Method->parameters()) {
    if (P->getType()->isVectorType()) {
      Loc = P->getBeginLoc();
      T = P->getType();
      break;
    }
  }
  if (Loc.isInvalid()) {
    if (Method->getReturnType()->isVectorType()) {
      Loc = Method->getReturnTypeSourceRange().getBegin();
      T = Method->getReturnType();
    } else
      return;
  }

  // Vector parameters/return values are not supported by objc_msgSend on x86 in
  // iOS < 9 and macOS < 10.11.
  const auto &Triple = SemaRef.getASTContext().getTargetInfo().getTriple();
  VersionTuple AcceptedInVersion;
  if (Triple.getOS() == llvm::Triple::IOS)
    AcceptedInVersion = VersionTuple(/*Major=*/9);
  else if (Triple.isMacOSX())
    AcceptedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/11);
  else
    return;
  if (SemaRef.getASTContext().getTargetInfo().getPlatformMinVersion() >=
      AcceptedInVersion)
    return;
  SemaRef.Diag(Loc, diag::err_objc_method_unsupported_param_ret_type)
      << T << (Method->getReturnType()->isVectorType() ? /*return value*/ 1
                                                       : /*parameter*/ 0)
      << (Triple.isMacOSX() ? "macOS 10.11" : "iOS 9");
}

static void mergeObjCDirectMembers(Sema &S, Decl *CD, ObjCMethodDecl *Method) {
  if (!Method->isDirectMethod() && !Method->hasAttr<UnavailableAttr>() &&
      CD->hasAttr<ObjCDirectMembersAttr>()) {
    Method->addAttr(
        ObjCDirectAttr::CreateImplicit(S.Context, Method->getLocation()));
  }
}

static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl,
                                         ObjCMethodDecl *Method,
                                         ObjCImplDecl *ImpDecl = nullptr) {
  auto Sel = Method->getSelector();
  bool isInstance = Method->isInstanceMethod();
  bool diagnosed = false;

  auto diagClash = [&](const ObjCMethodDecl *IMD) {
    if (diagnosed || IMD->isImplicit())
      return;
    if (Method->isDirectMethod() || IMD->isDirectMethod()) {
      S.Diag(Method->getLocation(), diag::err_objc_direct_duplicate_decl)
          << Method->isDirectMethod() << /* method */ 0 << IMD->isDirectMethod()
          << Method->getDeclName();
      S.Diag(IMD->getLocation(), diag::note_previous_declaration);
      diagnosed = true;
    }
  };

  // Look for any other declaration of this method anywhere we can see in this
  // compilation unit.
  //
  // We do not use IDecl->lookupMethod() because we have specific needs:
  //
  // - we absolutely do not need to walk protocols, because
  //   diag::err_objc_direct_on_protocol has already been emitted
  //   during parsing if there's a conflict,
  //
  // - when we do not find a match in a given @interface container,
  //   we need to attempt looking it up in the @implementation block if the
  //   translation unit sees it to find more clashes.

  if (auto *IMD = IDecl->getMethod(Sel, isInstance))
    diagClash(IMD);
  else if (auto *Impl = IDecl->getImplementation())
    if (Impl != ImpDecl)
      if (auto *IMD = IDecl->getImplementation()->getMethod(Sel, isInstance))
        diagClash(IMD);

  for (const auto *Cat : IDecl->visible_categories())
    if (auto *IMD = Cat->getMethod(Sel, isInstance))
      diagClash(IMD);
    else if (auto CatImpl = Cat->getImplementation())
      if (CatImpl != ImpDecl)
        if (auto *IMD = Cat->getMethod(Sel, isInstance))
          diagClash(IMD);
}

ParmVarDecl *SemaObjC::ActOnMethodParmDeclaration(Scope *S,
                                                  ObjCArgInfo &ArgInfo,
                                                  int ParamIndex,
                                                  bool MethodDefinition) {
  ASTContext &Context = getASTContext();
  QualType ArgType;
  TypeSourceInfo *DI;

  if (!ArgInfo.Type) {
    ArgType = Context.getObjCIdType();
    DI = nullptr;
  } else {
    ArgType = SemaRef.GetTypeFromParser(ArgInfo.Type, &DI);
  }
  LookupResult R(SemaRef, ArgInfo.Name, ArgInfo.NameLoc,
                 Sema::LookupOrdinaryName,
                 SemaRef.forRedeclarationInCurContext());
  SemaRef.LookupName(R, S);
  if (R.isSingleResult()) {
    NamedDecl *PrevDecl = R.getFoundDecl();
    if (S->isDeclScope(PrevDecl)) {
      Diag(ArgInfo.NameLoc,
           (MethodDefinition ? diag::warn_method_param_redefinition
                             : diag::warn_method_param_declaration))
          << ArgInfo.Name;
      Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
    }
  }
  SourceLocation StartLoc =
      DI ? DI->getTypeLoc().getBeginLoc() : ArgInfo.NameLoc;

  // Temporarily put parameter variables in the translation unit. This is what
  // ActOnParamDeclarator does in the case of C arguments to the Objective-C
  // method too.
  ParmVarDecl *Param = SemaRef.CheckParameter(
      Context.getTranslationUnitDecl(), StartLoc, ArgInfo.NameLoc, ArgInfo.Name,
      ArgType, DI, SC_None);
  Param->setObjCMethodScopeInfo(ParamIndex);
  Param->setObjCDeclQualifier(
      CvtQTToAstBitMask(ArgInfo.DeclSpec.getObjCDeclQualifier()));

  // Apply the attributes to the parameter.
  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, ArgInfo.ArgAttrs);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);
  if (Param->hasAttr<BlocksAttr>()) {
    Diag(Param->getLocation(), diag::err_block_on_nonlocal);
    Param->setInvalidDecl();
  }

  S->AddDecl(Param);
  SemaRef.IdResolver.AddDecl(Param);
  return Param;
}

Decl *SemaObjC::ActOnMethodDeclaration(
    Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,
    tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,
    ArrayRef<SourceLocation> SelectorLocs, Selector Sel,
    // optional arguments. The number of types/arguments is obtained
    // from the Sel.getNumArgs().
    ParmVarDecl **ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,
    unsigned CNumArgs, // c-style args
    const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,
    bool isVariadic, bool MethodDefinition) {
  ASTContext &Context = getASTContext();
  // Make sure we can establish a context for the method.
  if (!SemaRef.CurContext->isObjCContainer()) {
    Diag(MethodLoc, diag::err_missing_method_context);
    return nullptr;
  }

  Decl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext);
  QualType resultDeclType;

  bool HasRelatedResultType = false;
  TypeSourceInfo *ReturnTInfo = nullptr;
  if (ReturnType) {
    resultDeclType = SemaRef.GetTypeFromParser(ReturnType, &ReturnTInfo);

    if (SemaRef.CheckFunctionReturnType(resultDeclType, MethodLoc))
      return nullptr;

    QualType bareResultType = resultDeclType;
    (void)AttributedType::stripOuterNullability(bareResultType);
    HasRelatedResultType = (bareResultType == Context.getObjCInstanceType());
  } else { // get the type for "id".
    resultDeclType = Context.getObjCIdType();
    Diag(MethodLoc, diag::warn_missing_method_return_type)
      << FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");
  }

  ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(
      Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo,
      SemaRef.CurContext, MethodType == tok::minus, isVariadic,
      /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,
      /*isImplicitlyDeclared=*/false, /*isDefined=*/false,
      MethodDeclKind == tok::objc_optional
          ? ObjCImplementationControl::Optional
          : ObjCImplementationControl::Required,
      HasRelatedResultType);

  SmallVector<ParmVarDecl*, 16> Params;
  for (unsigned I = 0; I < Sel.getNumArgs(); ++I) {
    ParmVarDecl *Param = ArgInfo[I];
    Param->setDeclContext(ObjCMethod);
    SemaRef.ProcessAPINotes(Param);
    Params.push_back(Param);
  }

  for (unsigned i = 0, e = CNumArgs; i != e; ++i) {
    ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);
    QualType ArgType = Param->getType();
    if (ArgType.isNull())
      ArgType = Context.getObjCIdType();
    else
      // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).
      ArgType = Context.getAdjustedParameterType(ArgType);

    Param->setDeclContext(ObjCMethod);
    Params.push_back(Param);
  }

  ObjCMethod->setMethodParams(Context, Params, SelectorLocs);
  ObjCMethod->setObjCDeclQualifier(
    CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));

  SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, ObjCMethod, AttrList);
  SemaRef.AddPragmaAttributes(SemaRef.TUScope, ObjCMethod);
  SemaRef.ProcessAPINotes(ObjCMethod);

  // Add the method now.
  const ObjCMethodDecl *PrevMethod = nullptr;
  if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {
    if (MethodType == tok::minus) {
      PrevMethod = ImpDecl->getInstanceMethod(Sel);
      ImpDecl->addInstanceMethod(ObjCMethod);
    } else {
      PrevMethod = ImpDecl->getClassMethod(Sel);
      ImpDecl->addClassMethod(ObjCMethod);
    }

    // If this method overrides a previous @synthesize declaration,
    // register it with the property.  Linear search through all
    // properties here, because the autosynthesized stub hasn't been
    // made visible yet, so it can be overridden by a later
    // user-specified implementation.
    for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) {
      if (auto *Setter = PropertyImpl->getSetterMethodDecl())
        if (Setter->getSelector() == Sel &&
            Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {
          assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected");
          PropertyImpl->setSetterMethodDecl(ObjCMethod);
        }
      if (auto *Getter = PropertyImpl->getGetterMethodDecl())
        if (Getter->getSelector() == Sel &&
            Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {
          assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected");
          PropertyImpl->setGetterMethodDecl(ObjCMethod);
          break;
        }
    }

    // A method is either tagged direct explicitly, or inherits it from its
    // canonical declaration.
    //
    // We have to do the merge upfront and not in mergeInterfaceMethodToImpl()
    // because IDecl->lookupMethod() returns more possible matches than just
    // the canonical declaration.
    if (!ObjCMethod->isDirectMethod()) {
      const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl();
      if (CanonicalMD->isDirectMethod()) {
        const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>();
        ObjCMethod->addAttr(
            ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));
      }
    }

    // Merge information from the @interface declaration into the
    // @implementation.
    if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {
      if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),
                                          ObjCMethod->isInstanceMethod())) {
        mergeInterfaceMethodToImpl(SemaRef, ObjCMethod, IMD);

        // The Idecl->lookupMethod() above will find declarations for ObjCMethod
        // in one of these places:
        //
        // (1) the canonical declaration in an @interface container paired
        //     with the ImplDecl,
        // (2) non canonical declarations in @interface not paired with the
        //     ImplDecl for the same Class,
        // (3) any superclass container.
        //
        // Direct methods only allow for canonical declarations in the matching
        // container (case 1).
        //
        // Direct methods overriding a superclass declaration (case 3) is
        // handled during overrides checks in CheckObjCMethodOverrides().
        //
        // We deal with same-class container mismatches (Case 2) here.
        if (IDecl == IMD->getClassInterface()) {
          auto diagContainerMismatch = [&] {
            int decl = 0, impl = 0;

            if (auto *Cat = dyn_cast<ObjCCategoryDecl>(IMD->getDeclContext()))
              decl = Cat->IsClassExtension() ? 1 : 2;

            if (isa<ObjCCategoryImplDecl>(ImpDecl))
              impl = 1 + (decl != 0);

            Diag(ObjCMethod->getLocation(),
                 diag::err_objc_direct_impl_decl_mismatch)
                << decl << impl;
            Diag(IMD->getLocation(), diag::note_previous_declaration);
          };

          if (ObjCMethod->isDirectMethod()) {
            const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>();
            if (ObjCMethod->getCanonicalDecl() != IMD) {
              diagContainerMismatch();
            } else if (!IMD->isDirectMethod()) {
              Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl);
              Diag(IMD->getLocation(), diag::note_previous_declaration);
            }
          } else if (IMD->isDirectMethod()) {
            const auto *attr = IMD->getAttr<ObjCDirectAttr>();
            if (ObjCMethod->getCanonicalDecl() != IMD) {
              diagContainerMismatch();
            } else {
              ObjCMethod->addAttr(
                  ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));
            }
          }
        }

        // Warn about defining -dealloc in a category.
        if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() &&
            ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) {
          Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)
            << ObjCMethod->getDeclName();
        }
      } else {
        mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);
        checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod, ImpDecl);
      }

      // Warn if a method declared in a protocol to which a category or
      // extension conforms is non-escaping and the implementation's method is
      // escaping.
      for (auto *C : IDecl->visible_categories())
        for (auto &P : C->protocols())
          if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(),
                                          ObjCMethod->isInstanceMethod())) {
            assert(ObjCMethod->parameters().size() ==
                       IMD->parameters().size() &&
                   "Methods have different number of parameters");
            auto OI = IMD->param_begin(), OE = IMD->param_end();
            auto NI = ObjCMethod->param_begin();
            for (; OI != OE; ++OI, ++NI)
              diagnoseNoescape(*NI, *OI, C, P, SemaRef);
          }
    }
  } else {
    if (!isa<ObjCProtocolDecl>(ClassDecl)) {
      mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);

      ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
      if (!IDecl)
        IDecl = cast<ObjCCategoryDecl>(ClassDecl)->getClassInterface();
      // For valid code, we should always know the primary interface
      // declaration by now, however for invalid code we'll keep parsing
      // but we won't find the primary interface and IDecl will be nil.
      if (IDecl)
        checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod);
    }

    cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);
  }

  if (PrevMethod) {
    // You can never have two method definitions with the same name.
    Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)
      << ObjCMethod->getDeclName();
    Diag(PrevMethod->getLocation(), diag::note_previous_declaration);
    ObjCMethod->setInvalidDecl();
    return ObjCMethod;
  }

  // If this Objective-C method does not have a related result type, but we
  // are allowed to infer related result types, try to do so based on the
  // method family.
  ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl);
  if (!CurrentClass) {
    if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl))
      CurrentClass = Cat->getClassInterface();
    else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl))
      CurrentClass = Impl->getClassInterface();
    else if (ObjCCategoryImplDecl *CatImpl
                                   = dyn_cast<ObjCCategoryImplDecl>(ClassDecl))
      CurrentClass = CatImpl->getClassInterface();
  }

  ResultTypeCompatibilityKind RTC =
      CheckRelatedResultTypeCompatibility(SemaRef, ObjCMethod, CurrentClass);

  CheckObjCMethodOverrides(ObjCMethod, CurrentClass, RTC);

  bool ARCError = false;
  if (getLangOpts().ObjCAutoRefCount)
    ARCError = CheckARCMethodDecl(ObjCMethod);

  // Infer the related result type when possible.
  if (!ARCError && RTC == SemaObjC::RTC_Compatible &&
      !ObjCMethod->hasRelatedResultType() &&
      getLangOpts().ObjCInferRelatedResultType) {
    bool InferRelatedResultType = false;
    switch (ObjCMethod->getMethodFamily()) {
    case OMF_None:
    case OMF_copy:
    case OMF_dealloc:
    case OMF_finalize:
    case OMF_mutableCopy:
    case OMF_release:
    case OMF_retainCount:
    case OMF_initialize:
    case OMF_performSelector:
      break;

    case OMF_alloc:
    case OMF_new:
        InferRelatedResultType = ObjCMethod->isClassMethod();
      break;

    case OMF_init:
    case OMF_autorelease:
    case OMF_retain:
    case OMF_self:
      InferRelatedResultType = ObjCMethod->isInstanceMethod();
      break;
    }

    if (InferRelatedResultType &&
        !ObjCMethod->getReturnType()->isObjCIndependentClassType())
      ObjCMethod->setRelatedResultType();
  }

  if (MethodDefinition &&
      Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)
    checkObjCMethodX86VectorTypes(SemaRef, ObjCMethod);

  // + load method cannot have availability attributes. It get called on
  // startup, so it has to have the availability of the deployment target.
  if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) {
    if (ObjCMethod->isClassMethod() &&
        ObjCMethod->getSelector().getAsString() == "load") {
      Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)
          << 0;
      ObjCMethod->dropAttr<AvailabilityAttr>();
    }
  }

  // Insert the invisible arguments, self and _cmd!
  ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface());

  SemaRef.ActOnDocumentableDecl(ObjCMethod);

  return ObjCMethod;
}

bool SemaObjC::CheckObjCDeclScope(Decl *D) {
  // Following is also an error. But it is caused by a missing @end
  // and diagnostic is issued elsewhere.
  if (isa<ObjCContainerDecl>(SemaRef.CurContext->getRedeclContext()))
    return false;

  // If we switched context to translation unit while we are still lexically in
  // an objc container, it means the parser missed emitting an error.
  if (isa<TranslationUnitDecl>(
          SemaRef.getCurLexicalContext()->getRedeclContext()))
    return false;

  Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);
  D->setInvalidDecl();

  return true;
}

/// Called whenever \@defs(ClassName) is encountered in the source.  Inserts the
/// instance variables of ClassName into Decls.
void SemaObjC::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,
                         const IdentifierInfo *ClassName,
                         SmallVectorImpl<Decl *> &Decls) {
  ASTContext &Context = getASTContext();
  // Check that ClassName is a valid class
  ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);
  if (!Class) {
    Diag(DeclStart, diag::err_undef_interface) << ClassName;
    return;
  }
  if (getLangOpts().ObjCRuntime.isNonFragile()) {
    Diag(DeclStart, diag::err_atdef_nonfragile_interface);
    return;
  }

  // Collect the instance variables
  SmallVector<const ObjCIvarDecl*, 32> Ivars;
  Context.DeepCollectObjCIvars(Class, true, Ivars);
  // For each ivar, create a fresh ObjCAtDefsFieldDecl.
  for (unsigned i = 0; i < Ivars.size(); i++) {
    const FieldDecl* ID = Ivars[i];
    RecordDecl *Record = dyn_cast<RecordDecl>(TagD);
    Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,
                                           /*FIXME: StartL=*/ID->getLocation(),
                                           ID->getLocation(),
                                           ID->getIdentifier(), ID->getType(),
                                           ID->getBitWidth());
    Decls.push_back(FD);
  }

  // Introduce all of these fields into the appropriate scope.
  for (SmallVectorImpl<Decl*>::iterator D = Decls.begin();
       D != Decls.end(); ++D) {
    FieldDecl *FD = cast<FieldDecl>(*D);
    if (getLangOpts().CPlusPlus)
      SemaRef.PushOnScopeChains(FD, S);
    else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))
      Record->addDecl(FD);
  }
}

/// Build a type-check a new Objective-C exception variable declaration.
VarDecl *SemaObjC::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,
                                          SourceLocation StartLoc,
                                          SourceLocation IdLoc,
                                          const IdentifierInfo *Id,
                                          bool Invalid) {
  ASTContext &Context = getASTContext();
  // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage
  // duration shall not be qualified by an address-space qualifier."
  // Since all parameters have automatic store duration, they can not have
  // an address space.
  if (T.getAddressSpace() != LangAS::Default) {
    Diag(IdLoc, diag::err_arg_with_address_space);
    Invalid = true;
  }

  // An @catch parameter must be an unqualified object pointer type;
  // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?
  if (Invalid) {
    // Don't do any further checking.
  } else if (T->isDependentType()) {
    // Okay: we don't know what this type will instantiate to.
  } else if (T->isObjCQualifiedIdType()) {
    Invalid = true;
    Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);
  } else if (T->isObjCIdType()) {
    // Okay: we don't know what this type will instantiate to.
  } else if (!T->isObjCObjectPointerType()) {
    Invalid = true;
    Diag(IdLoc, diag::err_catch_param_not_objc_type);
  } else if (!T->castAs<ObjCObjectPointerType>()->getInterfaceType()) {
    Invalid = true;
    Diag(IdLoc, diag::err_catch_param_not_objc_type);
  }

  VarDecl *New = VarDecl::Create(Context, SemaRef.CurContext, StartLoc, IdLoc,
                                 Id, T, TInfo, SC_None);
  New->setExceptionVariable(true);

  // In ARC, infer 'retaining' for variables of retainable type.
  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New))
    Invalid = true;

  if (Invalid)
    New->setInvalidDecl();
  return New;
}

Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {
  const DeclSpec &DS = D.getDeclSpec();

  // We allow the "register" storage class on exception variables because
  // GCC did, but we drop it completely. Any other storage class is an error.
  if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
    Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)
      << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));
  } else if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) {
    Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)
      << DeclSpec::getSpecifierName(SCS);
  }
  if (DS.isInlineSpecified())
    Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)
        << getLangOpts().CPlusPlus17;
  if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())
    Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
         diag::err_invalid_thread)
     << DeclSpec::getSpecifierName(TSCS);
  D.getMutableDeclSpec().ClearStorageClassSpecs();

  SemaRef.DiagnoseFunctionSpecifiers(D.getDeclSpec());

  // Check that there are no default arguments inside the type of this
  // exception object (C++ only).
  if (getLangOpts().CPlusPlus)
    SemaRef.CheckExtraCXXDefaultArguments(D);

  TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
  QualType ExceptionType = TInfo->getType();

  VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType,
                                        D.getSourceRange().getBegin(),
                                        D.getIdentifierLoc(),
                                        D.getIdentifier(),
                                        D.isInvalidType());

  // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).
  if (D.getCXXScopeSpec().isSet()) {
    Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)
      << D.getCXXScopeSpec().getRange();
    New->setInvalidDecl();
  }

  // Add the parameter declaration into this scope.
  S->AddDecl(New);
  if (D.getIdentifier())
    SemaRef.IdResolver.AddDecl(New);

  SemaRef.ProcessDeclAttributes(S, New, D);

  if (New->hasAttr<BlocksAttr>())
    Diag(New->getLocation(), diag::err_block_on_nonlocal);
  return New;
}

/// CollectIvarsToConstructOrDestruct - Collect those ivars which require
/// initialization.
void SemaObjC::CollectIvarsToConstructOrDestruct(
    ObjCInterfaceDecl *OI, SmallVectorImpl<ObjCIvarDecl *> &Ivars) {
  ASTContext &Context = getASTContext();
  for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;
       Iv= Iv->getNextIvar()) {
    QualType QT = Context.getBaseElementType(Iv->getType());
    if (QT->isRecordType())
      Ivars.push_back(Iv);
  }
}

void SemaObjC::DiagnoseUseOfUnimplementedSelectors() {
  ASTContext &Context = getASTContext();
  // Load referenced selectors from the external source.
  if (SemaRef.ExternalSource) {
    SmallVector<std::pair<Selector, SourceLocation>, 4> Sels;
    SemaRef.ExternalSource->ReadReferencedSelectors(Sels);
    for (unsigned I = 0, N = Sels.size(); I != N; ++I)
      ReferencedSelectors[Sels[I].first] = Sels[I].second;
  }

  // Warning will be issued only when selector table is
  // generated (which means there is at lease one implementation
  // in the TU). This is to match gcc's behavior.
  if (ReferencedSelectors.empty() ||
      !Context.AnyObjCImplementation())
    return;
  for (auto &SelectorAndLocation : ReferencedSelectors) {
    Selector Sel = SelectorAndLocation.first;
    SourceLocation Loc = SelectorAndLocation.second;
    if (!LookupImplementedMethodInGlobalPool(Sel))
      Diag(Loc, diag::warn_unimplemented_selector) << Sel;
  }
}

ObjCIvarDecl *
SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,
                                         const ObjCPropertyDecl *&PDecl) const {
  if (Method->isClassMethod())
    return nullptr;
  const ObjCInterfaceDecl *IDecl = Method->getClassInterface();
  if (!IDecl)
    return nullptr;
  Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,
                               /*shallowCategoryLookup=*/false,
                               /*followSuper=*/false);
  if (!Method || !Method->isPropertyAccessor())
    return nullptr;
  if ((PDecl = Method->findPropertyDecl()))
    if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {
      // property backing ivar must belong to property's class
      // or be a private ivar in class's implementation.
      // FIXME. fix the const-ness issue.
      IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable(
                                                        IV->getIdentifier());
      return IV;
    }
  return nullptr;
}

namespace {
/// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property
/// accessor references the backing ivar.
class UnusedBackingIvarChecker : public DynamicRecursiveASTVisitor {
public:
  Sema &S;
  const ObjCMethodDecl *Method;
  const ObjCIvarDecl *IvarD;
  bool AccessedIvar;
  bool InvokedSelfMethod;

  UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method,
                           const ObjCIvarDecl *IvarD)
      : S(S), Method(Method), IvarD(IvarD), AccessedIvar(false),
        InvokedSelfMethod(false) {
    assert(IvarD);
  }

  bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override {
    if (E->getDecl() == IvarD) {
      AccessedIvar = true;
      return false;
    }
    return true;
  }

  bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {
    if (E->getReceiverKind() == ObjCMessageExpr::Instance &&
        S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) {
      InvokedSelfMethod = true;
    }
    return true;
  }
};
} // end anonymous namespace

void SemaObjC::DiagnoseUnusedBackingIvarInAccessor(
    Scope *S, const ObjCImplementationDecl *ImplD) {
  if (S->hasUnrecoverableErrorOccurred())
    return;

  for (const auto *CurMethod : ImplD->instance_methods()) {
    unsigned DIAG = diag::warn_unused_property_backing_ivar;
    SourceLocation Loc = CurMethod->getLocation();
    if (getDiagnostics().isIgnored(DIAG, Loc))
      continue;

    const ObjCPropertyDecl *PDecl;
    const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);
    if (!IV)
      continue;

    if (CurMethod->isSynthesizedAccessorStub())
      continue;

    UnusedBackingIvarChecker Checker(SemaRef, CurMethod, IV);
    Checker.TraverseStmt(CurMethod->getBody());
    if (Checker.AccessedIvar)
      continue;

    // Do not issue this warning if backing ivar is used somewhere and accessor
    // implementation makes a self call. This is to prevent false positive in
    // cases where the ivar is accessed by another method that the accessor
    // delegates to.
    if (!IV->isReferenced() || !Checker.InvokedSelfMethod) {
      Diag(Loc, DIAG) << IV;
      Diag(PDecl->getLocation(), diag::note_property_declare);
    }
  }
}

QualType SemaObjC::AdjustParameterTypeForObjCAutoRefCount(
    QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo) {
  ASTContext &Context = getASTContext();
  // In ARC, infer a lifetime qualifier for appropriate parameter types.
  if (!getLangOpts().ObjCAutoRefCount ||
      T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType())
    return T;

  Qualifiers::ObjCLifetime Lifetime;

  // Special cases for arrays:
  //   - if it's const, use __unsafe_unretained
  //   - otherwise, it's an error
  if (T->isArrayType()) {
    if (!T.isConstQualified()) {
      if (SemaRef.DelayedDiagnostics.shouldDelayDiagnostics())
        SemaRef.DelayedDiagnostics.add(
            sema::DelayedDiagnostic::makeForbiddenType(
                NameLoc, diag::err_arc_array_param_no_ownership, T, false));
      else
        Diag(NameLoc, diag::err_arc_array_param_no_ownership)
            << TSInfo->getTypeLoc().getSourceRange();
    }
    Lifetime = Qualifiers::OCL_ExplicitNone;
  } else {
    Lifetime = T->getObjCARCImplicitLifetime();
  }
  T = Context.getLifetimeQualifiedType(T, Lifetime);

  return T;
}

ObjCInterfaceDecl *SemaObjC::getObjCInterfaceDecl(const IdentifierInfo *&Id,
                                                  SourceLocation IdLoc,
                                                  bool DoTypoCorrection) {
  // The third "scope" argument is 0 since we aren't enabling lazy built-in
  // creation from this context.
  NamedDecl *IDecl = SemaRef.LookupSingleName(SemaRef.TUScope, Id, IdLoc,
                                              Sema::LookupOrdinaryName);

  if (!IDecl && DoTypoCorrection) {
    // Perform typo correction at the given location, but only if we
    // find an Objective-C class name.
    DeclFilterCCC<ObjCInterfaceDecl> CCC{};
    if (TypoCorrection C = SemaRef.CorrectTypo(
            DeclarationNameInfo(Id, IdLoc), Sema::LookupOrdinaryName,
            SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::ErrorRecovery)) {
      SemaRef.diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);
      IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();
      Id = IDecl->getIdentifier();
    }
  }
  ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
  // This routine must always return a class definition, if any.
  if (Def && Def->getDefinition())
    Def = Def->getDefinition();
  return Def;
}

bool SemaObjC::inferObjCARCLifetime(ValueDecl *decl) {
  ASTContext &Context = getASTContext();
  QualType type = decl->getType();
  Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();
  if (lifetime == Qualifiers::OCL_Autoreleasing) {
    // Various kinds of declaration aren't allowed to be __autoreleasing.
    unsigned kind = -1U;
    if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
      if (var->hasAttr<BlocksAttr>())
        kind = 0; // __block
      else if (!var->hasLocalStorage())
        kind = 1; // global
    } else if (isa<ObjCIvarDecl>(decl)) {
      kind = 3; // ivar
    } else if (isa<FieldDecl>(decl)) {
      kind = 2; // field
    }

    if (kind != -1U) {
      Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind;
    }
  } else if (lifetime == Qualifiers::OCL_None) {
    // Try to infer lifetime.
    if (!type->isObjCLifetimeType())
      return false;

    lifetime = type->getObjCARCImplicitLifetime();
    type = Context.getLifetimeQualifiedType(type, lifetime);
    decl->setType(type);
  }

  if (VarDecl *var = dyn_cast<VarDecl>(decl)) {
    // Thread-local variables cannot have lifetime.
    if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&
        var->getTLSKind()) {
      Diag(var->getLocation(), diag::err_arc_thread_ownership)
          << var->getType();
      return true;
    }
  }

  return false;
}

ObjCContainerDecl *SemaObjC::getObjCDeclContext() const {
  return (dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext));
}

void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {
  if (!getLangOpts().CPlusPlus)
    return;
  if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {
    ASTContext &Context = getASTContext();
    SmallVector<ObjCIvarDecl *, 8> ivars;
    CollectIvarsToConstructOrDestruct(OID, ivars);
    if (ivars.empty())
      return;
    SmallVector<CXXCtorInitializer *, 32> AllToInit;
    for (unsigned i = 0; i < ivars.size(); i++) {
      FieldDecl *Field = ivars[i];
      if (Field->isInvalidDecl())
        continue;

      CXXCtorInitializer *Member;
      InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);
      InitializationKind InitKind =
          InitializationKind::CreateDefault(ObjCImplementation->getLocation());

      InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, {});
      ExprResult MemberInit =
          InitSeq.Perform(SemaRef, InitEntity, InitKind, {});
      MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);
      // Note, MemberInit could actually come back empty if no initialization
      // is required (e.g., because it would call a trivial default constructor)
      if (!MemberInit.get() || MemberInit.isInvalid())
        continue;

      Member = new (Context)
          CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(),
                             MemberInit.getAs<Expr>(), SourceLocation());
      AllToInit.push_back(Member);

      // Be sure that the destructor is accessible and is marked as referenced.
      if (auto *RD = Context.getBaseElementType(Field->getType())
                         ->getAsCXXRecordDecl()) {
        if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) {
          SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor);
          SemaRef.CheckDestructorAccess(
              Field->getLocation(), Destructor,
              PDiag(diag::err_access_dtor_ivar)
                  << Context.getBaseElementType(Field->getType()));
        }
      }
    }
    ObjCImplementation->setIvarInitializers(Context, AllToInit.data(),
                                            AllToInit.size());
  }
}

/// TranslateIvarVisibility - Translate visibility from a token ID to an
///  AST enum value.
static ObjCIvarDecl::AccessControl
TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {
  switch (ivarVisibility) {
  default:
    llvm_unreachable("Unknown visitibility kind");
  case tok::objc_private:
    return ObjCIvarDecl::Private;
  case tok::objc_public:
    return ObjCIvarDecl::Public;
  case tok::objc_protected:
    return ObjCIvarDecl::Protected;
  case tok::objc_package:
    return ObjCIvarDecl::Package;
  }
}

/// ActOnIvar - Each ivar field of an objective-c class is passed into this
/// in order to create an IvarDecl object for it.
Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D,
                          Expr *BitWidth, tok::ObjCKeywordKind Visibility) {

  const IdentifierInfo *II = D.getIdentifier();
  SourceLocation Loc = DeclStart;
  if (II)
    Loc = D.getIdentifierLoc();

  // FIXME: Unnamed fields can be handled in various different ways, for
  // example, unnamed unions inject all members into the struct namespace!

  TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);
  QualType T = TInfo->getType();
  ASTContext &Context = getASTContext();
  if (Context.getLangOpts().PointerAuthObjcInterfaceSel &&
      !T.getPointerAuth()) {
    if (Context.isObjCSelType(T.getUnqualifiedType())) {
      if (auto PAQ = Context.getObjCMemberSelTypePtrAuth())
        T = Context.getPointerAuthType(T, PAQ);
    }
  }

  if (BitWidth) {
    // 6.7.2.1p3, 6.7.2.1p4
    BitWidth =
        SemaRef.VerifyBitField(Loc, II, T, /*IsMsStruct*/ false, BitWidth)
            .get();
    if (!BitWidth)
      D.setInvalidType();
  } else {
    // Not a bitfield.

    // validate II.
  }
  if (T->isReferenceType()) {
    Diag(Loc, diag::err_ivar_reference_type);
    D.setInvalidType();
  }
  // C99 6.7.2.1p8: A member of a structure or union may have any type other
  // than a variably modified type.
  else if (T->isVariablyModifiedType()) {
    if (!SemaRef.tryToFixVariablyModifiedVarType(
            TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))
      D.setInvalidType();
  }

  // Get the visibility (access control) for this ivar.
  ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword
                                       ? TranslateIvarVisibility(Visibility)
                                       : ObjCIvarDecl::None;
  // Must set ivar's DeclContext to its enclosing interface.
  ObjCContainerDecl *EnclosingDecl =
      cast<ObjCContainerDecl>(SemaRef.CurContext);
  if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())
    return nullptr;
  ObjCContainerDecl *EnclosingContext;
  if (ObjCImplementationDecl *IMPDecl =
          dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {
    if (getLangOpts().ObjCRuntime.isFragile()) {
      // Case of ivar declared in an implementation. Context is that of its
      // class.
      EnclosingContext = IMPDecl->getClassInterface();
      assert(EnclosingContext && "Implementation has no class interface!");
    } else
      EnclosingContext = EnclosingDecl;
  } else {
    if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {
      if (getLangOpts().ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {
        Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();
        return nullptr;
      }
    }
    EnclosingContext = EnclosingDecl;
  }

  // Construct the decl.
  ObjCIvarDecl *NewID =
      ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc,
                           II, T, TInfo, ac, BitWidth);

  if (T->containsErrors())
    NewID->setInvalidDecl();

  if (II) {
    NamedDecl *PrevDecl =
        SemaRef.LookupSingleName(S, II, Loc, Sema::LookupMemberName,
                                 RedeclarationKind::ForVisibleRedeclaration);
    if (PrevDecl && SemaRef.isDeclInScope(PrevDecl, EnclosingContext, S) &&
        !isa<TagDecl>(PrevDecl)) {
      Diag(Loc, diag::err_duplicate_member) << II;
      Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
      NewID->setInvalidDecl();
    }
  }

  // Process attributes attached to the ivar.
  SemaRef.ProcessDeclAttributes(S, NewID, D);

  if (D.isInvalidType())
    NewID->setInvalidDecl();

  // In ARC, infer 'retaining' for ivars of retainable type.
  if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID))
    NewID->setInvalidDecl();

  if (D.getDeclSpec().isModulePrivateSpecified())
    NewID->setModulePrivate();

  if (II) {
    // FIXME: When interfaces are DeclContexts, we'll need to add
    // these to the interface.
    S->AddDecl(NewID);
    SemaRef.IdResolver.AddDecl(NewID);
  }

  if (getLangOpts().ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() &&
      isa<ObjCInterfaceDecl>(EnclosingDecl))
    Diag(Loc, diag::warn_ivars_in_interface);

  return NewID;
}
