//===--- 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, Sema::CTK_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(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());
  }
}

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<IdentifierLocPair> ProtocolId,
                                       SmallVectorImpl<Decl *> &Protocols) {
  for (const IdentifierLocPair &Pair : ProtocolId) {
    ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);
    if (!PDecl) {
      DeclFilterCCC<ObjCProtocolDecl> CCC{};
      TypoCorrection Corrected =
          SemaRef.CorrectTypo(DeclarationNameInfo(Pair.first, Pair.second),
                              Sema::LookupObjCProtocolName, SemaRef.TUScope,
                              nullptr, CCC, Sema::CTK_ErrorRecovery);
      if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))
        SemaRef.diagnoseTypo(Corrected,
                             PDiag(diag::err_undeclared_protocol_suggest)
                                 << Pair.first);
    }

    if (!PDecl) {
      Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first;
      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.second);
    }

    // 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.second, diag::warn_undef_protocolref) << Pair.first;
      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.
        auto type = Context.getTypeDeclType(typeDecl);
        if (type->isObjCObjectPointerType() ||
            type->isBlockPointerType() ||
            type->isDependentType() ||
            type->isObjCObjectType())
          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 = typeDecl.dyn_cast<TypeDecl *>())
      type = Context.getTypeDeclType(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, Sema::CTK_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<IdentifierLocPair> IdentList,
    const ParsedAttributesView &attrList) {
  ASTContext &Context = getASTContext();
  SmallVector<Decl *, 8> DeclsInGroup;
  for (const IdentifierLocPair &IdentPair : IdentList) {
    IdentifierInfo *Ident = IdentPair.first;
    ObjCProtocolDecl *PrevDecl = LookupProtocol(
        Ident, IdentPair.second, SemaRef.forRedeclarationInCurContext());
    ObjCProtocolDecl *PDecl =
        ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident,
                                 IdentPair.second, 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, Sema::CTK_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);

  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)->getDecl();
  RecordDecl *right = cast<RecordType>(rt)->getDecl();

  // 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;
  SmallVector<ObjCMethodDecl *, 4> Methods;
  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 *RecordTy = T->getAs<RecordType>();
  return (RecordTy && RecordTy->getDecl()->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
          << llvm::to_underlying(TagTypeKind::Class); // Use "class" for Obj-C.
      IsInvalidIvar = true;
    } else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) {
      if (RecordTy->getDecl()->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, Sema::CTK_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 (const RecordType *RecordTy =
              Context.getBaseElementType(Field->getType())
                  ->getAs<RecordType>()) {
        CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
        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();

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