Path: blob/main/contrib/llvm-project/clang/lib/Sema/SemaDeclObjC.cpp
35233 views
//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements semantic analysis for Objective C declarations.9//10//===----------------------------------------------------------------------===//1112#include "TypeLocBuilder.h"13#include "clang/AST/ASTConsumer.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/ASTMutationListener.h"16#include "clang/AST/DeclObjC.h"17#include "clang/AST/Expr.h"18#include "clang/AST/ExprObjC.h"19#include "clang/AST/RecursiveASTVisitor.h"20#include "clang/Basic/SourceManager.h"21#include "clang/Basic/TargetInfo.h"22#include "clang/Sema/DeclSpec.h"23#include "clang/Sema/DelayedDiagnostic.h"24#include "clang/Sema/Initialization.h"25#include "clang/Sema/Lookup.h"26#include "clang/Sema/Scope.h"27#include "clang/Sema/ScopeInfo.h"28#include "clang/Sema/SemaInternal.h"29#include "clang/Sema/SemaObjC.h"30#include "llvm/ADT/DenseMap.h"31#include "llvm/ADT/DenseSet.h"3233using namespace clang;3435/// Check whether the given method, which must be in the 'init'36/// family, is a valid member of that family.37///38/// \param receiverTypeIfCall - if null, check this as if declaring it;39/// if non-null, check this as if making a call to it with the given40/// receiver type41///42/// \return true to indicate that there was an error and appropriate43/// actions were taken44bool SemaObjC::checkInitMethod(ObjCMethodDecl *method,45QualType receiverTypeIfCall) {46ASTContext &Context = getASTContext();47if (method->isInvalidDecl()) return true;4849// This castAs is safe: methods that don't return an object50// pointer won't be inferred as inits and will reject an explicit51// objc_method_family(init).5253// We ignore protocols here. Should we? What about Class?5455const ObjCObjectType *result =56method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType();5758if (result->isObjCId()) {59return false;60} else if (result->isObjCClass()) {61// fall through: always an error62} else {63ObjCInterfaceDecl *resultClass = result->getInterface();64assert(resultClass && "unexpected object type!");6566// It's okay for the result type to still be a forward declaration67// if we're checking an interface declaration.68if (!resultClass->hasDefinition()) {69if (receiverTypeIfCall.isNull() &&70!isa<ObjCImplementationDecl>(method->getDeclContext()))71return false;7273// Otherwise, we try to compare class types.74} else {75// If this method was declared in a protocol, we can't check76// anything unless we have a receiver type that's an interface.77const ObjCInterfaceDecl *receiverClass = nullptr;78if (isa<ObjCProtocolDecl>(method->getDeclContext())) {79if (receiverTypeIfCall.isNull())80return false;8182receiverClass = receiverTypeIfCall->castAs<ObjCObjectPointerType>()83->getInterfaceDecl();8485// This can be null for calls to e.g. id<Foo>.86if (!receiverClass) return false;87} else {88receiverClass = method->getClassInterface();89assert(receiverClass && "method not associated with a class!");90}9192// If either class is a subclass of the other, it's fine.93if (receiverClass->isSuperClassOf(resultClass) ||94resultClass->isSuperClassOf(receiverClass))95return false;96}97}9899SourceLocation loc = method->getLocation();100101// If we're in a system header, and this is not a call, just make102// the method unusable.103if (receiverTypeIfCall.isNull() &&104SemaRef.getSourceManager().isInSystemHeader(loc)) {105method->addAttr(UnavailableAttr::CreateImplicit(Context, "",106UnavailableAttr::IR_ARCInitReturnsUnrelated, loc));107return true;108}109110// Otherwise, it's an error.111Diag(loc, diag::err_arc_init_method_unrelated_result_type);112method->setInvalidDecl();113return true;114}115116/// Issue a warning if the parameter of the overridden method is non-escaping117/// but the parameter of the overriding method is not.118static bool diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,119Sema &S) {120if (OldD->hasAttr<NoEscapeAttr>() && !NewD->hasAttr<NoEscapeAttr>()) {121S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape);122S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape);123return false;124}125126return true;127}128129/// Produce additional diagnostics if a category conforms to a protocol that130/// defines a method taking a non-escaping parameter.131static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD,132const ObjCCategoryDecl *CD,133const ObjCProtocolDecl *PD, Sema &S) {134if (!diagnoseNoescape(NewD, OldD, S))135S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot)136<< CD->IsClassExtension() << PD137<< cast<ObjCMethodDecl>(NewD->getDeclContext());138}139140void SemaObjC::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,141const ObjCMethodDecl *Overridden) {142ASTContext &Context = getASTContext();143if (Overridden->hasRelatedResultType() &&144!NewMethod->hasRelatedResultType()) {145// This can only happen when the method follows a naming convention that146// implies a related result type, and the original (overridden) method has147// a suitable return type, but the new (overriding) method does not have148// a suitable return type.149QualType ResultType = NewMethod->getReturnType();150SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange();151152// Figure out which class this method is part of, if any.153ObjCInterfaceDecl *CurrentClass154= dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext());155if (!CurrentClass) {156DeclContext *DC = NewMethod->getDeclContext();157if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC))158CurrentClass = Cat->getClassInterface();159else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC))160CurrentClass = Impl->getClassInterface();161else if (ObjCCategoryImplDecl *CatImpl162= dyn_cast<ObjCCategoryImplDecl>(DC))163CurrentClass = CatImpl->getClassInterface();164}165166if (CurrentClass) {167Diag(NewMethod->getLocation(),168diag::warn_related_result_type_compatibility_class)169<< Context.getObjCInterfaceType(CurrentClass)170<< ResultType171<< ResultTypeRange;172} else {173Diag(NewMethod->getLocation(),174diag::warn_related_result_type_compatibility_protocol)175<< ResultType176<< ResultTypeRange;177}178179if (ObjCMethodFamily Family = Overridden->getMethodFamily())180Diag(Overridden->getLocation(),181diag::note_related_result_type_family)182<< /*overridden method*/ 0183<< Family;184else185Diag(Overridden->getLocation(),186diag::note_related_result_type_overridden);187}188189if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=190Overridden->hasAttr<NSReturnsRetainedAttr>())) {191Diag(NewMethod->getLocation(),192getLangOpts().ObjCAutoRefCount193? diag::err_nsreturns_retained_attribute_mismatch194: diag::warn_nsreturns_retained_attribute_mismatch)195<< 1;196Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";197}198if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=199Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {200Diag(NewMethod->getLocation(),201getLangOpts().ObjCAutoRefCount202? diag::err_nsreturns_retained_attribute_mismatch203: diag::warn_nsreturns_retained_attribute_mismatch)204<< 0;205Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";206}207208ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),209oe = Overridden->param_end();210for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(),211ne = NewMethod->param_end();212ni != ne && oi != oe; ++ni, ++oi) {213const ParmVarDecl *oldDecl = (*oi);214ParmVarDecl *newDecl = (*ni);215if (newDecl->hasAttr<NSConsumedAttr>() !=216oldDecl->hasAttr<NSConsumedAttr>()) {217Diag(newDecl->getLocation(),218getLangOpts().ObjCAutoRefCount219? diag::err_nsconsumed_attribute_mismatch220: diag::warn_nsconsumed_attribute_mismatch);221Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";222}223224diagnoseNoescape(newDecl, oldDecl, SemaRef);225}226}227228/// Check a method declaration for compatibility with the Objective-C229/// ARC conventions.230bool SemaObjC::CheckARCMethodDecl(ObjCMethodDecl *method) {231ASTContext &Context = getASTContext();232ObjCMethodFamily family = method->getMethodFamily();233switch (family) {234case OMF_None:235case OMF_finalize:236case OMF_retain:237case OMF_release:238case OMF_autorelease:239case OMF_retainCount:240case OMF_self:241case OMF_initialize:242case OMF_performSelector:243return false;244245case OMF_dealloc:246if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {247SourceRange ResultTypeRange = method->getReturnTypeSourceRange();248if (ResultTypeRange.isInvalid())249Diag(method->getLocation(), diag::err_dealloc_bad_result_type)250<< method->getReturnType()251<< FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");252else253Diag(method->getLocation(), diag::err_dealloc_bad_result_type)254<< method->getReturnType()255<< FixItHint::CreateReplacement(ResultTypeRange, "void");256return true;257}258return false;259260case OMF_init:261// If the method doesn't obey the init rules, don't bother annotating it.262if (checkInitMethod(method, QualType()))263return true;264265method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));266267// Don't add a second copy of this attribute, but otherwise don't268// let it be suppressed.269if (method->hasAttr<NSReturnsRetainedAttr>())270return false;271break;272273case OMF_alloc:274case OMF_copy:275case OMF_mutableCopy:276case OMF_new:277if (method->hasAttr<NSReturnsRetainedAttr>() ||278method->hasAttr<NSReturnsNotRetainedAttr>() ||279method->hasAttr<NSReturnsAutoreleasedAttr>())280return false;281break;282}283284method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));285return false;286}287288static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,289SourceLocation ImplLoc) {290if (!ND)291return;292bool IsCategory = false;293StringRef RealizedPlatform;294AvailabilityResult Availability = ND->getAvailability(295/*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),296&RealizedPlatform);297if (Availability != AR_Deprecated) {298if (isa<ObjCMethodDecl>(ND)) {299if (Availability != AR_Unavailable)300return;301if (RealizedPlatform.empty())302RealizedPlatform = S.Context.getTargetInfo().getPlatformName();303// Warn about implementing unavailable methods, unless the unavailable304// is for an app extension.305if (RealizedPlatform.ends_with("_app_extension"))306return;307S.Diag(ImplLoc, diag::warn_unavailable_def);308S.Diag(ND->getLocation(), diag::note_method_declared_at)309<< ND->getDeclName();310return;311}312if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND)) {313if (!CD->getClassInterface()->isDeprecated())314return;315ND = CD->getClassInterface();316IsCategory = true;317} else318return;319}320S.Diag(ImplLoc, diag::warn_deprecated_def)321<< (isa<ObjCMethodDecl>(ND)322? /*Method*/ 0323: isa<ObjCCategoryDecl>(ND) || IsCategory ? /*Category*/ 2324: /*Class*/ 1);325if (isa<ObjCMethodDecl>(ND))326S.Diag(ND->getLocation(), diag::note_method_declared_at)327<< ND->getDeclName();328else329S.Diag(ND->getLocation(), diag::note_previous_decl)330<< (isa<ObjCCategoryDecl>(ND) ? "category" : "class");331}332333/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global334/// pool.335void SemaObjC::AddAnyMethodToGlobalPool(Decl *D) {336ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);337338// If we don't have a valid method decl, simply return.339if (!MDecl)340return;341if (MDecl->isInstanceMethod())342AddInstanceMethodToGlobalPool(MDecl, true);343else344AddFactoryMethodToGlobalPool(MDecl, true);345}346347/// HasExplicitOwnershipAttr - returns true when pointer to ObjC pointer348/// has explicit ownership attribute; false otherwise.349static bool350HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {351QualType T = Param->getType();352353if (const PointerType *PT = T->getAs<PointerType>()) {354T = PT->getPointeeType();355} else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {356T = RT->getPointeeType();357} else {358return true;359}360361// If we have a lifetime qualifier, but it's local, we must have362// inferred it. So, it is implicit.363return !T.getLocalQualifiers().hasObjCLifetime();364}365366/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible367/// and user declared, in the method definition's AST.368void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {369ASTContext &Context = getASTContext();370SemaRef.ImplicitlyRetainedSelfLocs.clear();371assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused");372ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);373374SemaRef.PushExpressionEvaluationContext(375SemaRef.ExprEvalContexts.back().Context);376377// If we don't have a valid method decl, simply return.378if (!MDecl)379return;380381QualType ResultType = MDecl->getReturnType();382if (!ResultType->isDependentType() && !ResultType->isVoidType() &&383!MDecl->isInvalidDecl() &&384SemaRef.RequireCompleteType(MDecl->getLocation(), ResultType,385diag::err_func_def_incomplete_result))386MDecl->setInvalidDecl();387388// Allow all of Sema to see that we are entering a method definition.389SemaRef.PushDeclContext(FnBodyScope, MDecl);390SemaRef.PushFunctionScope();391392// Create Decl objects for each parameter, entrring them in the scope for393// binding to their use.394395// Insert the invisible arguments, self and _cmd!396MDecl->createImplicitParams(Context, MDecl->getClassInterface());397398SemaRef.PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);399SemaRef.PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);400401// The ObjC parser requires parameter names so there's no need to check.402SemaRef.CheckParmsForFunctionDef(MDecl->parameters(),403/*CheckParameterNames=*/false);404405// Introduce all of the other parameters into this scope.406for (auto *Param : MDecl->parameters()) {407if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount &&408!HasExplicitOwnershipAttr(SemaRef, Param))409Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<410Param->getType();411412if (Param->getIdentifier())413SemaRef.PushOnScopeChains(Param, FnBodyScope);414}415416// In ARC, disallow definition of retain/release/autorelease/retainCount417if (getLangOpts().ObjCAutoRefCount) {418switch (MDecl->getMethodFamily()) {419case OMF_retain:420case OMF_retainCount:421case OMF_release:422case OMF_autorelease:423Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def)424<< 0 << MDecl->getSelector();425break;426427case OMF_None:428case OMF_dealloc:429case OMF_finalize:430case OMF_alloc:431case OMF_init:432case OMF_mutableCopy:433case OMF_copy:434case OMF_new:435case OMF_self:436case OMF_initialize:437case OMF_performSelector:438break;439}440}441442// Warn on deprecated methods under -Wdeprecated-implementations,443// and prepare for warning on missing super calls.444if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {445ObjCMethodDecl *IMD =446IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());447448if (IMD) {449ObjCImplDecl *ImplDeclOfMethodDef =450dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());451ObjCContainerDecl *ContDeclOfMethodDecl =452dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());453ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;454if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))455ImplDeclOfMethodDecl = OID->getImplementation();456else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {457if (CD->IsClassExtension()) {458if (ObjCInterfaceDecl *OID = CD->getClassInterface())459ImplDeclOfMethodDecl = OID->getImplementation();460} else461ImplDeclOfMethodDecl = CD->getImplementation();462}463// No need to issue deprecated warning if deprecated mehod in class/category464// is being implemented in its own implementation (no overriding is involved).465if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)466DiagnoseObjCImplementedDeprecations(SemaRef, IMD, MDecl->getLocation());467}468469if (MDecl->getMethodFamily() == OMF_init) {470if (MDecl->isDesignatedInitializerForTheInterface()) {471SemaRef.getCurFunction()->ObjCIsDesignatedInit = true;472SemaRef.getCurFunction()->ObjCWarnForNoDesignatedInitChain =473IC->getSuperClass() != nullptr;474} else if (IC->hasDesignatedInitializers()) {475SemaRef.getCurFunction()->ObjCIsSecondaryInit = true;476SemaRef.getCurFunction()->ObjCWarnForNoInitDelegation = true;477}478}479480// If this is "dealloc" or "finalize", set some bit here.481// Then in ActOnSuperMessage() (SemaExprObjC), set it back to false.482// Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set.483// Only do this if the current class actually has a superclass.484if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) {485ObjCMethodFamily Family = MDecl->getMethodFamily();486if (Family == OMF_dealloc) {487if (!(getLangOpts().ObjCAutoRefCount ||488getLangOpts().getGC() == LangOptions::GCOnly))489SemaRef.getCurFunction()->ObjCShouldCallSuper = true;490491} else if (Family == OMF_finalize) {492if (Context.getLangOpts().getGC() != LangOptions::NonGC)493SemaRef.getCurFunction()->ObjCShouldCallSuper = true;494495} else {496const ObjCMethodDecl *SuperMethod =497SuperClass->lookupMethod(MDecl->getSelector(),498MDecl->isInstanceMethod());499SemaRef.getCurFunction()->ObjCShouldCallSuper =500(SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());501}502}503}504505// Some function attributes (like OptimizeNoneAttr) need actions before506// parsing body started.507SemaRef.applyFunctionAttributesBeforeParsingBody(D);508}509510namespace {511512// Callback to only accept typo corrections that are Objective-C classes.513// If an ObjCInterfaceDecl* is given to the constructor, then the validation514// function will reject corrections to that class.515class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback {516public:517ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}518explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)519: CurrentIDecl(IDecl) {}520521bool ValidateCandidate(const TypoCorrection &candidate) override {522ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();523return ID && !declaresSameEntity(ID, CurrentIDecl);524}525526std::unique_ptr<CorrectionCandidateCallback> clone() override {527return std::make_unique<ObjCInterfaceValidatorCCC>(*this);528}529530private:531ObjCInterfaceDecl *CurrentIDecl;532};533534} // end anonymous namespace535536static void diagnoseUseOfProtocols(Sema &TheSema,537ObjCContainerDecl *CD,538ObjCProtocolDecl *const *ProtoRefs,539unsigned NumProtoRefs,540const SourceLocation *ProtoLocs) {541assert(ProtoRefs);542// Diagnose availability in the context of the ObjC container.543Sema::ContextRAII SavedContext(TheSema, CD);544for (unsigned i = 0; i < NumProtoRefs; ++i) {545(void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i],546/*UnknownObjCClass=*/nullptr,547/*ObjCPropertyAccess=*/false,548/*AvoidPartialAvailabilityChecks=*/true);549}550}551552void SemaObjC::ActOnSuperClassOfClassInterface(553Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,554IdentifierInfo *ClassName, SourceLocation ClassLoc,555IdentifierInfo *SuperName, SourceLocation SuperLoc,556ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange) {557ASTContext &Context = getASTContext();558// Check if a different kind of symbol declared in this scope.559NamedDecl *PrevDecl = SemaRef.LookupSingleName(560SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);561562if (!PrevDecl) {563// Try to correct for a typo in the superclass name without correcting564// to the class we're defining.565ObjCInterfaceValidatorCCC CCC(IDecl);566if (TypoCorrection Corrected = SemaRef.CorrectTypo(567DeclarationNameInfo(SuperName, SuperLoc), Sema::LookupOrdinaryName,568SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) {569SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)570<< SuperName << ClassName);571PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();572}573}574575if (declaresSameEntity(PrevDecl, IDecl)) {576Diag(SuperLoc, diag::err_recursive_superclass)577<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);578IDecl->setEndOfDefinitionLoc(ClassLoc);579} else {580ObjCInterfaceDecl *SuperClassDecl =581dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);582QualType SuperClassType;583584// Diagnose classes that inherit from deprecated classes.585if (SuperClassDecl) {586(void)SemaRef.DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);587SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);588}589590if (PrevDecl && !SuperClassDecl) {591// The previous declaration was not a class decl. Check if we have a592// typedef. If we do, get the underlying class type.593if (const TypedefNameDecl *TDecl =594dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {595QualType T = TDecl->getUnderlyingType();596if (T->isObjCObjectType()) {597if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {598SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);599SuperClassType = Context.getTypeDeclType(TDecl);600601// This handles the following case:602// @interface NewI @end603// typedef NewI DeprI __attribute__((deprecated("blah")))604// @interface SI : DeprI /* warn here */ @end605(void)SemaRef.DiagnoseUseOfDecl(606const_cast<TypedefNameDecl *>(TDecl), SuperLoc);607}608}609}610611// This handles the following case:612//613// typedef int SuperClass;614// @interface MyClass : SuperClass {} @end615//616if (!SuperClassDecl) {617Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;618Diag(PrevDecl->getLocation(), diag::note_previous_definition);619}620}621622if (!isa_and_nonnull<TypedefNameDecl>(PrevDecl)) {623if (!SuperClassDecl)624Diag(SuperLoc, diag::err_undef_superclass)625<< SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);626else if (SemaRef.RequireCompleteType(627SuperLoc, SuperClassType, diag::err_forward_superclass,628SuperClassDecl->getDeclName(), ClassName,629SourceRange(AtInterfaceLoc, ClassLoc))) {630SuperClassDecl = nullptr;631SuperClassType = QualType();632}633}634635if (SuperClassType.isNull()) {636assert(!SuperClassDecl && "Failed to set SuperClassType?");637return;638}639640// Handle type arguments on the superclass.641TypeSourceInfo *SuperClassTInfo = nullptr;642if (!SuperTypeArgs.empty()) {643TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(644S, SuperLoc, SemaRef.CreateParsedType(SuperClassType, nullptr),645SuperTypeArgsRange.getBegin(), SuperTypeArgs,646SuperTypeArgsRange.getEnd(), SourceLocation(), {}, {},647SourceLocation());648if (!fullSuperClassType.isUsable())649return;650651SuperClassType =652SemaRef.GetTypeFromParser(fullSuperClassType.get(), &SuperClassTInfo);653}654655if (!SuperClassTInfo) {656SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,657SuperLoc);658}659660IDecl->setSuperClass(SuperClassTInfo);661IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc());662}663}664665DeclResult SemaObjC::actOnObjCTypeParam(666Scope *S, ObjCTypeParamVariance variance, SourceLocation varianceLoc,667unsigned index, IdentifierInfo *paramName, SourceLocation paramLoc,668SourceLocation colonLoc, ParsedType parsedTypeBound) {669ASTContext &Context = getASTContext();670// If there was an explicitly-provided type bound, check it.671TypeSourceInfo *typeBoundInfo = nullptr;672if (parsedTypeBound) {673// The type bound can be any Objective-C pointer type.674QualType typeBound =675SemaRef.GetTypeFromParser(parsedTypeBound, &typeBoundInfo);676if (typeBound->isObjCObjectPointerType()) {677// okay678} else if (typeBound->isObjCObjectType()) {679// The user forgot the * on an Objective-C pointer type, e.g.,680// "T : NSView".681SourceLocation starLoc =682SemaRef.getLocForEndOfToken(typeBoundInfo->getTypeLoc().getEndLoc());683Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),684diag::err_objc_type_param_bound_missing_pointer)685<< typeBound << paramName686<< FixItHint::CreateInsertion(starLoc, " *");687688// Create a new type location builder so we can update the type689// location information we have.690TypeLocBuilder builder;691builder.pushFullCopy(typeBoundInfo->getTypeLoc());692693// Create the Objective-C pointer type.694typeBound = Context.getObjCObjectPointerType(typeBound);695ObjCObjectPointerTypeLoc newT696= builder.push<ObjCObjectPointerTypeLoc>(typeBound);697newT.setStarLoc(starLoc);698699// Form the new type source information.700typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);701} else {702// Not a valid type bound.703Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),704diag::err_objc_type_param_bound_nonobject)705<< typeBound << paramName;706707// Forget the bound; we'll default to id later.708typeBoundInfo = nullptr;709}710711// Type bounds cannot have qualifiers (even indirectly) or explicit712// nullability.713if (typeBoundInfo) {714QualType typeBound = typeBoundInfo->getType();715TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc();716if (qual || typeBound.hasQualifiers()) {717bool diagnosed = false;718SourceRange rangeToRemove;719if (qual) {720if (auto attr = qual.getAs<AttributedTypeLoc>()) {721rangeToRemove = attr.getLocalSourceRange();722if (attr.getTypePtr()->getImmediateNullability()) {723Diag(attr.getBeginLoc(),724diag::err_objc_type_param_bound_explicit_nullability)725<< paramName << typeBound726<< FixItHint::CreateRemoval(rangeToRemove);727diagnosed = true;728}729}730}731732if (!diagnosed) {733Diag(qual ? qual.getBeginLoc()734: typeBoundInfo->getTypeLoc().getBeginLoc(),735diag::err_objc_type_param_bound_qualified)736<< paramName << typeBound737<< typeBound.getQualifiers().getAsString()738<< FixItHint::CreateRemoval(rangeToRemove);739}740741// If the type bound has qualifiers other than CVR, we need to strip742// them or we'll probably assert later when trying to apply new743// qualifiers.744Qualifiers quals = typeBound.getQualifiers();745quals.removeCVRQualifiers();746if (!quals.empty()) {747typeBoundInfo =748Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType());749}750}751}752}753754// If there was no explicit type bound (or we removed it due to an error),755// use 'id' instead.756if (!typeBoundInfo) {757colonLoc = SourceLocation();758typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType());759}760761// Create the type parameter.762return ObjCTypeParamDecl::Create(Context, SemaRef.CurContext, variance,763varianceLoc, index, paramLoc, paramName,764colonLoc, typeBoundInfo);765}766767ObjCTypeParamList *768SemaObjC::actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,769ArrayRef<Decl *> typeParamsIn,770SourceLocation rAngleLoc) {771ASTContext &Context = getASTContext();772// We know that the array only contains Objective-C type parameters.773ArrayRef<ObjCTypeParamDecl *>774typeParams(775reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()),776typeParamsIn.size());777778// Diagnose redeclarations of type parameters.779// We do this now because Objective-C type parameters aren't pushed into780// scope until later (after the instance variable block), but we want the781// diagnostics to occur right after we parse the type parameter list.782llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams;783for (auto *typeParam : typeParams) {784auto known = knownParams.find(typeParam->getIdentifier());785if (known != knownParams.end()) {786Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl)787<< typeParam->getIdentifier()788<< SourceRange(known->second->getLocation());789790typeParam->setInvalidDecl();791} else {792knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam));793794// Push the type parameter into scope.795SemaRef.PushOnScopeChains(typeParam, S, /*AddToContext=*/false);796}797}798799// Create the parameter list.800return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc);801}802803void SemaObjC::popObjCTypeParamList(Scope *S,804ObjCTypeParamList *typeParamList) {805for (auto *typeParam : *typeParamList) {806if (!typeParam->isInvalidDecl()) {807S->RemoveDecl(typeParam);808SemaRef.IdResolver.RemoveDecl(typeParam);809}810}811}812813namespace {814/// The context in which an Objective-C type parameter list occurs, for use815/// in diagnostics.816enum class TypeParamListContext {817ForwardDeclaration,818Definition,819Category,820Extension821};822} // end anonymous namespace823824/// Check consistency between two Objective-C type parameter lists, e.g.,825/// between a category/extension and an \@interface or between an \@class and an826/// \@interface.827static bool checkTypeParamListConsistency(Sema &S,828ObjCTypeParamList *prevTypeParams,829ObjCTypeParamList *newTypeParams,830TypeParamListContext newContext) {831// If the sizes don't match, complain about that.832if (prevTypeParams->size() != newTypeParams->size()) {833SourceLocation diagLoc;834if (newTypeParams->size() > prevTypeParams->size()) {835diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();836} else {837diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc());838}839840S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)841<< static_cast<unsigned>(newContext)842<< (newTypeParams->size() > prevTypeParams->size())843<< prevTypeParams->size()844<< newTypeParams->size();845846return true;847}848849// Match up the type parameters.850for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) {851ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i];852ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i];853854// Check for consistency of the variance.855if (newTypeParam->getVariance() != prevTypeParam->getVariance()) {856if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant &&857newContext != TypeParamListContext::Definition) {858// When the new type parameter is invariant and is not part859// of the definition, just propagate the variance.860newTypeParam->setVariance(prevTypeParam->getVariance());861} else if (prevTypeParam->getVariance()862== ObjCTypeParamVariance::Invariant &&863!(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&864cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())865->getDefinition() == prevTypeParam->getDeclContext())) {866// When the old parameter is invariant and was not part of the867// definition, just ignore the difference because it doesn't868// matter.869} else {870{871// Diagnose the conflict and update the second declaration.872SourceLocation diagLoc = newTypeParam->getVarianceLoc();873if (diagLoc.isInvalid())874diagLoc = newTypeParam->getBeginLoc();875876auto diag = S.Diag(diagLoc,877diag::err_objc_type_param_variance_conflict)878<< static_cast<unsigned>(newTypeParam->getVariance())879<< newTypeParam->getDeclName()880<< static_cast<unsigned>(prevTypeParam->getVariance())881<< prevTypeParam->getDeclName();882switch (prevTypeParam->getVariance()) {883case ObjCTypeParamVariance::Invariant:884diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc());885break;886887case ObjCTypeParamVariance::Covariant:888case ObjCTypeParamVariance::Contravariant: {889StringRef newVarianceStr890= prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant891? "__covariant"892: "__contravariant";893if (newTypeParam->getVariance()894== ObjCTypeParamVariance::Invariant) {895diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(),896(newVarianceStr + " ").str());897} else {898diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),899newVarianceStr);900}901}902}903}904905S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)906<< prevTypeParam->getDeclName();907908// Override the variance.909newTypeParam->setVariance(prevTypeParam->getVariance());910}911}912913// If the bound types match, there's nothing to do.914if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(),915newTypeParam->getUnderlyingType()))916continue;917918// If the new type parameter's bound was explicit, complain about it being919// different from the original.920if (newTypeParam->hasExplicitBound()) {921SourceRange newBoundRange = newTypeParam->getTypeSourceInfo()922->getTypeLoc().getSourceRange();923S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict)924<< newTypeParam->getUnderlyingType()925<< newTypeParam->getDeclName()926<< prevTypeParam->hasExplicitBound()927<< prevTypeParam->getUnderlyingType()928<< (newTypeParam->getDeclName() == prevTypeParam->getDeclName())929<< prevTypeParam->getDeclName()930<< FixItHint::CreateReplacement(931newBoundRange,932prevTypeParam->getUnderlyingType().getAsString(933S.Context.getPrintingPolicy()));934935S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)936<< prevTypeParam->getDeclName();937938// Override the new type parameter's bound type with the previous type,939// so that it's consistent.940S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);941continue;942}943944// The new type parameter got the implicit bound of 'id'. That's okay for945// categories and extensions (overwrite it later), but not for forward946// declarations and @interfaces, because those must be standalone.947if (newContext == TypeParamListContext::ForwardDeclaration ||948newContext == TypeParamListContext::Definition) {949// Diagnose this problem for forward declarations and definitions.950SourceLocation insertionLoc951= S.getLocForEndOfToken(newTypeParam->getLocation());952std::string newCode953= " : " + prevTypeParam->getUnderlyingType().getAsString(954S.Context.getPrintingPolicy());955S.Diag(newTypeParam->getLocation(),956diag::err_objc_type_param_bound_missing)957<< prevTypeParam->getUnderlyingType()958<< newTypeParam->getDeclName()959<< (newContext == TypeParamListContext::ForwardDeclaration)960<< FixItHint::CreateInsertion(insertionLoc, newCode);961962S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)963<< prevTypeParam->getDeclName();964}965966// Update the new type parameter's bound to match the previous one.967S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);968}969970return false;971}972973ObjCInterfaceDecl *SemaObjC::ActOnStartClassInterface(974Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,975SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,976IdentifierInfo *SuperName, SourceLocation SuperLoc,977ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,978Decl *const *ProtoRefs, unsigned NumProtoRefs,979const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,980const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {981assert(ClassName && "Missing class identifier");982983ASTContext &Context = getASTContext();984// Check for another declaration kind with the same name.985NamedDecl *PrevDecl = SemaRef.LookupSingleName(986SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,987SemaRef.forRedeclarationInCurContext());988989if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {990Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;991Diag(PrevDecl->getLocation(), diag::note_previous_definition);992}993994// Create a declaration to describe this @interface.995ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);996997if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {998// A previous decl with a different name is because of999// @compatibility_alias, for example:1000// \code1001// @class NewImage;1002// @compatibility_alias OldImage NewImage;1003// \endcode1004// A lookup for 'OldImage' will return the 'NewImage' decl.1005//1006// In such a case use the real declaration name, instead of the alias one,1007// otherwise we will break IdentifierResolver and redecls-chain invariants.1008// FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl1009// has been aliased.1010ClassName = PrevIDecl->getIdentifier();1011}10121013// If there was a forward declaration with type parameters, check1014// for consistency.1015if (PrevIDecl) {1016if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {1017if (typeParamList) {1018// Both have type parameter lists; check for consistency.1019if (checkTypeParamListConsistency(SemaRef, prevTypeParamList,1020typeParamList,1021TypeParamListContext::Definition)) {1022typeParamList = nullptr;1023}1024} else {1025Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first)1026<< ClassName;1027Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl)1028<< ClassName;10291030// Clone the type parameter list.1031SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams;1032for (auto *typeParam : *prevTypeParamList) {1033clonedTypeParams.push_back(ObjCTypeParamDecl::Create(1034Context, SemaRef.CurContext, typeParam->getVariance(),1035SourceLocation(), typeParam->getIndex(), SourceLocation(),1036typeParam->getIdentifier(), SourceLocation(),1037Context.getTrivialTypeSourceInfo(1038typeParam->getUnderlyingType())));1039}10401041typeParamList = ObjCTypeParamList::create(Context,1042SourceLocation(),1043clonedTypeParams,1044SourceLocation());1045}1046}1047}10481049ObjCInterfaceDecl *IDecl =1050ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,1051ClassName, typeParamList, PrevIDecl, ClassLoc);1052if (PrevIDecl) {1053// Class already seen. Was it a definition?1054if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {1055if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {1056SkipBody->CheckSameAsPrevious = true;1057SkipBody->New = IDecl;1058SkipBody->Previous = Def;1059} else {1060Diag(AtInterfaceLoc, diag::err_duplicate_class_def)1061<< PrevIDecl->getDeclName();1062Diag(Def->getLocation(), diag::note_previous_definition);1063IDecl->setInvalidDecl();1064}1065}1066}10671068SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IDecl, AttrList);1069SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);1070SemaRef.ProcessAPINotes(IDecl);10711072// Merge attributes from previous declarations.1073if (PrevIDecl)1074SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);10751076SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);10771078// Start the definition of this class. If we're in a redefinition case, there1079// may already be a definition, so we'll end up adding to it.1080if (SkipBody && SkipBody->CheckSameAsPrevious)1081IDecl->startDuplicateDefinitionForComparison();1082else if (!IDecl->hasDefinition())1083IDecl->startDefinition();10841085if (SuperName) {1086// Diagnose availability in the context of the @interface.1087Sema::ContextRAII SavedContext(SemaRef, IDecl);10881089ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,1090ClassName, ClassLoc,1091SuperName, SuperLoc, SuperTypeArgs,1092SuperTypeArgsRange);1093} else { // we have a root class.1094IDecl->setEndOfDefinitionLoc(ClassLoc);1095}10961097// Check then save referenced protocols.1098if (NumProtoRefs) {1099diagnoseUseOfProtocols(SemaRef, IDecl, (ObjCProtocolDecl *const *)ProtoRefs,1100NumProtoRefs, ProtoLocs);1101IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1102ProtoLocs, Context);1103IDecl->setEndOfDefinitionLoc(EndProtoLoc);1104}11051106CheckObjCDeclScope(IDecl);1107ActOnObjCContainerStartDefinition(IDecl);1108return IDecl;1109}11101111/// ActOnTypedefedProtocols - this action finds protocol list as part of the1112/// typedef'ed use for a qualified super class and adds them to the list1113/// of the protocols.1114void SemaObjC::ActOnTypedefedProtocols(1115SmallVectorImpl<Decl *> &ProtocolRefs,1116SmallVectorImpl<SourceLocation> &ProtocolLocs, IdentifierInfo *SuperName,1117SourceLocation SuperLoc) {1118if (!SuperName)1119return;1120NamedDecl *IDecl = SemaRef.LookupSingleName(1121SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);1122if (!IDecl)1123return;11241125if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {1126QualType T = TDecl->getUnderlyingType();1127if (T->isObjCObjectType())1128if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) {1129ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());1130// FIXME: Consider whether this should be an invalid loc since the loc1131// is not actually pointing to a protocol name reference but to the1132// typedef reference. Note that the base class name loc is also pointing1133// at the typedef.1134ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc);1135}1136}1137}11381139/// ActOnCompatibilityAlias - this action is called after complete parsing of1140/// a \@compatibility_alias declaration. It sets up the alias relationships.1141Decl *SemaObjC::ActOnCompatibilityAlias(SourceLocation AtLoc,1142IdentifierInfo *AliasName,1143SourceLocation AliasLocation,1144IdentifierInfo *ClassName,1145SourceLocation ClassLocation) {1146ASTContext &Context = getASTContext();1147// Look for previous declaration of alias name1148NamedDecl *ADecl = SemaRef.LookupSingleName(1149SemaRef.TUScope, AliasName, AliasLocation, Sema::LookupOrdinaryName,1150SemaRef.forRedeclarationInCurContext());1151if (ADecl) {1152Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;1153Diag(ADecl->getLocation(), diag::note_previous_declaration);1154return nullptr;1155}1156// Check for class declaration1157NamedDecl *CDeclU = SemaRef.LookupSingleName(1158SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,1159SemaRef.forRedeclarationInCurContext());1160if (const TypedefNameDecl *TDecl =1161dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {1162QualType T = TDecl->getUnderlyingType();1163if (T->isObjCObjectType()) {1164if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {1165ClassName = IDecl->getIdentifier();1166CDeclU = SemaRef.LookupSingleName(1167SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,1168SemaRef.forRedeclarationInCurContext());1169}1170}1171}1172ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);1173if (!CDecl) {1174Diag(ClassLocation, diag::warn_undef_interface) << ClassName;1175if (CDeclU)1176Diag(CDeclU->getLocation(), diag::note_previous_declaration);1177return nullptr;1178}11791180// Everything checked out, instantiate a new alias declaration AST.1181ObjCCompatibleAliasDecl *AliasDecl = ObjCCompatibleAliasDecl::Create(1182Context, SemaRef.CurContext, AtLoc, AliasName, CDecl);11831184if (!CheckObjCDeclScope(AliasDecl))1185SemaRef.PushOnScopeChains(AliasDecl, SemaRef.TUScope);11861187return AliasDecl;1188}11891190bool SemaObjC::CheckForwardProtocolDeclarationForCircularDependency(1191IdentifierInfo *PName, SourceLocation &Ploc, SourceLocation PrevLoc,1192const ObjCList<ObjCProtocolDecl> &PList) {11931194bool res = false;1195for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),1196E = PList.end(); I != E; ++I) {1197if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), Ploc)) {1198if (PDecl->getIdentifier() == PName) {1199Diag(Ploc, diag::err_protocol_has_circular_dependency);1200Diag(PrevLoc, diag::note_previous_definition);1201res = true;1202}12031204if (!PDecl->hasDefinition())1205continue;12061207if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,1208PDecl->getLocation(), PDecl->getReferencedProtocols()))1209res = true;1210}1211}1212return res;1213}12141215ObjCProtocolDecl *SemaObjC::ActOnStartProtocolInterface(1216SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,1217SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,1218const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,1219const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {1220ASTContext &Context = getASTContext();1221bool err = false;1222// FIXME: Deal with AttrList.1223assert(ProtocolName && "Missing protocol identifier");1224ObjCProtocolDecl *PrevDecl = LookupProtocol(1225ProtocolName, ProtocolLoc, SemaRef.forRedeclarationInCurContext());1226ObjCProtocolDecl *PDecl = nullptr;1227if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {1228// Create a new protocol that is completely distinct from previous1229// declarations, and do not make this protocol available for name lookup.1230// That way, we'll end up completely ignoring the duplicate.1231// FIXME: Can we turn this into an error?1232PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,1233ProtocolLoc, AtProtoInterfaceLoc,1234/*PrevDecl=*/Def);12351236if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {1237SkipBody->CheckSameAsPrevious = true;1238SkipBody->New = PDecl;1239SkipBody->Previous = Def;1240} else {1241// If we already have a definition, complain.1242Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;1243Diag(Def->getLocation(), diag::note_previous_definition);1244}12451246// If we are using modules, add the decl to the context in order to1247// serialize something meaningful.1248if (getLangOpts().Modules)1249SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1250PDecl->startDuplicateDefinitionForComparison();1251} else {1252if (PrevDecl) {1253// Check for circular dependencies among protocol declarations. This can1254// only happen if this protocol was forward-declared.1255ObjCList<ObjCProtocolDecl> PList;1256PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);1257err = CheckForwardProtocolDeclarationForCircularDependency(1258ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList);1259}12601261// Create the new declaration.1262PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,1263ProtocolLoc, AtProtoInterfaceLoc,1264/*PrevDecl=*/PrevDecl);12651266SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1267PDecl->startDefinition();1268}12691270SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, AttrList);1271SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);1272SemaRef.ProcessAPINotes(PDecl);12731274// Merge attributes from previous declarations.1275if (PrevDecl)1276SemaRef.mergeDeclAttributes(PDecl, PrevDecl);12771278if (!err && NumProtoRefs ) {1279/// Check then save referenced protocols.1280diagnoseUseOfProtocols(SemaRef, PDecl, (ObjCProtocolDecl *const *)ProtoRefs,1281NumProtoRefs, ProtoLocs);1282PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1283ProtoLocs, Context);1284}12851286CheckObjCDeclScope(PDecl);1287ActOnObjCContainerStartDefinition(PDecl);1288return PDecl;1289}12901291static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,1292ObjCProtocolDecl *&UndefinedProtocol) {1293if (!PDecl->hasDefinition() ||1294!PDecl->getDefinition()->isUnconditionallyVisible()) {1295UndefinedProtocol = PDecl;1296return true;1297}12981299for (auto *PI : PDecl->protocols())1300if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {1301UndefinedProtocol = PI;1302return true;1303}1304return false;1305}13061307/// FindProtocolDeclaration - This routine looks up protocols and1308/// issues an error if they are not declared. It returns list of1309/// protocol declarations in its 'Protocols' argument.1310void SemaObjC::FindProtocolDeclaration(bool WarnOnDeclarations,1311bool ForObjCContainer,1312ArrayRef<IdentifierLocPair> ProtocolId,1313SmallVectorImpl<Decl *> &Protocols) {1314for (const IdentifierLocPair &Pair : ProtocolId) {1315ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second);1316if (!PDecl) {1317DeclFilterCCC<ObjCProtocolDecl> CCC{};1318TypoCorrection Corrected =1319SemaRef.CorrectTypo(DeclarationNameInfo(Pair.first, Pair.second),1320Sema::LookupObjCProtocolName, SemaRef.TUScope,1321nullptr, CCC, Sema::CTK_ErrorRecovery);1322if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))1323SemaRef.diagnoseTypo(Corrected,1324PDiag(diag::err_undeclared_protocol_suggest)1325<< Pair.first);1326}13271328if (!PDecl) {1329Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first;1330continue;1331}1332// If this is a forward protocol declaration, get its definition.1333if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())1334PDecl = PDecl->getDefinition();13351336// For an objc container, delay protocol reference checking until after we1337// can set the objc decl as the availability context, otherwise check now.1338if (!ForObjCContainer) {1339(void)SemaRef.DiagnoseUseOfDecl(PDecl, Pair.second);1340}13411342// If this is a forward declaration and we are supposed to warn in this1343// case, do it.1344// FIXME: Recover nicely in the hidden case.1345ObjCProtocolDecl *UndefinedProtocol;13461347if (WarnOnDeclarations &&1348NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {1349Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first;1350Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)1351<< UndefinedProtocol;1352}1353Protocols.push_back(PDecl);1354}1355}13561357namespace {1358// Callback to only accept typo corrections that are either1359// Objective-C protocols or valid Objective-C type arguments.1360class ObjCTypeArgOrProtocolValidatorCCC final1361: public CorrectionCandidateCallback {1362ASTContext &Context;1363Sema::LookupNameKind LookupKind;1364public:1365ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,1366Sema::LookupNameKind lookupKind)1367: Context(context), LookupKind(lookupKind) { }13681369bool ValidateCandidate(const TypoCorrection &candidate) override {1370// If we're allowed to find protocols and we have a protocol, accept it.1371if (LookupKind != Sema::LookupOrdinaryName) {1372if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())1373return true;1374}13751376// If we're allowed to find type names and we have one, accept it.1377if (LookupKind != Sema::LookupObjCProtocolName) {1378// If we have a type declaration, we might accept this result.1379if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {1380// If we found a tag declaration outside of C++, skip it. This1381// can happy because we look for any name when there is no1382// bias to protocol or type names.1383if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)1384return false;13851386// Make sure the type is something we would accept as a type1387// argument.1388auto type = Context.getTypeDeclType(typeDecl);1389if (type->isObjCObjectPointerType() ||1390type->isBlockPointerType() ||1391type->isDependentType() ||1392type->isObjCObjectType())1393return true;13941395return false;1396}13971398// If we have an Objective-C class type, accept it; there will1399// be another fix to add the '*'.1400if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())1401return true;14021403return false;1404}14051406return false;1407}14081409std::unique_ptr<CorrectionCandidateCallback> clone() override {1410return std::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this);1411}1412};1413} // end anonymous namespace14141415void SemaObjC::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,1416SourceLocation ProtocolLoc,1417IdentifierInfo *TypeArgId,1418SourceLocation TypeArgLoc,1419bool SelectProtocolFirst) {1420Diag(TypeArgLoc, diag::err_objc_type_args_and_protocols)1421<< SelectProtocolFirst << TypeArgId << ProtocolId1422<< SourceRange(ProtocolLoc);1423}14241425void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers(1426Scope *S, ParsedType baseType, SourceLocation lAngleLoc,1427ArrayRef<IdentifierInfo *> identifiers,1428ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc,1429SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs,1430SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc,1431SmallVectorImpl<Decl *> &protocols, SourceLocation &protocolRAngleLoc,1432bool warnOnIncompleteProtocols) {1433ASTContext &Context = getASTContext();1434// Local function that updates the declaration specifiers with1435// protocol information.1436unsigned numProtocolsResolved = 0;1437auto resolvedAsProtocols = [&] {1438assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");14391440// Determine whether the base type is a parameterized class, in1441// which case we want to warn about typos such as1442// "NSArray<NSObject>" (that should be NSArray<NSObject *>).1443ObjCInterfaceDecl *baseClass = nullptr;1444QualType base = SemaRef.GetTypeFromParser(baseType, nullptr);1445bool allAreTypeNames = false;1446SourceLocation firstClassNameLoc;1447if (!base.isNull()) {1448if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) {1449baseClass = objcObjectType->getInterface();1450if (baseClass) {1451if (auto typeParams = baseClass->getTypeParamList()) {1452if (typeParams->size() == numProtocolsResolved) {1453// Note that we should be looking for type names, too.1454allAreTypeNames = true;1455}1456}1457}1458}1459}14601461for (unsigned i = 0, n = protocols.size(); i != n; ++i) {1462ObjCProtocolDecl *&proto1463= reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]);1464// For an objc container, delay protocol reference checking until after we1465// can set the objc decl as the availability context, otherwise check now.1466if (!warnOnIncompleteProtocols) {1467(void)SemaRef.DiagnoseUseOfDecl(proto, identifierLocs[i]);1468}14691470// If this is a forward protocol declaration, get its definition.1471if (!proto->isThisDeclarationADefinition() && proto->getDefinition())1472proto = proto->getDefinition();14731474// If this is a forward declaration and we are supposed to warn in this1475// case, do it.1476// FIXME: Recover nicely in the hidden case.1477ObjCProtocolDecl *forwardDecl = nullptr;1478if (warnOnIncompleteProtocols &&1479NestedProtocolHasNoDefinition(proto, forwardDecl)) {1480Diag(identifierLocs[i], diag::warn_undef_protocolref)1481<< proto->getDeclName();1482Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)1483<< forwardDecl;1484}14851486// If everything this far has been a type name (and we care1487// about such things), check whether this name refers to a type1488// as well.1489if (allAreTypeNames) {1490if (auto *decl =1491SemaRef.LookupSingleName(S, identifiers[i], identifierLocs[i],1492Sema::LookupOrdinaryName)) {1493if (isa<ObjCInterfaceDecl>(decl)) {1494if (firstClassNameLoc.isInvalid())1495firstClassNameLoc = identifierLocs[i];1496} else if (!isa<TypeDecl>(decl)) {1497// Not a type.1498allAreTypeNames = false;1499}1500} else {1501allAreTypeNames = false;1502}1503}1504}15051506// All of the protocols listed also have type names, and at least1507// one is an Objective-C class name. Check whether all of the1508// protocol conformances are declared by the base class itself, in1509// which case we warn.1510if (allAreTypeNames && firstClassNameLoc.isValid()) {1511llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols;1512Context.CollectInheritedProtocols(baseClass, knownProtocols);1513bool allProtocolsDeclared = true;1514for (auto *proto : protocols) {1515if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) {1516allProtocolsDeclared = false;1517break;1518}1519}15201521if (allProtocolsDeclared) {1522Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)1523<< baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)1524<< FixItHint::CreateInsertion(1525SemaRef.getLocForEndOfToken(firstClassNameLoc), " *");1526}1527}15281529protocolLAngleLoc = lAngleLoc;1530protocolRAngleLoc = rAngleLoc;1531assert(protocols.size() == identifierLocs.size());1532};15331534// Attempt to resolve all of the identifiers as protocols.1535for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1536ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);1537protocols.push_back(proto);1538if (proto)1539++numProtocolsResolved;1540}15411542// If all of the names were protocols, these were protocol qualifiers.1543if (numProtocolsResolved == identifiers.size())1544return resolvedAsProtocols();15451546// Attempt to resolve all of the identifiers as type names or1547// Objective-C class names. The latter is technically ill-formed,1548// but is probably something like \c NSArray<NSView *> missing the1549// \c*.1550typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;1551SmallVector<TypeOrClassDecl, 4> typeDecls;1552unsigned numTypeDeclsResolved = 0;1553for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1554NamedDecl *decl = SemaRef.LookupSingleName(1555S, identifiers[i], identifierLocs[i], Sema::LookupOrdinaryName);1556if (!decl) {1557typeDecls.push_back(TypeOrClassDecl());1558continue;1559}15601561if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {1562typeDecls.push_back(typeDecl);1563++numTypeDeclsResolved;1564continue;1565}15661567if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {1568typeDecls.push_back(objcClass);1569++numTypeDeclsResolved;1570continue;1571}15721573typeDecls.push_back(TypeOrClassDecl());1574}15751576AttributeFactory attrFactory;15771578// Local function that forms a reference to the given type or1579// Objective-C class declaration.1580auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)1581-> TypeResult {1582// Form declaration specifiers. They simply refer to the type.1583DeclSpec DS(attrFactory);1584const char* prevSpec; // unused1585unsigned diagID; // unused1586QualType type;1587if (auto *actualTypeDecl = typeDecl.dyn_cast<TypeDecl *>())1588type = Context.getTypeDeclType(actualTypeDecl);1589else1590type = Context.getObjCInterfaceType(typeDecl.get<ObjCInterfaceDecl *>());1591TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);1592ParsedType parsedType = SemaRef.CreateParsedType(type, parsedTSInfo);1593DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,1594parsedType, Context.getPrintingPolicy());1595// Use the identifier location for the type source range.1596DS.SetRangeStart(loc);1597DS.SetRangeEnd(loc);15981599// Form the declarator.1600Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName);16011602// If we have a typedef of an Objective-C class type that is missing a '*',1603// add the '*'.1604if (type->getAs<ObjCInterfaceType>()) {1605SourceLocation starLoc = SemaRef.getLocForEndOfToken(loc);1606D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc,1607SourceLocation(),1608SourceLocation(),1609SourceLocation(),1610SourceLocation(),1611SourceLocation()),1612starLoc);16131614// Diagnose the missing '*'.1615Diag(loc, diag::err_objc_type_arg_missing_star)1616<< type1617<< FixItHint::CreateInsertion(starLoc, " *");1618}16191620// Convert this to a type.1621return SemaRef.ActOnTypeName(D);1622};16231624// Local function that updates the declaration specifiers with1625// type argument information.1626auto resolvedAsTypeDecls = [&] {1627// We did not resolve these as protocols.1628protocols.clear();16291630assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl");1631// Map type declarations to type arguments.1632for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1633// Map type reference to a type.1634TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]);1635if (!type.isUsable()) {1636typeArgs.clear();1637return;1638}16391640typeArgs.push_back(type.get());1641}16421643typeArgsLAngleLoc = lAngleLoc;1644typeArgsRAngleLoc = rAngleLoc;1645};16461647// If all of the identifiers can be resolved as type names or1648// Objective-C class names, we have type arguments.1649if (numTypeDeclsResolved == identifiers.size())1650return resolvedAsTypeDecls();16511652// Error recovery: some names weren't found, or we have a mix of1653// type and protocol names. Go resolve all of the unresolved names1654// and complain if we can't find a consistent answer.1655Sema::LookupNameKind lookupKind = Sema::LookupAnyName;1656for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1657// If we already have a protocol or type. Check whether it is the1658// right thing.1659if (protocols[i] || typeDecls[i]) {1660// If we haven't figured out whether we want types or protocols1661// yet, try to figure it out from this name.1662if (lookupKind == Sema::LookupAnyName) {1663// If this name refers to both a protocol and a type (e.g., \c1664// NSObject), don't conclude anything yet.1665if (protocols[i] && typeDecls[i])1666continue;16671668// Otherwise, let this name decide whether we'll be correcting1669// toward types or protocols.1670lookupKind = protocols[i] ? Sema::LookupObjCProtocolName1671: Sema::LookupOrdinaryName;1672continue;1673}16741675// If we want protocols and we have a protocol, there's nothing1676// more to do.1677if (lookupKind == Sema::LookupObjCProtocolName && protocols[i])1678continue;16791680// If we want types and we have a type declaration, there's1681// nothing more to do.1682if (lookupKind == Sema::LookupOrdinaryName && typeDecls[i])1683continue;16841685// We have a conflict: some names refer to protocols and others1686// refer to types.1687DiagnoseTypeArgsAndProtocols(identifiers[0], identifierLocs[0],1688identifiers[i], identifierLocs[i],1689protocols[i] != nullptr);16901691protocols.clear();1692typeArgs.clear();1693return;1694}16951696// Perform typo correction on the name.1697ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind);1698TypoCorrection corrected = SemaRef.CorrectTypo(1699DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,1700nullptr, CCC, Sema::CTK_ErrorRecovery);1701if (corrected) {1702// Did we find a protocol?1703if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {1704SemaRef.diagnoseTypo(corrected,1705PDiag(diag::err_undeclared_protocol_suggest)1706<< identifiers[i]);1707lookupKind = Sema::LookupObjCProtocolName;1708protocols[i] = proto;1709++numProtocolsResolved;1710continue;1711}17121713// Did we find a type?1714if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {1715SemaRef.diagnoseTypo(corrected,1716PDiag(diag::err_unknown_typename_suggest)1717<< identifiers[i]);1718lookupKind = Sema::LookupOrdinaryName;1719typeDecls[i] = typeDecl;1720++numTypeDeclsResolved;1721continue;1722}17231724// Did we find an Objective-C class?1725if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {1726SemaRef.diagnoseTypo(corrected,1727PDiag(diag::err_unknown_type_or_class_name_suggest)1728<< identifiers[i] << true);1729lookupKind = Sema::LookupOrdinaryName;1730typeDecls[i] = objcClass;1731++numTypeDeclsResolved;1732continue;1733}1734}17351736// We couldn't find anything.1737Diag(identifierLocs[i],1738(lookupKind == Sema::LookupAnyName ? diag::err_objc_type_arg_missing1739: lookupKind == Sema::LookupObjCProtocolName1740? diag::err_undeclared_protocol1741: diag::err_unknown_typename))1742<< identifiers[i];1743protocols.clear();1744typeArgs.clear();1745return;1746}17471748// If all of the names were (corrected to) protocols, these were1749// protocol qualifiers.1750if (numProtocolsResolved == identifiers.size())1751return resolvedAsProtocols();17521753// Otherwise, all of the names were (corrected to) types.1754assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");1755return resolvedAsTypeDecls();1756}17571758/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of1759/// a class method in its extension.1760///1761void SemaObjC::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,1762ObjCInterfaceDecl *ID) {1763if (!ID)1764return; // Possibly due to previous error17651766llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;1767for (auto *MD : ID->methods())1768MethodMap[MD->getSelector()] = MD;17691770if (MethodMap.empty())1771return;1772for (const auto *Method : CAT->methods()) {1773const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];1774if (PrevMethod &&1775(PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) &&1776!MatchTwoMethodDeclarations(Method, PrevMethod)) {1777Diag(Method->getLocation(), diag::err_duplicate_method_decl)1778<< Method->getDeclName();1779Diag(PrevMethod->getLocation(), diag::note_previous_declaration);1780}1781}1782}17831784/// ActOnForwardProtocolDeclaration - Handle \@protocol foo;1785SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardProtocolDeclaration(1786SourceLocation AtProtocolLoc, ArrayRef<IdentifierLocPair> IdentList,1787const ParsedAttributesView &attrList) {1788ASTContext &Context = getASTContext();1789SmallVector<Decl *, 8> DeclsInGroup;1790for (const IdentifierLocPair &IdentPair : IdentList) {1791IdentifierInfo *Ident = IdentPair.first;1792ObjCProtocolDecl *PrevDecl = LookupProtocol(1793Ident, IdentPair.second, SemaRef.forRedeclarationInCurContext());1794ObjCProtocolDecl *PDecl =1795ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident,1796IdentPair.second, AtProtocolLoc, PrevDecl);17971798SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1799CheckObjCDeclScope(PDecl);18001801SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, attrList);1802SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);18031804if (PrevDecl)1805SemaRef.mergeDeclAttributes(PDecl, PrevDecl);18061807DeclsInGroup.push_back(PDecl);1808}18091810return SemaRef.BuildDeclaratorGroup(DeclsInGroup);1811}18121813ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface(1814SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName,1815SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,1816const IdentifierInfo *CategoryName, SourceLocation CategoryLoc,1817Decl *const *ProtoRefs, unsigned NumProtoRefs,1818const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,1819const ParsedAttributesView &AttrList) {1820ASTContext &Context = getASTContext();1821ObjCCategoryDecl *CDecl;1822ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);18231824/// Check that class of this category is already completely declared.18251826if (!IDecl ||1827SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),1828diag::err_category_forward_interface,1829CategoryName == nullptr)) {1830// Create an invalid ObjCCategoryDecl to serve as context for1831// the enclosing method declarations. We mark the decl invalid1832// to make it clear that this isn't a valid AST.1833CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext,1834AtInterfaceLoc, ClassLoc, CategoryLoc,1835CategoryName, IDecl, typeParamList);1836CDecl->setInvalidDecl();1837SemaRef.CurContext->addDecl(CDecl);18381839if (!IDecl)1840Diag(ClassLoc, diag::err_undef_interface) << ClassName;1841ActOnObjCContainerStartDefinition(CDecl);1842return CDecl;1843}18441845if (!CategoryName && IDecl->getImplementation()) {1846Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;1847Diag(IDecl->getImplementation()->getLocation(),1848diag::note_implementation_declared);1849}18501851if (CategoryName) {1852/// Check for duplicate interface declaration for this category1853if (ObjCCategoryDecl *Previous1854= IDecl->FindCategoryDeclaration(CategoryName)) {1855// Class extensions can be declared multiple times, categories cannot.1856Diag(CategoryLoc, diag::warn_dup_category_def)1857<< ClassName << CategoryName;1858Diag(Previous->getLocation(), diag::note_previous_definition);1859}1860}18611862// If we have a type parameter list, check it.1863if (typeParamList) {1864if (auto prevTypeParamList = IDecl->getTypeParamList()) {1865if (checkTypeParamListConsistency(1866SemaRef, prevTypeParamList, typeParamList,1867CategoryName ? TypeParamListContext::Category1868: TypeParamListContext::Extension))1869typeParamList = nullptr;1870} else {1871Diag(typeParamList->getLAngleLoc(),1872diag::err_objc_parameterized_category_nonclass)1873<< (CategoryName != nullptr)1874<< ClassName1875<< typeParamList->getSourceRange();18761877typeParamList = nullptr;1878}1879}18801881CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,1882ClassLoc, CategoryLoc, CategoryName, IDecl,1883typeParamList);1884// FIXME: PushOnScopeChains?1885SemaRef.CurContext->addDecl(CDecl);18861887// Process the attributes before looking at protocols to ensure that the1888// availability attribute is attached to the category to provide availability1889// checking for protocol uses.1890SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList);1891SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);18921893if (NumProtoRefs) {1894diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs,1895NumProtoRefs, ProtoLocs);1896CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1897ProtoLocs, Context);1898// Protocols in the class extension belong to the class.1899if (CDecl->IsClassExtension())1900IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs,1901NumProtoRefs, Context);1902}19031904CheckObjCDeclScope(CDecl);1905ActOnObjCContainerStartDefinition(CDecl);1906return CDecl;1907}19081909/// ActOnStartCategoryImplementation - Perform semantic checks on the1910/// category implementation declaration and build an ObjCCategoryImplDecl1911/// object.1912ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation(1913SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName,1914SourceLocation ClassLoc, const IdentifierInfo *CatName,1915SourceLocation CatLoc, const ParsedAttributesView &Attrs) {1916ASTContext &Context = getASTContext();1917ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);1918ObjCCategoryDecl *CatIDecl = nullptr;1919if (IDecl && IDecl->hasDefinition()) {1920CatIDecl = IDecl->FindCategoryDeclaration(CatName);1921if (!CatIDecl) {1922// Category @implementation with no corresponding @interface.1923// Create and install one.1924CatIDecl =1925ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtCatImplLoc,1926ClassLoc, CatLoc, CatName, IDecl,1927/*typeParamList=*/nullptr);1928CatIDecl->setImplicit();1929}1930}19311932ObjCCategoryImplDecl *CDecl =1933ObjCCategoryImplDecl::Create(Context, SemaRef.CurContext, CatName, IDecl,1934ClassLoc, AtCatImplLoc, CatLoc);1935/// Check that class of this category is already completely declared.1936if (!IDecl) {1937Diag(ClassLoc, diag::err_undef_interface) << ClassName;1938CDecl->setInvalidDecl();1939} else if (SemaRef.RequireCompleteType(ClassLoc,1940Context.getObjCInterfaceType(IDecl),1941diag::err_undef_interface)) {1942CDecl->setInvalidDecl();1943}19441945SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs);1946SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);19471948// FIXME: PushOnScopeChains?1949SemaRef.CurContext->addDecl(CDecl);19501951// If the interface has the objc_runtime_visible attribute, we1952// cannot implement a category for it.1953if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) {1954Diag(ClassLoc, diag::err_objc_runtime_visible_category)1955<< IDecl->getDeclName();1956}19571958/// Check that CatName, category name, is not used in another implementation.1959if (CatIDecl) {1960if (CatIDecl->getImplementation()) {1961Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName1962<< CatName;1963Diag(CatIDecl->getImplementation()->getLocation(),1964diag::note_previous_definition);1965CDecl->setInvalidDecl();1966} else {1967CatIDecl->setImplementation(CDecl);1968// Warn on implementating category of deprecated class under1969// -Wdeprecated-implementations flag.1970DiagnoseObjCImplementedDeprecations(SemaRef, CatIDecl,1971CDecl->getLocation());1972}1973}19741975CheckObjCDeclScope(CDecl);1976ActOnObjCContainerStartDefinition(CDecl);1977return CDecl;1978}19791980ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation(1981SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName,1982SourceLocation ClassLoc, const IdentifierInfo *SuperClassname,1983SourceLocation SuperClassLoc, const ParsedAttributesView &Attrs) {1984ASTContext &Context = getASTContext();1985ObjCInterfaceDecl *IDecl = nullptr;1986// Check for another declaration kind with the same name.1987NamedDecl *PrevDecl = SemaRef.LookupSingleName(1988SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,1989SemaRef.forRedeclarationInCurContext());1990if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {1991Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;1992Diag(PrevDecl->getLocation(), diag::note_previous_definition);1993} else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {1994// FIXME: This will produce an error if the definition of the interface has1995// been imported from a module but is not visible.1996SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),1997diag::warn_undef_interface);1998} else {1999// We did not find anything with the name ClassName; try to correct for2000// typos in the class name.2001ObjCInterfaceValidatorCCC CCC{};2002TypoCorrection Corrected = SemaRef.CorrectTypo(2003DeclarationNameInfo(ClassName, ClassLoc), Sema::LookupOrdinaryName,2004SemaRef.TUScope, nullptr, CCC, Sema::CTK_NonError);2005if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {2006// Suggest the (potentially) correct interface name. Don't provide a2007// code-modification hint or use the typo name for recovery, because2008// this is just a warning. The program may actually be correct.2009SemaRef.diagnoseTypo(2010Corrected, PDiag(diag::warn_undef_interface_suggest) << ClassName,2011/*ErrorRecovery*/ false);2012} else {2013Diag(ClassLoc, diag::warn_undef_interface) << ClassName;2014}2015}20162017// Check that super class name is valid class name2018ObjCInterfaceDecl *SDecl = nullptr;2019if (SuperClassname) {2020// Check if a different kind of symbol declared in this scope.2021PrevDecl =2022SemaRef.LookupSingleName(SemaRef.TUScope, SuperClassname, SuperClassLoc,2023Sema::LookupOrdinaryName);2024if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {2025Diag(SuperClassLoc, diag::err_redefinition_different_kind)2026<< SuperClassname;2027Diag(PrevDecl->getLocation(), diag::note_previous_definition);2028} else {2029SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);2030if (SDecl && !SDecl->hasDefinition())2031SDecl = nullptr;2032if (!SDecl)2033Diag(SuperClassLoc, diag::err_undef_superclass)2034<< SuperClassname << ClassName;2035else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) {2036// This implementation and its interface do not have the same2037// super class.2038Diag(SuperClassLoc, diag::err_conflicting_super_class)2039<< SDecl->getDeclName();2040Diag(SDecl->getLocation(), diag::note_previous_definition);2041}2042}2043}20442045if (!IDecl) {2046// Legacy case of @implementation with no corresponding @interface.2047// Build, chain & install the interface decl into the identifier.20482049// FIXME: Do we support attributes on the @implementation? If so we should2050// copy them over.2051IDecl =2052ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtClassImplLoc,2053ClassName, /*typeParamList=*/nullptr,2054/*PrevDecl=*/nullptr, ClassLoc, true);2055SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);2056IDecl->startDefinition();2057if (SDecl) {2058IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(2059Context.getObjCInterfaceType(SDecl),2060SuperClassLoc));2061IDecl->setEndOfDefinitionLoc(SuperClassLoc);2062} else {2063IDecl->setEndOfDefinitionLoc(ClassLoc);2064}20652066SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);2067} else {2068// Mark the interface as being completed, even if it was just as2069// @class ....;2070// declaration; the user cannot reopen it.2071if (!IDecl->hasDefinition())2072IDecl->startDefinition();2073}20742075ObjCImplementationDecl *IMPDecl =2076ObjCImplementationDecl::Create(Context, SemaRef.CurContext, IDecl, SDecl,2077ClassLoc, AtClassImplLoc, SuperClassLoc);20782079SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs);2080SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl);20812082if (CheckObjCDeclScope(IMPDecl)) {2083ActOnObjCContainerStartDefinition(IMPDecl);2084return IMPDecl;2085}20862087// Check that there is no duplicate implementation of this class.2088if (IDecl->getImplementation()) {2089// FIXME: Don't leak everything!2090Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;2091Diag(IDecl->getImplementation()->getLocation(),2092diag::note_previous_definition);2093IMPDecl->setInvalidDecl();2094} else { // add it to the list.2095IDecl->setImplementation(IMPDecl);2096SemaRef.PushOnScopeChains(IMPDecl, SemaRef.TUScope);2097// Warn on implementating deprecated class under2098// -Wdeprecated-implementations flag.2099DiagnoseObjCImplementedDeprecations(SemaRef, IDecl, IMPDecl->getLocation());2100}21012102// If the superclass has the objc_runtime_visible attribute, we2103// cannot implement a subclass of it.2104if (IDecl->getSuperClass() &&2105IDecl->getSuperClass()->hasAttr<ObjCRuntimeVisibleAttr>()) {2106Diag(ClassLoc, diag::err_objc_runtime_visible_subclass)2107<< IDecl->getDeclName()2108<< IDecl->getSuperClass()->getDeclName();2109}21102111ActOnObjCContainerStartDefinition(IMPDecl);2112return IMPDecl;2113}21142115SemaObjC::DeclGroupPtrTy2116SemaObjC::ActOnFinishObjCImplementation(Decl *ObjCImpDecl,2117ArrayRef<Decl *> Decls) {2118SmallVector<Decl *, 64> DeclsInGroup;2119DeclsInGroup.reserve(Decls.size() + 1);21202121for (unsigned i = 0, e = Decls.size(); i != e; ++i) {2122Decl *Dcl = Decls[i];2123if (!Dcl)2124continue;2125if (Dcl->getDeclContext()->isFileContext())2126Dcl->setTopLevelDeclInObjCContainer();2127DeclsInGroup.push_back(Dcl);2128}21292130DeclsInGroup.push_back(ObjCImpDecl);21312132return SemaRef.BuildDeclaratorGroup(DeclsInGroup);2133}21342135void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,2136ObjCIvarDecl **ivars, unsigned numIvars,2137SourceLocation RBrace) {2138assert(ImpDecl && "missing implementation decl");2139ASTContext &Context = getASTContext();2140ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();2141if (!IDecl)2142return;2143/// Check case of non-existing \@interface decl.2144/// (legacy objective-c \@implementation decl without an \@interface decl).2145/// Add implementations's ivar to the synthesize class's ivar list.2146if (IDecl->isImplicitInterfaceDecl()) {2147IDecl->setEndOfDefinitionLoc(RBrace);2148// Add ivar's to class's DeclContext.2149for (unsigned i = 0, e = numIvars; i != e; ++i) {2150ivars[i]->setLexicalDeclContext(ImpDecl);2151// In a 'fragile' runtime the ivar was added to the implicit2152// ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is2153// only in the ObjCImplementationDecl. In the non-fragile case the ivar2154// therefore also needs to be propagated to the ObjCInterfaceDecl.2155if (!getLangOpts().ObjCRuntime.isFragile())2156IDecl->makeDeclVisibleInContext(ivars[i]);2157ImpDecl->addDecl(ivars[i]);2158}21592160return;2161}2162// If implementation has empty ivar list, just return.2163if (numIvars == 0)2164return;21652166assert(ivars && "missing @implementation ivars");2167if (getLangOpts().ObjCRuntime.isNonFragile()) {2168if (ImpDecl->getSuperClass())2169Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);2170for (unsigned i = 0; i < numIvars; i++) {2171ObjCIvarDecl* ImplIvar = ivars[i];2172if (const ObjCIvarDecl *ClsIvar =2173IDecl->getIvarDecl(ImplIvar->getIdentifier())) {2174Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);2175Diag(ClsIvar->getLocation(), diag::note_previous_definition);2176continue;2177}2178// Check class extensions (unnamed categories) for duplicate ivars.2179for (const auto *CDecl : IDecl->visible_extensions()) {2180if (const ObjCIvarDecl *ClsExtIvar =2181CDecl->getIvarDecl(ImplIvar->getIdentifier())) {2182Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);2183Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);2184continue;2185}2186}2187// Instance ivar to Implementation's DeclContext.2188ImplIvar->setLexicalDeclContext(ImpDecl);2189IDecl->makeDeclVisibleInContext(ImplIvar);2190ImpDecl->addDecl(ImplIvar);2191}2192return;2193}2194// Check interface's Ivar list against those in the implementation.2195// names and types must match.2196//2197unsigned j = 0;2198ObjCInterfaceDecl::ivar_iterator2199IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();2200for (; numIvars > 0 && IVI != IVE; ++IVI) {2201ObjCIvarDecl* ImplIvar = ivars[j++];2202ObjCIvarDecl* ClsIvar = *IVI;2203assert (ImplIvar && "missing implementation ivar");2204assert (ClsIvar && "missing class ivar");22052206// First, make sure the types match.2207if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) {2208Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)2209<< ImplIvar->getIdentifier()2210<< ImplIvar->getType() << ClsIvar->getType();2211Diag(ClsIvar->getLocation(), diag::note_previous_definition);2212} else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&2213ImplIvar->getBitWidthValue(Context) !=2214ClsIvar->getBitWidthValue(Context)) {2215Diag(ImplIvar->getBitWidth()->getBeginLoc(),2216diag::err_conflicting_ivar_bitwidth)2217<< ImplIvar->getIdentifier();2218Diag(ClsIvar->getBitWidth()->getBeginLoc(),2219diag::note_previous_definition);2220}2221// Make sure the names are identical.2222if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {2223Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)2224<< ImplIvar->getIdentifier() << ClsIvar->getIdentifier();2225Diag(ClsIvar->getLocation(), diag::note_previous_definition);2226}2227--numIvars;2228}22292230if (numIvars > 0)2231Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count);2232else if (IVI != IVE)2233Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);2234}22352236static bool shouldWarnUndefinedMethod(const ObjCMethodDecl *M) {2237// No point warning no definition of method which is 'unavailable'.2238return M->getAvailability() != AR_Unavailable;2239}22402241static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl,2242ObjCMethodDecl *method, bool &IncompleteImpl,2243unsigned DiagID,2244NamedDecl *NeededFor = nullptr) {2245if (!shouldWarnUndefinedMethod(method))2246return;22472248// FIXME: For now ignore 'IncompleteImpl'.2249// Previously we grouped all unimplemented methods under a single2250// warning, but some users strongly voiced that they would prefer2251// separate warnings. We will give that approach a try, as that2252// matches what we do with protocols.2253{2254const SemaBase::SemaDiagnosticBuilder &B =2255S.Diag(Impl->getLocation(), DiagID);2256B << method;2257if (NeededFor)2258B << NeededFor;22592260// Add an empty definition at the end of the @implementation.2261std::string FixItStr;2262llvm::raw_string_ostream Out(FixItStr);2263method->print(Out, Impl->getASTContext().getPrintingPolicy());2264Out << " {\n}\n\n";22652266SourceLocation Loc = Impl->getAtEndRange().getBegin();2267B << FixItHint::CreateInsertion(Loc, FixItStr);2268}22692270// Issue a note to the original declaration.2271SourceLocation MethodLoc = method->getBeginLoc();2272if (MethodLoc.isValid())2273S.Diag(MethodLoc, diag::note_method_declared_at) << method;2274}22752276/// Determines if type B can be substituted for type A. Returns true if we can2277/// guarantee that anything that the user will do to an object of type A can2278/// also be done to an object of type B. This is trivially true if the two2279/// types are the same, or if B is a subclass of A. It becomes more complex2280/// in cases where protocols are involved.2281///2282/// Object types in Objective-C describe the minimum requirements for an2283/// object, rather than providing a complete description of a type. For2284/// example, if A is a subclass of B, then B* may refer to an instance of A.2285/// The principle of substitutability means that we may use an instance of A2286/// anywhere that we may use an instance of B - it will implement all of the2287/// ivars of B and all of the methods of B.2288///2289/// This substitutability is important when type checking methods, because2290/// the implementation may have stricter type definitions than the interface.2291/// The interface specifies minimum requirements, but the implementation may2292/// have more accurate ones. For example, a method may privately accept2293/// instances of B, but only publish that it accepts instances of A. Any2294/// object passed to it will be type checked against B, and so will implicitly2295/// by a valid A*. Similarly, a method may return a subclass of the class that2296/// it is declared as returning.2297///2298/// This is most important when considering subclassing. A method in a2299/// subclass must accept any object as an argument that its superclass's2300/// implementation accepts. It may, however, accept a more general type2301/// without breaking substitutability (i.e. you can still use the subclass2302/// anywhere that you can use the superclass, but not vice versa). The2303/// converse requirement applies to return types: the return type for a2304/// subclass method must be a valid object of the kind that the superclass2305/// advertises, but it may be specified more accurately. This avoids the need2306/// for explicit down-casting by callers.2307///2308/// Note: This is a stricter requirement than for assignment.2309static bool isObjCTypeSubstitutable(ASTContext &Context,2310const ObjCObjectPointerType *A,2311const ObjCObjectPointerType *B,2312bool rejectId) {2313// Reject a protocol-unqualified id.2314if (rejectId && B->isObjCIdType()) return false;23152316// If B is a qualified id, then A must also be a qualified id and it must2317// implement all of the protocols in B. It may not be a qualified class.2318// For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a2319// stricter definition so it is not substitutable for id<A>.2320if (B->isObjCQualifiedIdType()) {2321return A->isObjCQualifiedIdType() &&2322Context.ObjCQualifiedIdTypesAreCompatible(A, B, false);2323}23242325/*2326// id is a special type that bypasses type checking completely. We want a2327// warning when it is used in one place but not another.2328if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false;232923302331// If B is a qualified id, then A must also be a qualified id (which it isn't2332// if we've got this far)2333if (B->isObjCQualifiedIdType()) return false;2334*/23352336// Now we know that A and B are (potentially-qualified) class types. The2337// normal rules for assignment apply.2338return Context.canAssignObjCInterfaces(A, B);2339}23402341static SourceRange getTypeRange(TypeSourceInfo *TSI) {2342return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());2343}23442345/// Determine whether two set of Objective-C declaration qualifiers conflict.2346static bool objcModifiersConflict(Decl::ObjCDeclQualifier x,2347Decl::ObjCDeclQualifier y) {2348return (x & ~Decl::OBJC_TQ_CSNullability) !=2349(y & ~Decl::OBJC_TQ_CSNullability);2350}23512352static bool CheckMethodOverrideReturn(Sema &S,2353ObjCMethodDecl *MethodImpl,2354ObjCMethodDecl *MethodDecl,2355bool IsProtocolMethodDecl,2356bool IsOverridingMode,2357bool Warn) {2358if (IsProtocolMethodDecl &&2359objcModifiersConflict(MethodDecl->getObjCDeclQualifier(),2360MethodImpl->getObjCDeclQualifier())) {2361if (Warn) {2362S.Diag(MethodImpl->getLocation(),2363(IsOverridingMode2364? diag::warn_conflicting_overriding_ret_type_modifiers2365: diag::warn_conflicting_ret_type_modifiers))2366<< MethodImpl->getDeclName()2367<< MethodImpl->getReturnTypeSourceRange();2368S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)2369<< MethodDecl->getReturnTypeSourceRange();2370}2371else2372return false;2373}2374if (Warn && IsOverridingMode &&2375!isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&2376!S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),2377MethodDecl->getReturnType(),2378false)) {2379auto nullabilityMethodImpl = *MethodImpl->getReturnType()->getNullability();2380auto nullabilityMethodDecl = *MethodDecl->getReturnType()->getNullability();2381S.Diag(MethodImpl->getLocation(),2382diag::warn_conflicting_nullability_attr_overriding_ret_types)2383<< DiagNullabilityKind(nullabilityMethodImpl,2384((MethodImpl->getObjCDeclQualifier() &2385Decl::OBJC_TQ_CSNullability) != 0))2386<< DiagNullabilityKind(nullabilityMethodDecl,2387((MethodDecl->getObjCDeclQualifier() &2388Decl::OBJC_TQ_CSNullability) != 0));2389S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);2390}23912392if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),2393MethodDecl->getReturnType()))2394return true;2395if (!Warn)2396return false;23972398unsigned DiagID =2399IsOverridingMode ? diag::warn_conflicting_overriding_ret_types2400: diag::warn_conflicting_ret_types;24012402// Mismatches between ObjC pointers go into a different warning2403// category, and sometimes they're even completely explicitly allowed.2404if (const ObjCObjectPointerType *ImplPtrTy =2405MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) {2406if (const ObjCObjectPointerType *IfacePtrTy =2407MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) {2408// Allow non-matching return types as long as they don't violate2409// the principle of substitutability. Specifically, we permit2410// return types that are subclasses of the declared return type,2411// or that are more-qualified versions of the declared type.2412if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))2413return false;24142415DiagID =2416IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types2417: diag::warn_non_covariant_ret_types;2418}2419}24202421S.Diag(MethodImpl->getLocation(), DiagID)2422<< MethodImpl->getDeclName() << MethodDecl->getReturnType()2423<< MethodImpl->getReturnType()2424<< MethodImpl->getReturnTypeSourceRange();2425S.Diag(MethodDecl->getLocation(), IsOverridingMode2426? diag::note_previous_declaration2427: diag::note_previous_definition)2428<< MethodDecl->getReturnTypeSourceRange();2429return false;2430}24312432static bool CheckMethodOverrideParam(Sema &S,2433ObjCMethodDecl *MethodImpl,2434ObjCMethodDecl *MethodDecl,2435ParmVarDecl *ImplVar,2436ParmVarDecl *IfaceVar,2437bool IsProtocolMethodDecl,2438bool IsOverridingMode,2439bool Warn) {2440if (IsProtocolMethodDecl &&2441objcModifiersConflict(ImplVar->getObjCDeclQualifier(),2442IfaceVar->getObjCDeclQualifier())) {2443if (Warn) {2444if (IsOverridingMode)2445S.Diag(ImplVar->getLocation(),2446diag::warn_conflicting_overriding_param_modifiers)2447<< getTypeRange(ImplVar->getTypeSourceInfo())2448<< MethodImpl->getDeclName();2449else S.Diag(ImplVar->getLocation(),2450diag::warn_conflicting_param_modifiers)2451<< getTypeRange(ImplVar->getTypeSourceInfo())2452<< MethodImpl->getDeclName();2453S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)2454<< getTypeRange(IfaceVar->getTypeSourceInfo());2455}2456else2457return false;2458}24592460QualType ImplTy = ImplVar->getType();2461QualType IfaceTy = IfaceVar->getType();2462if (Warn && IsOverridingMode &&2463!isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&2464!S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {2465S.Diag(ImplVar->getLocation(),2466diag::warn_conflicting_nullability_attr_overriding_param_types)2467<< DiagNullabilityKind(*ImplTy->getNullability(),2468((ImplVar->getObjCDeclQualifier() &2469Decl::OBJC_TQ_CSNullability) != 0))2470<< DiagNullabilityKind(*IfaceTy->getNullability(),2471((IfaceVar->getObjCDeclQualifier() &2472Decl::OBJC_TQ_CSNullability) != 0));2473S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);2474}2475if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))2476return true;24772478if (!Warn)2479return false;2480unsigned DiagID =2481IsOverridingMode ? diag::warn_conflicting_overriding_param_types2482: diag::warn_conflicting_param_types;24832484// Mismatches between ObjC pointers go into a different warning2485// category, and sometimes they're even completely explicitly allowed..2486if (const ObjCObjectPointerType *ImplPtrTy =2487ImplTy->getAs<ObjCObjectPointerType>()) {2488if (const ObjCObjectPointerType *IfacePtrTy =2489IfaceTy->getAs<ObjCObjectPointerType>()) {2490// Allow non-matching argument types as long as they don't2491// violate the principle of substitutability. Specifically, the2492// implementation must accept any objects that the superclass2493// accepts, however it may also accept others.2494if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))2495return false;24962497DiagID =2498IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types2499: diag::warn_non_contravariant_param_types;2500}2501}25022503S.Diag(ImplVar->getLocation(), DiagID)2504<< getTypeRange(ImplVar->getTypeSourceInfo())2505<< MethodImpl->getDeclName() << IfaceTy << ImplTy;2506S.Diag(IfaceVar->getLocation(),2507(IsOverridingMode ? diag::note_previous_declaration2508: diag::note_previous_definition))2509<< getTypeRange(IfaceVar->getTypeSourceInfo());2510return false;2511}25122513/// In ARC, check whether the conventional meanings of the two methods2514/// match. If they don't, it's a hard error.2515static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,2516ObjCMethodDecl *decl) {2517ObjCMethodFamily implFamily = impl->getMethodFamily();2518ObjCMethodFamily declFamily = decl->getMethodFamily();2519if (implFamily == declFamily) return false;25202521// Since conventions are sorted by selector, the only possibility is2522// that the types differ enough to cause one selector or the other2523// to fall out of the family.2524assert(implFamily == OMF_None || declFamily == OMF_None);25252526// No further diagnostics required on invalid declarations.2527if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true;25282529const ObjCMethodDecl *unmatched = impl;2530ObjCMethodFamily family = declFamily;2531unsigned errorID = diag::err_arc_lost_method_convention;2532unsigned noteID = diag::note_arc_lost_method_convention;2533if (declFamily == OMF_None) {2534unmatched = decl;2535family = implFamily;2536errorID = diag::err_arc_gained_method_convention;2537noteID = diag::note_arc_gained_method_convention;2538}25392540// Indexes into a %select clause in the diagnostic.2541enum FamilySelector {2542F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new2543};2544FamilySelector familySelector = FamilySelector();25452546switch (family) {2547case OMF_None: llvm_unreachable("logic error, no method convention");2548case OMF_retain:2549case OMF_release:2550case OMF_autorelease:2551case OMF_dealloc:2552case OMF_finalize:2553case OMF_retainCount:2554case OMF_self:2555case OMF_initialize:2556case OMF_performSelector:2557// Mismatches for these methods don't change ownership2558// conventions, so we don't care.2559return false;25602561case OMF_init: familySelector = F_init; break;2562case OMF_alloc: familySelector = F_alloc; break;2563case OMF_copy: familySelector = F_copy; break;2564case OMF_mutableCopy: familySelector = F_mutableCopy; break;2565case OMF_new: familySelector = F_new; break;2566}25672568enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn };2569ReasonSelector reasonSelector;25702571// The only reason these methods don't fall within their families is2572// due to unusual result types.2573if (unmatched->getReturnType()->isObjCObjectPointerType()) {2574reasonSelector = R_UnrelatedReturn;2575} else {2576reasonSelector = R_NonObjectReturn;2577}25782579S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector);2580S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector);25812582return true;2583}25842585void SemaObjC::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,2586ObjCMethodDecl *MethodDecl,2587bool IsProtocolMethodDecl) {2588if (getLangOpts().ObjCAutoRefCount &&2589checkMethodFamilyMismatch(SemaRef, ImpMethodDecl, MethodDecl))2590return;25912592CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,2593IsProtocolMethodDecl, false, true);25942595for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),2596IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),2597EF = MethodDecl->param_end();2598IM != EM && IF != EF; ++IM, ++IF) {2599CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, *IF,2600IsProtocolMethodDecl, false, true);2601}26022603if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {2604Diag(ImpMethodDecl->getLocation(),2605diag::warn_conflicting_variadic);2606Diag(MethodDecl->getLocation(), diag::note_previous_declaration);2607}2608}26092610void SemaObjC::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,2611ObjCMethodDecl *Overridden,2612bool IsProtocolMethodDecl) {26132614CheckMethodOverrideReturn(SemaRef, Method, Overridden, IsProtocolMethodDecl,2615true, true);26162617for (ObjCMethodDecl::param_iterator IM = Method->param_begin(),2618IF = Overridden->param_begin(), EM = Method->param_end(),2619EF = Overridden->param_end();2620IM != EM && IF != EF; ++IM, ++IF) {2621CheckMethodOverrideParam(SemaRef, Method, Overridden, *IM, *IF,2622IsProtocolMethodDecl, true, true);2623}26242625if (Method->isVariadic() != Overridden->isVariadic()) {2626Diag(Method->getLocation(),2627diag::warn_conflicting_overriding_variadic);2628Diag(Overridden->getLocation(), diag::note_previous_declaration);2629}2630}26312632/// WarnExactTypedMethods - This routine issues a warning if method2633/// implementation declaration matches exactly that of its declaration.2634void SemaObjC::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,2635ObjCMethodDecl *MethodDecl,2636bool IsProtocolMethodDecl) {2637ASTContext &Context = getASTContext();2638// don't issue warning when protocol method is optional because primary2639// class is not required to implement it and it is safe for protocol2640// to implement it.2641if (MethodDecl->getImplementationControl() ==2642ObjCImplementationControl::Optional)2643return;2644// don't issue warning when primary class's method is2645// deprecated/unavailable.2646if (MethodDecl->hasAttr<UnavailableAttr>() ||2647MethodDecl->hasAttr<DeprecatedAttr>())2648return;26492650bool match = CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,2651IsProtocolMethodDecl, false, false);2652if (match)2653for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),2654IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),2655EF = MethodDecl->param_end();2656IM != EM && IF != EF; ++IM, ++IF) {2657match = CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM,2658*IF, IsProtocolMethodDecl, false, false);2659if (!match)2660break;2661}2662if (match)2663match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic());2664if (match)2665match = !(MethodDecl->isClassMethod() &&2666MethodDecl->getSelector() == GetNullarySelector("load", Context));26672668if (match) {2669Diag(ImpMethodDecl->getLocation(),2670diag::warn_category_method_impl_match);2671Diag(MethodDecl->getLocation(), diag::note_method_declared_at)2672<< MethodDecl->getDeclName();2673}2674}26752676/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely2677/// improve the efficiency of selector lookups and type checking by associating2678/// with each protocol / interface / category the flattened instance tables. If2679/// we used an immutable set to keep the table then it wouldn't add significant2680/// memory cost and it would be handy for lookups.26812682typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet;2683typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet;26842685static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl,2686ProtocolNameSet &PNS) {2687if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())2688PNS.insert(PDecl->getIdentifier());2689for (const auto *PI : PDecl->protocols())2690findProtocolsWithExplicitImpls(PI, PNS);2691}26922693/// Recursively populates a set with all conformed protocols in a class2694/// hierarchy that have the 'objc_protocol_requires_explicit_implementation'2695/// attribute.2696static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super,2697ProtocolNameSet &PNS) {2698if (!Super)2699return;27002701for (const auto *I : Super->all_referenced_protocols())2702findProtocolsWithExplicitImpls(I, PNS);27032704findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS);2705}27062707/// CheckProtocolMethodDefs - This routine checks unimplemented methods2708/// Declared in protocol, and those referenced by it.2709static void CheckProtocolMethodDefs(2710Sema &S, ObjCImplDecl *Impl, ObjCProtocolDecl *PDecl, bool &IncompleteImpl,2711const SemaObjC::SelectorSet &InsMap, const SemaObjC::SelectorSet &ClsMap,2712ObjCContainerDecl *CDecl, LazyProtocolNameSet &ProtocolsExplictImpl) {2713ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);2714ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()2715: dyn_cast<ObjCInterfaceDecl>(CDecl);2716assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");27172718ObjCInterfaceDecl *Super = IDecl->getSuperClass();2719ObjCInterfaceDecl *NSIDecl = nullptr;27202721// If this protocol is marked 'objc_protocol_requires_explicit_implementation'2722// then we should check if any class in the super class hierarchy also2723// conforms to this protocol, either directly or via protocol inheritance.2724// If so, we can skip checking this protocol completely because we2725// know that a parent class already satisfies this protocol.2726//2727// Note: we could generalize this logic for all protocols, and merely2728// add the limit on looking at the super class chain for just2729// specially marked protocols. This may be a good optimization. This2730// change is restricted to 'objc_protocol_requires_explicit_implementation'2731// protocols for now for controlled evaluation.2732if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) {2733if (!ProtocolsExplictImpl) {2734ProtocolsExplictImpl.reset(new ProtocolNameSet);2735findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl);2736}2737if (ProtocolsExplictImpl->contains(PDecl->getIdentifier()))2738return;27392740// If no super class conforms to the protocol, we should not search2741// for methods in the super class to implicitly satisfy the protocol.2742Super = nullptr;2743}27442745if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {2746// check to see if class implements forwardInvocation method and objects2747// of this class are derived from 'NSProxy' so that to forward requests2748// from one object to another.2749// Under such conditions, which means that every method possible is2750// implemented in the class, we should not issue "Method definition not2751// found" warnings.2752// FIXME: Use a general GetUnarySelector method for this.2753const IdentifierInfo *II = &S.Context.Idents.get("forwardInvocation");2754Selector fISelector = S.Context.Selectors.getSelector(1, &II);2755if (InsMap.count(fISelector))2756// Is IDecl derived from 'NSProxy'? If so, no instance methods2757// need be implemented in the implementation.2758NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy"));2759}27602761// If this is a forward protocol declaration, get its definition.2762if (!PDecl->isThisDeclarationADefinition() &&2763PDecl->getDefinition())2764PDecl = PDecl->getDefinition();27652766// If a method lookup fails locally we still need to look and see if2767// the method was implemented by a base class or an inherited2768// protocol. This lookup is slow, but occurs rarely in correct code2769// and otherwise would terminate in a warning.27702771// check unimplemented instance methods.2772if (!NSIDecl)2773for (auto *method : PDecl->instance_methods()) {2774if (method->getImplementationControl() !=2775ObjCImplementationControl::Optional &&2776!method->isPropertyAccessor() &&2777!InsMap.count(method->getSelector()) &&2778(!Super || !Super->lookupMethod(2779method->getSelector(), true /* instance */,2780false /* shallowCategory */, true /* followsSuper */,2781nullptr /* category */))) {2782// If a method is not implemented in the category implementation but2783// has been declared in its primary class, superclass,2784// or in one of their protocols, no need to issue the warning.2785// This is because method will be implemented in the primary class2786// or one of its super class implementation.27872788// Ugly, but necessary. Method declared in protocol might have2789// have been synthesized due to a property declared in the class which2790// uses the protocol.2791if (ObjCMethodDecl *MethodInClass = IDecl->lookupMethod(2792method->getSelector(), true /* instance */,2793true /* shallowCategoryLookup */, false /* followSuper */))2794if (C || MethodInClass->isPropertyAccessor())2795continue;2796unsigned DIAG = diag::warn_unimplemented_protocol_method;2797if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {2798WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);2799}2800}2801}2802// check unimplemented class methods2803for (auto *method : PDecl->class_methods()) {2804if (method->getImplementationControl() !=2805ObjCImplementationControl::Optional &&2806!ClsMap.count(method->getSelector()) &&2807(!Super || !Super->lookupMethod(2808method->getSelector(), false /* class method */,2809false /* shallowCategoryLookup */,2810true /* followSuper */, nullptr /* category */))) {2811// See above comment for instance method lookups.2812if (C && IDecl->lookupMethod(method->getSelector(),2813false /* class */,2814true /* shallowCategoryLookup */,2815false /* followSuper */))2816continue;28172818unsigned DIAG = diag::warn_unimplemented_protocol_method;2819if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {2820WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);2821}2822}2823}2824// Check on this protocols's referenced protocols, recursively.2825for (auto *PI : PDecl->protocols())2826CheckProtocolMethodDefs(S, Impl, PI, IncompleteImpl, InsMap, ClsMap, CDecl,2827ProtocolsExplictImpl);2828}28292830/// MatchAllMethodDeclarations - Check methods declared in interface2831/// or protocol against those declared in their implementations.2832///2833void SemaObjC::MatchAllMethodDeclarations(2834const SelectorSet &InsMap, const SelectorSet &ClsMap,2835SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl,2836ObjCContainerDecl *CDecl, bool &IncompleteImpl, bool ImmediateClass,2837bool WarnCategoryMethodImpl) {2838// Check and see if instance methods in class interface have been2839// implemented in the implementation class. If so, their types match.2840for (auto *I : CDecl->instance_methods()) {2841if (!InsMapSeen.insert(I->getSelector()).second)2842continue;2843if (!I->isPropertyAccessor() &&2844!InsMap.count(I->getSelector())) {2845if (ImmediateClass)2846WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,2847diag::warn_undef_method_impl);2848continue;2849} else {2850ObjCMethodDecl *ImpMethodDecl =2851IMPDecl->getInstanceMethod(I->getSelector());2852assert(CDecl->getInstanceMethod(I->getSelector(), true/*AllowHidden*/) &&2853"Expected to find the method through lookup as well");2854// ImpMethodDecl may be null as in a @dynamic property.2855if (ImpMethodDecl) {2856// Skip property accessor function stubs.2857if (ImpMethodDecl->isSynthesizedAccessorStub())2858continue;2859if (!WarnCategoryMethodImpl)2860WarnConflictingTypedMethods(ImpMethodDecl, I,2861isa<ObjCProtocolDecl>(CDecl));2862else if (!I->isPropertyAccessor())2863WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));2864}2865}2866}28672868// Check and see if class methods in class interface have been2869// implemented in the implementation class. If so, their types match.2870for (auto *I : CDecl->class_methods()) {2871if (!ClsMapSeen.insert(I->getSelector()).second)2872continue;2873if (!I->isPropertyAccessor() &&2874!ClsMap.count(I->getSelector())) {2875if (ImmediateClass)2876WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,2877diag::warn_undef_method_impl);2878} else {2879ObjCMethodDecl *ImpMethodDecl =2880IMPDecl->getClassMethod(I->getSelector());2881assert(CDecl->getClassMethod(I->getSelector(), true/*AllowHidden*/) &&2882"Expected to find the method through lookup as well");2883// ImpMethodDecl may be null as in a @dynamic property.2884if (ImpMethodDecl) {2885// Skip property accessor function stubs.2886if (ImpMethodDecl->isSynthesizedAccessorStub())2887continue;2888if (!WarnCategoryMethodImpl)2889WarnConflictingTypedMethods(ImpMethodDecl, I,2890isa<ObjCProtocolDecl>(CDecl));2891else if (!I->isPropertyAccessor())2892WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));2893}2894}2895}28962897if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {2898// Also, check for methods declared in protocols inherited by2899// this protocol.2900for (auto *PI : PD->protocols())2901MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2902IMPDecl, PI, IncompleteImpl, false,2903WarnCategoryMethodImpl);2904}29052906if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {2907// when checking that methods in implementation match their declaration,2908// i.e. when WarnCategoryMethodImpl is false, check declarations in class2909// extension; as well as those in categories.2910if (!WarnCategoryMethodImpl) {2911for (auto *Cat : I->visible_categories())2912MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2913IMPDecl, Cat, IncompleteImpl,2914ImmediateClass && Cat->IsClassExtension(),2915WarnCategoryMethodImpl);2916} else {2917// Also methods in class extensions need be looked at next.2918for (auto *Ext : I->visible_extensions())2919MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2920IMPDecl, Ext, IncompleteImpl, false,2921WarnCategoryMethodImpl);2922}29232924// Check for any implementation of a methods declared in protocol.2925for (auto *PI : I->all_referenced_protocols())2926MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2927IMPDecl, PI, IncompleteImpl, false,2928WarnCategoryMethodImpl);29292930// FIXME. For now, we are not checking for exact match of methods2931// in category implementation and its primary class's super class.2932if (!WarnCategoryMethodImpl && I->getSuperClass())2933MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2934IMPDecl,2935I->getSuperClass(), IncompleteImpl, false);2936}2937}29382939/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in2940/// category matches with those implemented in its primary class and2941/// warns each time an exact match is found.2942void SemaObjC::CheckCategoryVsClassMethodMatches(2943ObjCCategoryImplDecl *CatIMPDecl) {2944// Get category's primary class.2945ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();2946if (!CatDecl)2947return;2948ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();2949if (!IDecl)2950return;2951ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();2952SelectorSet InsMap, ClsMap;29532954for (const auto *I : CatIMPDecl->instance_methods()) {2955Selector Sel = I->getSelector();2956// When checking for methods implemented in the category, skip over2957// those declared in category class's super class. This is because2958// the super class must implement the method.2959if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))2960continue;2961InsMap.insert(Sel);2962}29632964for (const auto *I : CatIMPDecl->class_methods()) {2965Selector Sel = I->getSelector();2966if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))2967continue;2968ClsMap.insert(Sel);2969}2970if (InsMap.empty() && ClsMap.empty())2971return;29722973SelectorSet InsMapSeen, ClsMapSeen;2974bool IncompleteImpl = false;2975MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2976CatIMPDecl, IDecl,2977IncompleteImpl, false,2978true /*WarnCategoryMethodImpl*/);2979}29802981void SemaObjC::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl,2982ObjCContainerDecl *CDecl,2983bool IncompleteImpl) {2984SelectorSet InsMap;2985// Check and see if instance methods in class interface have been2986// implemented in the implementation class.2987for (const auto *I : IMPDecl->instance_methods())2988InsMap.insert(I->getSelector());29892990// Add the selectors for getters/setters of @dynamic properties.2991for (const auto *PImpl : IMPDecl->property_impls()) {2992// We only care about @dynamic implementations.2993if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)2994continue;29952996const auto *P = PImpl->getPropertyDecl();2997if (!P) continue;29982999InsMap.insert(P->getGetterName());3000if (!P->getSetterName().isNull())3001InsMap.insert(P->getSetterName());3002}30033004// Check and see if properties declared in the interface have either 1)3005// an implementation or 2) there is a @synthesize/@dynamic implementation3006// of the property in the @implementation.3007if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {3008bool SynthesizeProperties = getLangOpts().ObjCDefaultSynthProperties &&3009getLangOpts().ObjCRuntime.isNonFragile() &&3010!IDecl->isObjCRequiresPropertyDefs();3011DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);3012}30133014// Diagnose null-resettable synthesized setters.3015diagnoseNullResettableSynthesizedSetters(IMPDecl);30163017SelectorSet ClsMap;3018for (const auto *I : IMPDecl->class_methods())3019ClsMap.insert(I->getSelector());30203021// Check for type conflict of methods declared in a class/protocol and3022// its implementation; if any.3023SelectorSet InsMapSeen, ClsMapSeen;3024MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,3025IMPDecl, CDecl,3026IncompleteImpl, true);30273028// check all methods implemented in category against those declared3029// in its primary class.3030if (ObjCCategoryImplDecl *CatDecl =3031dyn_cast<ObjCCategoryImplDecl>(IMPDecl))3032CheckCategoryVsClassMethodMatches(CatDecl);30333034// Check the protocol list for unimplemented methods in the @implementation3035// class.3036// Check and see if class methods in class interface have been3037// implemented in the implementation class.30383039LazyProtocolNameSet ExplicitImplProtocols;30403041if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {3042for (auto *PI : I->all_referenced_protocols())3043CheckProtocolMethodDefs(SemaRef, IMPDecl, PI, IncompleteImpl, InsMap,3044ClsMap, I, ExplicitImplProtocols);3045} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {3046// For extended class, unimplemented methods in its protocols will3047// be reported in the primary class.3048if (!C->IsClassExtension()) {3049for (auto *P : C->protocols())3050CheckProtocolMethodDefs(SemaRef, IMPDecl, P, IncompleteImpl, InsMap,3051ClsMap, CDecl, ExplicitImplProtocols);3052DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,3053/*SynthesizeProperties=*/false);3054}3055} else3056llvm_unreachable("invalid ObjCContainerDecl type.");3057}30583059SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardClassDeclaration(3060SourceLocation AtClassLoc, IdentifierInfo **IdentList,3061SourceLocation *IdentLocs, ArrayRef<ObjCTypeParamList *> TypeParamLists,3062unsigned NumElts) {3063ASTContext &Context = getASTContext();3064SmallVector<Decl *, 8> DeclsInGroup;3065for (unsigned i = 0; i != NumElts; ++i) {3066// Check for another declaration kind with the same name.3067NamedDecl *PrevDecl = SemaRef.LookupSingleName(3068SemaRef.TUScope, IdentList[i], IdentLocs[i], Sema::LookupOrdinaryName,3069SemaRef.forRedeclarationInCurContext());3070if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {3071// GCC apparently allows the following idiom:3072//3073// typedef NSObject < XCElementTogglerP > XCElementToggler;3074// @class XCElementToggler;3075//3076// Here we have chosen to ignore the forward class declaration3077// with a warning. Since this is the implied behavior.3078TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);3079if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {3080Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];3081Diag(PrevDecl->getLocation(), diag::note_previous_definition);3082} else {3083// a forward class declaration matching a typedef name of a class refers3084// to the underlying class. Just ignore the forward class with a warning3085// as this will force the intended behavior which is to lookup the3086// typedef name.3087if (isa<ObjCObjectType>(TDD->getUnderlyingType())) {3088Diag(AtClassLoc, diag::warn_forward_class_redefinition)3089<< IdentList[i];3090Diag(PrevDecl->getLocation(), diag::note_previous_definition);3091continue;3092}3093}3094}30953096// Create a declaration to describe this forward declaration.3097ObjCInterfaceDecl *PrevIDecl3098= dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);30993100IdentifierInfo *ClassName = IdentList[i];3101if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {3102// A previous decl with a different name is because of3103// @compatibility_alias, for example:3104// \code3105// @class NewImage;3106// @compatibility_alias OldImage NewImage;3107// \endcode3108// A lookup for 'OldImage' will return the 'NewImage' decl.3109//3110// In such a case use the real declaration name, instead of the alias one,3111// otherwise we will break IdentifierResolver and redecls-chain invariants.3112// FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl3113// has been aliased.3114ClassName = PrevIDecl->getIdentifier();3115}31163117// If this forward declaration has type parameters, compare them with the3118// type parameters of the previous declaration.3119ObjCTypeParamList *TypeParams = TypeParamLists[i];3120if (PrevIDecl && TypeParams) {3121if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) {3122// Check for consistency with the previous declaration.3123if (checkTypeParamListConsistency(3124SemaRef, PrevTypeParams, TypeParams,3125TypeParamListContext::ForwardDeclaration)) {3126TypeParams = nullptr;3127}3128} else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {3129// The @interface does not have type parameters. Complain.3130Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class)3131<< ClassName3132<< TypeParams->getSourceRange();3133Diag(Def->getLocation(), diag::note_defined_here)3134<< ClassName;31353136TypeParams = nullptr;3137}3138}31393140ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(3141Context, SemaRef.CurContext, AtClassLoc, ClassName, TypeParams,3142PrevIDecl, IdentLocs[i]);3143IDecl->setAtEndRange(IdentLocs[i]);31443145if (PrevIDecl)3146SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);31473148SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);3149CheckObjCDeclScope(IDecl);3150DeclsInGroup.push_back(IDecl);3151}31523153return SemaRef.BuildDeclaratorGroup(DeclsInGroup);3154}31553156static bool tryMatchRecordTypes(ASTContext &Context,3157SemaObjC::MethodMatchStrategy strategy,3158const Type *left, const Type *right);31593160static bool matchTypes(ASTContext &Context,3161SemaObjC::MethodMatchStrategy strategy, QualType leftQT,3162QualType rightQT) {3163const Type *left =3164Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr();3165const Type *right =3166Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr();31673168if (left == right) return true;31693170// If we're doing a strict match, the types have to match exactly.3171if (strategy == SemaObjC::MMS_strict)3172return false;31733174if (left->isIncompleteType() || right->isIncompleteType()) return false;31753176// Otherwise, use this absurdly complicated algorithm to try to3177// validate the basic, low-level compatibility of the two types.31783179// As a minimum, require the sizes and alignments to match.3180TypeInfo LeftTI = Context.getTypeInfo(left);3181TypeInfo RightTI = Context.getTypeInfo(right);3182if (LeftTI.Width != RightTI.Width)3183return false;31843185if (LeftTI.Align != RightTI.Align)3186return false;31873188// Consider all the kinds of non-dependent canonical types:3189// - functions and arrays aren't possible as return and parameter types31903191// - vector types of equal size can be arbitrarily mixed3192if (isa<VectorType>(left)) return isa<VectorType>(right);3193if (isa<VectorType>(right)) return false;31943195// - references should only match references of identical type3196// - structs, unions, and Objective-C objects must match more-or-less3197// exactly3198// - everything else should be a scalar3199if (!left->isScalarType() || !right->isScalarType())3200return tryMatchRecordTypes(Context, strategy, left, right);32013202// Make scalars agree in kind, except count bools as chars, and group3203// all non-member pointers together.3204Type::ScalarTypeKind leftSK = left->getScalarTypeKind();3205Type::ScalarTypeKind rightSK = right->getScalarTypeKind();3206if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral;3207if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral;3208if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer)3209leftSK = Type::STK_ObjCObjectPointer;3210if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer)3211rightSK = Type::STK_ObjCObjectPointer;32123213// Note that data member pointers and function member pointers don't3214// intermix because of the size differences.32153216return (leftSK == rightSK);3217}32183219static bool tryMatchRecordTypes(ASTContext &Context,3220SemaObjC::MethodMatchStrategy strategy,3221const Type *lt, const Type *rt) {3222assert(lt && rt && lt != rt);32233224if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false;3225RecordDecl *left = cast<RecordType>(lt)->getDecl();3226RecordDecl *right = cast<RecordType>(rt)->getDecl();32273228// Require union-hood to match.3229if (left->isUnion() != right->isUnion()) return false;32303231// Require an exact match if either is non-POD.3232if ((isa<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) ||3233(isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(right)->isPOD()))3234return false;32353236// Require size and alignment to match.3237TypeInfo LeftTI = Context.getTypeInfo(lt);3238TypeInfo RightTI = Context.getTypeInfo(rt);3239if (LeftTI.Width != RightTI.Width)3240return false;32413242if (LeftTI.Align != RightTI.Align)3243return false;32443245// Require fields to match.3246RecordDecl::field_iterator li = left->field_begin(), le = left->field_end();3247RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end();3248for (; li != le && ri != re; ++li, ++ri) {3249if (!matchTypes(Context, strategy, li->getType(), ri->getType()))3250return false;3251}3252return (li == le && ri == re);3253}32543255/// MatchTwoMethodDeclarations - Checks that two methods have matching type and3256/// returns true, or false, accordingly.3257/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons3258bool SemaObjC::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,3259const ObjCMethodDecl *right,3260MethodMatchStrategy strategy) {3261ASTContext &Context = getASTContext();3262if (!matchTypes(Context, strategy, left->getReturnType(),3263right->getReturnType()))3264return false;32653266// If either is hidden, it is not considered to match.3267if (!left->isUnconditionallyVisible() || !right->isUnconditionallyVisible())3268return false;32693270if (left->isDirectMethod() != right->isDirectMethod())3271return false;32723273if (getLangOpts().ObjCAutoRefCount &&3274(left->hasAttr<NSReturnsRetainedAttr>()3275!= right->hasAttr<NSReturnsRetainedAttr>() ||3276left->hasAttr<NSConsumesSelfAttr>()3277!= right->hasAttr<NSConsumesSelfAttr>()))3278return false;32793280ObjCMethodDecl::param_const_iterator3281li = left->param_begin(), le = left->param_end(), ri = right->param_begin(),3282re = right->param_end();32833284for (; li != le && ri != re; ++li, ++ri) {3285assert(ri != right->param_end() && "Param mismatch");3286const ParmVarDecl *lparm = *li, *rparm = *ri;32873288if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType()))3289return false;32903291if (getLangOpts().ObjCAutoRefCount &&3292lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>())3293return false;3294}3295return true;3296}32973298static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method,3299ObjCMethodDecl *MethodInList) {3300auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());3301auto *MethodInListProtocol =3302dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext());3303// If this method belongs to a protocol but the method in list does not, or3304// vice versa, we say the context is not the same.3305if ((MethodProtocol && !MethodInListProtocol) ||3306(!MethodProtocol && MethodInListProtocol))3307return false;33083309if (MethodProtocol && MethodInListProtocol)3310return true;33113312ObjCInterfaceDecl *MethodInterface = Method->getClassInterface();3313ObjCInterfaceDecl *MethodInListInterface =3314MethodInList->getClassInterface();3315return MethodInterface == MethodInListInterface;3316}33173318void SemaObjC::addMethodToGlobalList(ObjCMethodList *List,3319ObjCMethodDecl *Method) {3320// Record at the head of the list whether there were 0, 1, or >= 2 methods3321// inside categories.3322if (ObjCCategoryDecl *CD =3323dyn_cast<ObjCCategoryDecl>(Method->getDeclContext()))3324if (!CD->IsClassExtension() && List->getBits() < 2)3325List->setBits(List->getBits() + 1);33263327// If the list is empty, make it a singleton list.3328if (List->getMethod() == nullptr) {3329List->setMethod(Method);3330List->setNext(nullptr);3331return;3332}33333334// We've seen a method with this name, see if we have already seen this type3335// signature.3336ObjCMethodList *Previous = List;3337ObjCMethodList *ListWithSameDeclaration = nullptr;3338for (; List; Previous = List, List = List->getNext()) {3339// If we are building a module, keep all of the methods.3340if (getLangOpts().isCompilingModule())3341continue;33423343bool SameDeclaration = MatchTwoMethodDeclarations(Method,3344List->getMethod());3345// Looking for method with a type bound requires the correct context exists.3346// We need to insert a method into the list if the context is different.3347// If the method's declaration matches the list3348// a> the method belongs to a different context: we need to insert it, in3349// order to emit the availability message, we need to prioritize over3350// availability among the methods with the same declaration.3351// b> the method belongs to the same context: there is no need to insert a3352// new entry.3353// If the method's declaration does not match the list, we insert it to the3354// end.3355if (!SameDeclaration ||3356!isMethodContextSameForKindofLookup(Method, List->getMethod())) {3357// Even if two method types do not match, we would like to say3358// there is more than one declaration so unavailability/deprecated3359// warning is not too noisy.3360if (!Method->isDefined())3361List->setHasMoreThanOneDecl(true);33623363// For methods with the same declaration, the one that is deprecated3364// should be put in the front for better diagnostics.3365if (Method->isDeprecated() && SameDeclaration &&3366!ListWithSameDeclaration && !List->getMethod()->isDeprecated())3367ListWithSameDeclaration = List;33683369if (Method->isUnavailable() && SameDeclaration &&3370!ListWithSameDeclaration &&3371List->getMethod()->getAvailability() < AR_Deprecated)3372ListWithSameDeclaration = List;3373continue;3374}33753376ObjCMethodDecl *PrevObjCMethod = List->getMethod();33773378// Propagate the 'defined' bit.3379if (Method->isDefined())3380PrevObjCMethod->setDefined(true);3381else {3382// Objective-C doesn't allow an @interface for a class after its3383// @implementation. So if Method is not defined and there already is3384// an entry for this type signature, Method has to be for a different3385// class than PrevObjCMethod.3386List->setHasMoreThanOneDecl(true);3387}33883389// If a method is deprecated, push it in the global pool.3390// This is used for better diagnostics.3391if (Method->isDeprecated()) {3392if (!PrevObjCMethod->isDeprecated())3393List->setMethod(Method);3394}3395// If the new method is unavailable, push it into global pool3396// unless previous one is deprecated.3397if (Method->isUnavailable()) {3398if (PrevObjCMethod->getAvailability() < AR_Deprecated)3399List->setMethod(Method);3400}34013402return;3403}34043405// We have a new signature for an existing method - add it.3406// This is extremely rare. Only 1% of Cocoa selectors are "overloaded".3407ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate<ObjCMethodList>();34083409// We insert it right before ListWithSameDeclaration.3410if (ListWithSameDeclaration) {3411auto *List = new (Mem) ObjCMethodList(*ListWithSameDeclaration);3412// FIXME: should we clear the other bits in ListWithSameDeclaration?3413ListWithSameDeclaration->setMethod(Method);3414ListWithSameDeclaration->setNext(List);3415return;3416}34173418Previous->setNext(new (Mem) ObjCMethodList(Method));3419}34203421/// Read the contents of the method pool for a given selector from3422/// external storage.3423void SemaObjC::ReadMethodPool(Selector Sel) {3424assert(SemaRef.ExternalSource && "We need an external AST source");3425SemaRef.ExternalSource->ReadMethodPool(Sel);3426}34273428void SemaObjC::updateOutOfDateSelector(Selector Sel) {3429if (!SemaRef.ExternalSource)3430return;3431SemaRef.ExternalSource->updateOutOfDateSelector(Sel);3432}34333434void SemaObjC::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,3435bool instance) {3436// Ignore methods of invalid containers.3437if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())3438return;34393440if (SemaRef.ExternalSource)3441ReadMethodPool(Method->getSelector());34423443GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector());3444if (Pos == MethodPool.end())3445Pos = MethodPool3446.insert(std::make_pair(Method->getSelector(),3447GlobalMethodPool::Lists()))3448.first;34493450Method->setDefined(impl);34513452ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second;3453addMethodToGlobalList(&Entry, Method);3454}34553456/// Determines if this is an "acceptable" loose mismatch in the global3457/// method pool. This exists mostly as a hack to get around certain3458/// global mismatches which we can't afford to make warnings / errors.3459/// Really, what we want is a way to take a method out of the global3460/// method pool.3461static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,3462ObjCMethodDecl *other) {3463if (!chosen->isInstanceMethod())3464return false;34653466if (chosen->isDirectMethod() != other->isDirectMethod())3467return false;34683469Selector sel = chosen->getSelector();3470if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length")3471return false;34723473// Don't complain about mismatches for -length if the method we3474// chose has an integral result type.3475return (chosen->getReturnType()->isIntegerType());3476}34773478/// Return true if the given method is wthin the type bound.3479static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method,3480const ObjCObjectType *TypeBound) {3481if (!TypeBound)3482return true;34833484if (TypeBound->isObjCId())3485// FIXME: should we handle the case of bounding to id<A, B> differently?3486return true;34873488auto *BoundInterface = TypeBound->getInterface();3489assert(BoundInterface && "unexpected object type!");34903491// Check if the Method belongs to a protocol. We should allow any method3492// defined in any protocol, because any subclass could adopt the protocol.3493auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());3494if (MethodProtocol) {3495return true;3496}34973498// If the Method belongs to a class, check if it belongs to the class3499// hierarchy of the class bound.3500if (ObjCInterfaceDecl *MethodInterface = Method->getClassInterface()) {3501// We allow methods declared within classes that are part of the hierarchy3502// of the class bound (superclass of, subclass of, or the same as the class3503// bound).3504return MethodInterface == BoundInterface ||3505MethodInterface->isSuperClassOf(BoundInterface) ||3506BoundInterface->isSuperClassOf(MethodInterface);3507}3508llvm_unreachable("unknown method context");3509}35103511/// We first select the type of the method: Instance or Factory, then collect3512/// all methods with that type.3513bool SemaObjC::CollectMultipleMethodsInGlobalPool(3514Selector Sel, SmallVectorImpl<ObjCMethodDecl *> &Methods,3515bool InstanceFirst, bool CheckTheOther, const ObjCObjectType *TypeBound) {3516if (SemaRef.ExternalSource)3517ReadMethodPool(Sel);35183519GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3520if (Pos == MethodPool.end())3521return false;35223523// Gather the non-hidden methods.3524ObjCMethodList &MethList = InstanceFirst ? Pos->second.first :3525Pos->second.second;3526for (ObjCMethodList *M = &MethList; M; M = M->getNext())3527if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {3528if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))3529Methods.push_back(M->getMethod());3530}35313532// Return if we find any method with the desired kind.3533if (!Methods.empty())3534return Methods.size() > 1;35353536if (!CheckTheOther)3537return false;35383539// Gather the other kind.3540ObjCMethodList &MethList2 = InstanceFirst ? Pos->second.second :3541Pos->second.first;3542for (ObjCMethodList *M = &MethList2; M; M = M->getNext())3543if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {3544if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))3545Methods.push_back(M->getMethod());3546}35473548return Methods.size() > 1;3549}35503551bool SemaObjC::AreMultipleMethodsInGlobalPool(3552Selector Sel, ObjCMethodDecl *BestMethod, SourceRange R,3553bool receiverIdOrClass, SmallVectorImpl<ObjCMethodDecl *> &Methods) {3554// Diagnose finding more than one method in global pool.3555SmallVector<ObjCMethodDecl *, 4> FilteredMethods;3556FilteredMethods.push_back(BestMethod);35573558for (auto *M : Methods)3559if (M != BestMethod && !M->hasAttr<UnavailableAttr>())3560FilteredMethods.push_back(M);35613562if (FilteredMethods.size() > 1)3563DiagnoseMultipleMethodInGlobalPool(FilteredMethods, Sel, R,3564receiverIdOrClass);35653566GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3567// Test for no method in the pool which should not trigger any warning by3568// caller.3569if (Pos == MethodPool.end())3570return true;3571ObjCMethodList &MethList =3572BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;3573return MethList.hasMoreThanOneDecl();3574}35753576ObjCMethodDecl *SemaObjC::LookupMethodInGlobalPool(Selector Sel, SourceRange R,3577bool receiverIdOrClass,3578bool instance) {3579if (SemaRef.ExternalSource)3580ReadMethodPool(Sel);35813582GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3583if (Pos == MethodPool.end())3584return nullptr;35853586// Gather the non-hidden methods.3587ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;3588SmallVector<ObjCMethodDecl *, 4> Methods;3589for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {3590if (M->getMethod() && M->getMethod()->isUnconditionallyVisible())3591return M->getMethod();3592}3593return nullptr;3594}35953596void SemaObjC::DiagnoseMultipleMethodInGlobalPool(3597SmallVectorImpl<ObjCMethodDecl *> &Methods, Selector Sel, SourceRange R,3598bool receiverIdOrClass) {3599// We found multiple methods, so we may have to complain.3600bool issueDiagnostic = false, issueError = false;36013602// We support a warning which complains about *any* difference in3603// method signature.3604bool strictSelectorMatch =3605receiverIdOrClass &&3606!getDiagnostics().isIgnored(diag::warn_strict_multiple_method_decl,3607R.getBegin());3608if (strictSelectorMatch) {3609for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3610if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {3611issueDiagnostic = true;3612break;3613}3614}3615}36163617// If we didn't see any strict differences, we won't see any loose3618// differences. In ARC, however, we also need to check for loose3619// mismatches, because most of them are errors.3620if (!strictSelectorMatch ||3621(issueDiagnostic && getLangOpts().ObjCAutoRefCount))3622for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3623// This checks if the methods differ in type mismatch.3624if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) &&3625!isAcceptableMethodMismatch(Methods[0], Methods[I])) {3626issueDiagnostic = true;3627if (getLangOpts().ObjCAutoRefCount)3628issueError = true;3629break;3630}3631}36323633if (issueDiagnostic) {3634if (issueError)3635Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;3636else if (strictSelectorMatch)3637Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;3638else3639Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;36403641Diag(Methods[0]->getBeginLoc(),3642issueError ? diag::note_possibility : diag::note_using)3643<< Methods[0]->getSourceRange();3644for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3645Diag(Methods[I]->getBeginLoc(), diag::note_also_found)3646<< Methods[I]->getSourceRange();3647}3648}3649}36503651ObjCMethodDecl *SemaObjC::LookupImplementedMethodInGlobalPool(Selector Sel) {3652GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3653if (Pos == MethodPool.end())3654return nullptr;36553656GlobalMethodPool::Lists &Methods = Pos->second;3657for (const ObjCMethodList *Method = &Methods.first; Method;3658Method = Method->getNext())3659if (Method->getMethod() &&3660(Method->getMethod()->isDefined() ||3661Method->getMethod()->isPropertyAccessor()))3662return Method->getMethod();36633664for (const ObjCMethodList *Method = &Methods.second; Method;3665Method = Method->getNext())3666if (Method->getMethod() &&3667(Method->getMethod()->isDefined() ||3668Method->getMethod()->isPropertyAccessor()))3669return Method->getMethod();3670return nullptr;3671}36723673static void3674HelperSelectorsForTypoCorrection(3675SmallVectorImpl<const ObjCMethodDecl *> &BestMethod,3676StringRef Typo, const ObjCMethodDecl * Method) {3677const unsigned MaxEditDistance = 1;3678unsigned BestEditDistance = MaxEditDistance + 1;3679std::string MethodName = Method->getSelector().getAsString();36803681unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size());3682if (MinPossibleEditDistance > 0 &&3683Typo.size() / MinPossibleEditDistance < 1)3684return;3685unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance);3686if (EditDistance > MaxEditDistance)3687return;3688if (EditDistance == BestEditDistance)3689BestMethod.push_back(Method);3690else if (EditDistance < BestEditDistance) {3691BestMethod.clear();3692BestMethod.push_back(Method);3693}3694}36953696static bool HelperIsMethodInObjCType(Sema &S, Selector Sel,3697QualType ObjectType) {3698if (ObjectType.isNull())3699return true;3700if (S.ObjC().LookupMethodInObjectType(Sel, ObjectType,3701true /*Instance method*/))3702return true;3703return S.ObjC().LookupMethodInObjectType(Sel, ObjectType,3704false /*Class method*/) != nullptr;3705}37063707const ObjCMethodDecl *3708SemaObjC::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) {3709unsigned NumArgs = Sel.getNumArgs();3710SmallVector<const ObjCMethodDecl *, 8> Methods;3711bool ObjectIsId = true, ObjectIsClass = true;3712if (ObjectType.isNull())3713ObjectIsId = ObjectIsClass = false;3714else if (!ObjectType->isObjCObjectPointerType())3715return nullptr;3716else if (const ObjCObjectPointerType *ObjCPtr =3717ObjectType->getAsObjCInterfacePointerType()) {3718ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);3719ObjectIsId = ObjectIsClass = false;3720}3721else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType())3722ObjectIsClass = false;3723else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())3724ObjectIsId = false;3725else3726return nullptr;37273728for (GlobalMethodPool::iterator b = MethodPool.begin(),3729e = MethodPool.end(); b != e; b++) {3730// instance methods3731for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())3732if (M->getMethod() &&3733(M->getMethod()->getSelector().getNumArgs() == NumArgs) &&3734(M->getMethod()->getSelector() != Sel)) {3735if (ObjectIsId)3736Methods.push_back(M->getMethod());3737else if (!ObjectIsClass &&3738HelperIsMethodInObjCType(3739SemaRef, M->getMethod()->getSelector(), ObjectType))3740Methods.push_back(M->getMethod());3741}3742// class methods3743for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())3744if (M->getMethod() &&3745(M->getMethod()->getSelector().getNumArgs() == NumArgs) &&3746(M->getMethod()->getSelector() != Sel)) {3747if (ObjectIsClass)3748Methods.push_back(M->getMethod());3749else if (!ObjectIsId &&3750HelperIsMethodInObjCType(3751SemaRef, M->getMethod()->getSelector(), ObjectType))3752Methods.push_back(M->getMethod());3753}3754}37553756SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;3757for (unsigned i = 0, e = Methods.size(); i < e; i++) {3758HelperSelectorsForTypoCorrection(SelectedMethods,3759Sel.getAsString(), Methods[i]);3760}3761return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr;3762}37633764/// DiagnoseDuplicateIvars -3765/// Check for duplicate ivars in the entire class at the start of3766/// \@implementation. This becomes necessary because class extension can3767/// add ivars to a class in random order which will not be known until3768/// class's \@implementation is seen.3769void SemaObjC::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,3770ObjCInterfaceDecl *SID) {3771for (auto *Ivar : ID->ivars()) {3772if (Ivar->isInvalidDecl())3773continue;3774if (IdentifierInfo *II = Ivar->getIdentifier()) {3775ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II);3776if (prevIvar) {3777Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;3778Diag(prevIvar->getLocation(), diag::note_previous_declaration);3779Ivar->setInvalidDecl();3780}3781}3782}3783}37843785/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled.3786static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {3787if (S.getLangOpts().ObjCWeak) return;37883789for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin();3790ivar; ivar = ivar->getNextIvar()) {3791if (ivar->isInvalidDecl()) continue;3792if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {3793if (S.getLangOpts().ObjCWeakRuntime) {3794S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled);3795} else {3796S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime);3797}3798}3799}3800}38013802/// Diagnose attempts to use flexible array member with retainable object type.3803static void DiagnoseRetainableFlexibleArrayMember(Sema &S,3804ObjCInterfaceDecl *ID) {3805if (!S.getLangOpts().ObjCAutoRefCount)3806return;38073808for (auto ivar = ID->all_declared_ivar_begin(); ivar;3809ivar = ivar->getNextIvar()) {3810if (ivar->isInvalidDecl())3811continue;3812QualType IvarTy = ivar->getType();3813if (IvarTy->isIncompleteArrayType() &&3814(IvarTy.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) &&3815IvarTy->isObjCLifetimeType()) {3816S.Diag(ivar->getLocation(), diag::err_flexible_array_arc_retainable);3817ivar->setInvalidDecl();3818}3819}3820}38213822SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const {3823switch (SemaRef.CurContext->getDeclKind()) {3824case Decl::ObjCInterface:3825return SemaObjC::OCK_Interface;3826case Decl::ObjCProtocol:3827return SemaObjC::OCK_Protocol;3828case Decl::ObjCCategory:3829if (cast<ObjCCategoryDecl>(SemaRef.CurContext)->IsClassExtension())3830return SemaObjC::OCK_ClassExtension;3831return SemaObjC::OCK_Category;3832case Decl::ObjCImplementation:3833return SemaObjC::OCK_Implementation;3834case Decl::ObjCCategoryImpl:3835return SemaObjC::OCK_CategoryImplementation;38363837default:3838return SemaObjC::OCK_None;3839}3840}38413842static bool IsVariableSizedType(QualType T) {3843if (T->isIncompleteArrayType())3844return true;3845const auto *RecordTy = T->getAs<RecordType>();3846return (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember());3847}38483849static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {3850ObjCInterfaceDecl *IntfDecl = nullptr;3851ObjCInterfaceDecl::ivar_range Ivars = llvm::make_range(3852ObjCInterfaceDecl::ivar_iterator(), ObjCInterfaceDecl::ivar_iterator());3853if ((IntfDecl = dyn_cast<ObjCInterfaceDecl>(OCD))) {3854Ivars = IntfDecl->ivars();3855} else if (auto *ImplDecl = dyn_cast<ObjCImplementationDecl>(OCD)) {3856IntfDecl = ImplDecl->getClassInterface();3857Ivars = ImplDecl->ivars();3858} else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(OCD)) {3859if (CategoryDecl->IsClassExtension()) {3860IntfDecl = CategoryDecl->getClassInterface();3861Ivars = CategoryDecl->ivars();3862}3863}38643865// Check if variable sized ivar is in interface and visible to subclasses.3866if (!isa<ObjCInterfaceDecl>(OCD)) {3867for (auto *ivar : Ivars) {3868if (!ivar->isInvalidDecl() && IsVariableSizedType(ivar->getType())) {3869S.Diag(ivar->getLocation(), diag::warn_variable_sized_ivar_visibility)3870<< ivar->getDeclName() << ivar->getType();3871}3872}3873}38743875// Subsequent checks require interface decl.3876if (!IntfDecl)3877return;38783879// Check if variable sized ivar is followed by another ivar.3880for (ObjCIvarDecl *ivar = IntfDecl->all_declared_ivar_begin(); ivar;3881ivar = ivar->getNextIvar()) {3882if (ivar->isInvalidDecl() || !ivar->getNextIvar())3883continue;3884QualType IvarTy = ivar->getType();3885bool IsInvalidIvar = false;3886if (IvarTy->isIncompleteArrayType()) {3887S.Diag(ivar->getLocation(), diag::err_flexible_array_not_at_end)3888<< ivar->getDeclName() << IvarTy3889<< llvm::to_underlying(TagTypeKind::Class); // Use "class" for Obj-C.3890IsInvalidIvar = true;3891} else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) {3892if (RecordTy->getDecl()->hasFlexibleArrayMember()) {3893S.Diag(ivar->getLocation(),3894diag::err_objc_variable_sized_type_not_at_end)3895<< ivar->getDeclName() << IvarTy;3896IsInvalidIvar = true;3897}3898}3899if (IsInvalidIvar) {3900S.Diag(ivar->getNextIvar()->getLocation(),3901diag::note_next_ivar_declaration)3902<< ivar->getNextIvar()->getSynthesize();3903ivar->setInvalidDecl();3904}3905}39063907// Check if ObjC container adds ivars after variable sized ivar in superclass.3908// Perform the check only if OCD is the first container to declare ivars to3909// avoid multiple warnings for the same ivar.3910ObjCIvarDecl *FirstIvar =3911(Ivars.begin() == Ivars.end()) ? nullptr : *Ivars.begin();3912if (FirstIvar && (FirstIvar == IntfDecl->all_declared_ivar_begin())) {3913const ObjCInterfaceDecl *SuperClass = IntfDecl->getSuperClass();3914while (SuperClass && SuperClass->ivar_empty())3915SuperClass = SuperClass->getSuperClass();3916if (SuperClass) {3917auto IvarIter = SuperClass->ivar_begin();3918std::advance(IvarIter, SuperClass->ivar_size() - 1);3919const ObjCIvarDecl *LastIvar = *IvarIter;3920if (IsVariableSizedType(LastIvar->getType())) {3921S.Diag(FirstIvar->getLocation(),3922diag::warn_superclass_variable_sized_type_not_at_end)3923<< FirstIvar->getDeclName() << LastIvar->getDeclName()3924<< LastIvar->getType() << SuperClass->getDeclName();3925S.Diag(LastIvar->getLocation(), diag::note_entity_declared_at)3926<< LastIvar->getDeclName();3927}3928}3929}3930}39313932static void DiagnoseCategoryDirectMembersProtocolConformance(3933Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl);39343935static void DiagnoseCategoryDirectMembersProtocolConformance(3936Sema &S, ObjCCategoryDecl *CDecl,3937const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) {3938for (auto *PI : Protocols)3939DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl);3940}39413942static void DiagnoseCategoryDirectMembersProtocolConformance(3943Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) {3944if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())3945PDecl = PDecl->getDefinition();39463947llvm::SmallVector<const Decl *, 4> DirectMembers;3948const auto *IDecl = CDecl->getClassInterface();3949for (auto *MD : PDecl->methods()) {3950if (!MD->isPropertyAccessor()) {3951if (const auto *CMD =3952IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) {3953if (CMD->isDirectMethod())3954DirectMembers.push_back(CMD);3955}3956}3957}3958for (auto *PD : PDecl->properties()) {3959if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass(3960PD->getIdentifier(),3961PD->isClassProperty()3962? ObjCPropertyQueryKind::OBJC_PR_query_class3963: ObjCPropertyQueryKind::OBJC_PR_query_instance)) {3964if (CPD->isDirectProperty())3965DirectMembers.push_back(CPD);3966}3967}3968if (!DirectMembers.empty()) {3969S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance)3970<< CDecl->IsClassExtension() << CDecl << PDecl << IDecl;3971for (const auto *MD : DirectMembers)3972S.Diag(MD->getLocation(), diag::note_direct_member_here);3973return;3974}39753976// Check on this protocols's referenced protocols, recursively.3977DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl,3978PDecl->protocols());3979}39803981// Note: For class/category implementations, allMethods is always null.3982Decl *SemaObjC::ActOnAtEnd(Scope *S, SourceRange AtEnd,3983ArrayRef<Decl *> allMethods,3984ArrayRef<DeclGroupPtrTy> allTUVars) {3985ASTContext &Context = getASTContext();3986if (getObjCContainerKind() == SemaObjC::OCK_None)3987return nullptr;39883989assert(AtEnd.isValid() && "Invalid location for '@end'");39903991auto *OCD = cast<ObjCContainerDecl>(SemaRef.CurContext);3992Decl *ClassDecl = OCD;39933994bool isInterfaceDeclKind =3995isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)3996|| isa<ObjCProtocolDecl>(ClassDecl);3997bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);39983999// Make synthesized accessor stub functions visible.4000// ActOnPropertyImplDecl() creates them as not visible in case4001// they are overridden by an explicit method that is encountered4002// later.4003if (auto *OID = dyn_cast<ObjCImplementationDecl>(SemaRef.CurContext)) {4004for (auto *PropImpl : OID->property_impls()) {4005if (auto *Getter = PropImpl->getGetterMethodDecl())4006if (Getter->isSynthesizedAccessorStub())4007OID->addDecl(Getter);4008if (auto *Setter = PropImpl->getSetterMethodDecl())4009if (Setter->isSynthesizedAccessorStub())4010OID->addDecl(Setter);4011}4012}40134014// FIXME: Remove these and use the ObjCContainerDecl/DeclContext.4015llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;4016llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;40174018for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) {4019ObjCMethodDecl *Method =4020cast_or_null<ObjCMethodDecl>(allMethods[i]);40214022if (!Method) continue; // Already issued a diagnostic.4023if (Method->isInstanceMethod()) {4024/// Check for instance method of the same name with incompatible types4025const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];4026bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)4027: false;4028if ((isInterfaceDeclKind && PrevMethod && !match)4029|| (checkIdenticalMethods && match)) {4030Diag(Method->getLocation(), diag::err_duplicate_method_decl)4031<< Method->getDeclName();4032Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4033Method->setInvalidDecl();4034} else {4035if (PrevMethod) {4036Method->setAsRedeclaration(PrevMethod);4037if (!Context.getSourceManager().isInSystemHeader(4038Method->getLocation()))4039Diag(Method->getLocation(), diag::warn_duplicate_method_decl)4040<< Method->getDeclName();4041Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4042}4043InsMap[Method->getSelector()] = Method;4044/// The following allows us to typecheck messages to "id".4045AddInstanceMethodToGlobalPool(Method);4046}4047} else {4048/// Check for class method of the same name with incompatible types4049const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];4050bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)4051: false;4052if ((isInterfaceDeclKind && PrevMethod && !match)4053|| (checkIdenticalMethods && match)) {4054Diag(Method->getLocation(), diag::err_duplicate_method_decl)4055<< Method->getDeclName();4056Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4057Method->setInvalidDecl();4058} else {4059if (PrevMethod) {4060Method->setAsRedeclaration(PrevMethod);4061if (!Context.getSourceManager().isInSystemHeader(4062Method->getLocation()))4063Diag(Method->getLocation(), diag::warn_duplicate_method_decl)4064<< Method->getDeclName();4065Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4066}4067ClsMap[Method->getSelector()] = Method;4068AddFactoryMethodToGlobalPool(Method);4069}4070}4071}4072if (isa<ObjCInterfaceDecl>(ClassDecl)) {4073// Nothing to do here.4074} else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {4075// Categories are used to extend the class by declaring new methods.4076// By the same token, they are also used to add new properties. No4077// need to compare the added property to those in the class.40784079if (C->IsClassExtension()) {4080ObjCInterfaceDecl *CCPrimary = C->getClassInterface();4081DiagnoseClassExtensionDupMethods(C, CCPrimary);4082}40834084DiagnoseCategoryDirectMembersProtocolConformance(SemaRef, C,4085C->protocols());4086}4087if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {4088if (CDecl->getIdentifier())4089// ProcessPropertyDecl is responsible for diagnosing conflicts with any4090// user-defined setter/getter. It also synthesizes setter/getter methods4091// and adds them to the DeclContext and global method pools.4092for (auto *I : CDecl->properties())4093ProcessPropertyDecl(I);4094CDecl->setAtEndRange(AtEnd);4095}4096if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {4097IC->setAtEndRange(AtEnd);4098if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {4099// Any property declared in a class extension might have user4100// declared setter or getter in current class extension or one4101// of the other class extensions. Mark them as synthesized as4102// property will be synthesized when property with same name is4103// seen in the @implementation.4104for (const auto *Ext : IDecl->visible_extensions()) {4105for (const auto *Property : Ext->instance_properties()) {4106// Skip over properties declared @dynamic4107if (const ObjCPropertyImplDecl *PIDecl4108= IC->FindPropertyImplDecl(Property->getIdentifier(),4109Property->getQueryKind()))4110if (PIDecl->getPropertyImplementation()4111== ObjCPropertyImplDecl::Dynamic)4112continue;41134114for (const auto *Ext : IDecl->visible_extensions()) {4115if (ObjCMethodDecl *GetterMethod =4116Ext->getInstanceMethod(Property->getGetterName()))4117GetterMethod->setPropertyAccessor(true);4118if (!Property->isReadOnly())4119if (ObjCMethodDecl *SetterMethod4120= Ext->getInstanceMethod(Property->getSetterName()))4121SetterMethod->setPropertyAccessor(true);4122}4123}4124}4125ImplMethodsVsClassMethods(S, IC, IDecl);4126AtomicPropertySetterGetterRules(IC, IDecl);4127DiagnoseOwningPropertyGetterSynthesis(IC);4128DiagnoseUnusedBackingIvarInAccessor(S, IC);4129if (IDecl->hasDesignatedInitializers())4130DiagnoseMissingDesignatedInitOverrides(IC, IDecl);4131DiagnoseWeakIvars(SemaRef, IC);4132DiagnoseRetainableFlexibleArrayMember(SemaRef, IDecl);41334134bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();4135if (IDecl->getSuperClass() == nullptr) {4136// This class has no superclass, so check that it has been marked with4137// __attribute((objc_root_class)).4138if (!HasRootClassAttr) {4139SourceLocation DeclLoc(IDecl->getLocation());4140SourceLocation SuperClassLoc(SemaRef.getLocForEndOfToken(DeclLoc));4141Diag(DeclLoc, diag::warn_objc_root_class_missing)4142<< IDecl->getIdentifier();4143// See if NSObject is in the current scope, and if it is, suggest4144// adding " : NSObject " to the class declaration.4145NamedDecl *IF = SemaRef.LookupSingleName(4146SemaRef.TUScope, NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject),4147DeclLoc, Sema::LookupOrdinaryName);4148ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);4149if (NSObjectDecl && NSObjectDecl->getDefinition()) {4150Diag(SuperClassLoc, diag::note_objc_needs_superclass)4151<< FixItHint::CreateInsertion(SuperClassLoc, " : NSObject ");4152} else {4153Diag(SuperClassLoc, diag::note_objc_needs_superclass);4154}4155}4156} else if (HasRootClassAttr) {4157// Complain that only root classes may have this attribute.4158Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);4159}41604161if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) {4162// An interface can subclass another interface with a4163// objc_subclassing_restricted attribute when it has that attribute as4164// well (because of interfaces imported from Swift). Therefore we have4165// to check if we can subclass in the implementation as well.4166if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&4167Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {4168Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch);4169Diag(Super->getLocation(), diag::note_class_declared);4170}4171}41724173if (IDecl->hasAttr<ObjCClassStubAttr>())4174Diag(IC->getLocation(), diag::err_implementation_of_class_stub);41754176if (getLangOpts().ObjCRuntime.isNonFragile()) {4177while (IDecl->getSuperClass()) {4178DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());4179IDecl = IDecl->getSuperClass();4180}4181}4182}4183SetIvarInitializers(IC);4184} else if (ObjCCategoryImplDecl* CatImplClass =4185dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {4186CatImplClass->setAtEndRange(AtEnd);41874188// Find category interface decl and then check that all methods declared4189// in this interface are implemented in the category @implementation.4190if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {4191if (ObjCCategoryDecl *Cat4192= IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) {4193ImplMethodsVsClassMethods(S, CatImplClass, Cat);4194}4195}4196} else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {4197if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) {4198if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&4199Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {4200Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch);4201Diag(Super->getLocation(), diag::note_class_declared);4202}4203}42044205if (IntfDecl->hasAttr<ObjCClassStubAttr>() &&4206!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>())4207Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch);4208}4209DiagnoseVariableSizedIvars(SemaRef, OCD);4210if (isInterfaceDeclKind) {4211// Reject invalid vardecls.4212for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {4213DeclGroupRef DG = allTUVars[i].get();4214for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)4215if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {4216if (!VDecl->hasExternalStorage())4217Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);4218}4219}4220}4221ActOnObjCContainerFinishDefinition();42224223for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {4224DeclGroupRef DG = allTUVars[i].get();4225for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)4226(*I)->setTopLevelDeclInObjCContainer();4227SemaRef.Consumer.HandleTopLevelDeclInObjCContainer(DG);4228}42294230SemaRef.ActOnDocumentableDecl(ClassDecl);4231return ClassDecl;4232}42334234/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for4235/// objective-c's type qualifier from the parser version of the same info.4236static Decl::ObjCDeclQualifier4237CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {4238return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;4239}42404241/// Check whether the declared result type of the given Objective-C4242/// method declaration is compatible with the method's class.4243///4244static SemaObjC::ResultTypeCompatibilityKind4245CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,4246ObjCInterfaceDecl *CurrentClass) {4247QualType ResultType = Method->getReturnType();42484249// If an Objective-C method inherits its related result type, then its4250// declared result type must be compatible with its own class type. The4251// declared result type is compatible if:4252if (const ObjCObjectPointerType *ResultObjectType4253= ResultType->getAs<ObjCObjectPointerType>()) {4254// - it is id or qualified id, or4255if (ResultObjectType->isObjCIdType() ||4256ResultObjectType->isObjCQualifiedIdType())4257return SemaObjC::RTC_Compatible;42584259if (CurrentClass) {4260if (ObjCInterfaceDecl *ResultClass4261= ResultObjectType->getInterfaceDecl()) {4262// - it is the same as the method's class type, or4263if (declaresSameEntity(CurrentClass, ResultClass))4264return SemaObjC::RTC_Compatible;42654266// - it is a superclass of the method's class type4267if (ResultClass->isSuperClassOf(CurrentClass))4268return SemaObjC::RTC_Compatible;4269}4270} else {4271// Any Objective-C pointer type might be acceptable for a protocol4272// method; we just don't know.4273return SemaObjC::RTC_Unknown;4274}4275}42764277return SemaObjC::RTC_Incompatible;4278}42794280namespace {4281/// A helper class for searching for methods which a particular method4282/// overrides.4283class OverrideSearch {4284public:4285const ObjCMethodDecl *Method;4286llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;4287bool Recursive;42884289public:4290OverrideSearch(Sema &S, const ObjCMethodDecl *method) : Method(method) {4291Selector selector = method->getSelector();42924293// Bypass this search if we've never seen an instance/class method4294// with this selector before.4295SemaObjC::GlobalMethodPool::iterator it =4296S.ObjC().MethodPool.find(selector);4297if (it == S.ObjC().MethodPool.end()) {4298if (!S.getExternalSource()) return;4299S.ObjC().ReadMethodPool(selector);43004301it = S.ObjC().MethodPool.find(selector);4302if (it == S.ObjC().MethodPool.end())4303return;4304}4305const ObjCMethodList &list =4306method->isInstanceMethod() ? it->second.first : it->second.second;4307if (!list.getMethod()) return;43084309const ObjCContainerDecl *container4310= cast<ObjCContainerDecl>(method->getDeclContext());43114312// Prevent the search from reaching this container again. This is4313// important with categories, which override methods from the4314// interface and each other.4315if (const ObjCCategoryDecl *Category =4316dyn_cast<ObjCCategoryDecl>(container)) {4317searchFromContainer(container);4318if (const ObjCInterfaceDecl *Interface = Category->getClassInterface())4319searchFromContainer(Interface);4320} else {4321searchFromContainer(container);4322}4323}43244325typedef decltype(Overridden)::iterator iterator;4326iterator begin() const { return Overridden.begin(); }4327iterator end() const { return Overridden.end(); }43284329private:4330void searchFromContainer(const ObjCContainerDecl *container) {4331if (container->isInvalidDecl()) return;43324333switch (container->getDeclKind()) {4334#define OBJCCONTAINER(type, base) \4335case Decl::type: \4336searchFrom(cast<type##Decl>(container)); \4337break;4338#define ABSTRACT_DECL(expansion)4339#define DECL(type, base) \4340case Decl::type:4341#include "clang/AST/DeclNodes.inc"4342llvm_unreachable("not an ObjC container!");4343}4344}43454346void searchFrom(const ObjCProtocolDecl *protocol) {4347if (!protocol->hasDefinition())4348return;43494350// A method in a protocol declaration overrides declarations from4351// referenced ("parent") protocols.4352search(protocol->getReferencedProtocols());4353}43544355void searchFrom(const ObjCCategoryDecl *category) {4356// A method in a category declaration overrides declarations from4357// the main class and from protocols the category references.4358// The main class is handled in the constructor.4359search(category->getReferencedProtocols());4360}43614362void searchFrom(const ObjCCategoryImplDecl *impl) {4363// A method in a category definition that has a category4364// declaration overrides declarations from the category4365// declaration.4366if (ObjCCategoryDecl *category = impl->getCategoryDecl()) {4367search(category);4368if (ObjCInterfaceDecl *Interface = category->getClassInterface())4369search(Interface);43704371// Otherwise it overrides declarations from the class.4372} else if (const auto *Interface = impl->getClassInterface()) {4373search(Interface);4374}4375}43764377void searchFrom(const ObjCInterfaceDecl *iface) {4378// A method in a class declaration overrides declarations from4379if (!iface->hasDefinition())4380return;43814382// - categories,4383for (auto *Cat : iface->known_categories())4384search(Cat);43854386// - the super class, and4387if (ObjCInterfaceDecl *super = iface->getSuperClass())4388search(super);43894390// - any referenced protocols.4391search(iface->getReferencedProtocols());4392}43934394void searchFrom(const ObjCImplementationDecl *impl) {4395// A method in a class implementation overrides declarations from4396// the class interface.4397if (const auto *Interface = impl->getClassInterface())4398search(Interface);4399}44004401void search(const ObjCProtocolList &protocols) {4402for (const auto *Proto : protocols)4403search(Proto);4404}44054406void search(const ObjCContainerDecl *container) {4407// Check for a method in this container which matches this selector.4408ObjCMethodDecl *meth = container->getMethod(Method->getSelector(),4409Method->isInstanceMethod(),4410/*AllowHidden=*/true);44114412// If we find one, record it and bail out.4413if (meth) {4414Overridden.insert(meth);4415return;4416}44174418// Otherwise, search for methods that a hypothetical method here4419// would have overridden.44204421// Note that we're now in a recursive case.4422Recursive = true;44234424searchFromContainer(container);4425}4426};4427} // end anonymous namespace44284429void SemaObjC::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,4430ObjCMethodDecl *overridden) {4431if (overridden->isDirectMethod()) {4432const auto *attr = overridden->getAttr<ObjCDirectAttr>();4433Diag(method->getLocation(), diag::err_objc_override_direct_method);4434Diag(attr->getLocation(), diag::note_previous_declaration);4435} else if (method->isDirectMethod()) {4436const auto *attr = method->getAttr<ObjCDirectAttr>();4437Diag(attr->getLocation(), diag::err_objc_direct_on_override)4438<< isa<ObjCProtocolDecl>(overridden->getDeclContext());4439Diag(overridden->getLocation(), diag::note_previous_declaration);4440}4441}44424443void SemaObjC::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,4444ObjCInterfaceDecl *CurrentClass,4445ResultTypeCompatibilityKind RTC) {4446ASTContext &Context = getASTContext();4447if (!ObjCMethod)4448return;4449auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) {4450// Checking canonical decl works across modules.4451return M->getClassInterface()->getCanonicalDecl() ==4452CurrentClass->getCanonicalDecl();4453};4454// Search for overridden methods and merge information down from them.4455OverrideSearch overrides(SemaRef, ObjCMethod);4456// Keep track if the method overrides any method in the class's base classes,4457// its protocols, or its categories' protocols; we will keep that info4458// in the ObjCMethodDecl.4459// For this info, a method in an implementation is not considered as4460// overriding the same method in the interface or its categories.4461bool hasOverriddenMethodsInBaseOrProtocol = false;4462for (ObjCMethodDecl *overridden : overrides) {4463if (!hasOverriddenMethodsInBaseOrProtocol) {4464if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) ||4465!IsMethodInCurrentClass(overridden) || overridden->isOverriding()) {4466CheckObjCMethodDirectOverrides(ObjCMethod, overridden);4467hasOverriddenMethodsInBaseOrProtocol = true;4468} else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) {4469// OverrideSearch will return as "overridden" the same method in the4470// interface. For hasOverriddenMethodsInBaseOrProtocol, we need to4471// check whether a category of a base class introduced a method with the4472// same selector, after the interface method declaration.4473// To avoid unnecessary lookups in the majority of cases, we use the4474// extra info bits in GlobalMethodPool to check whether there were any4475// category methods with this selector.4476GlobalMethodPool::iterator It =4477MethodPool.find(ObjCMethod->getSelector());4478if (It != MethodPool.end()) {4479ObjCMethodList &List =4480ObjCMethod->isInstanceMethod()? It->second.first: It->second.second;4481unsigned CategCount = List.getBits();4482if (CategCount > 0) {4483// If the method is in a category we'll do lookup if there were at4484// least 2 category methods recorded, otherwise only one will do.4485if (CategCount > 1 ||4486!isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) {4487OverrideSearch overrides(SemaRef, overridden);4488for (ObjCMethodDecl *SuperOverridden : overrides) {4489if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) ||4490!IsMethodInCurrentClass(SuperOverridden)) {4491CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden);4492hasOverriddenMethodsInBaseOrProtocol = true;4493overridden->setOverriding(true);4494break;4495}4496}4497}4498}4499}4500}4501}45024503// Propagate down the 'related result type' bit from overridden methods.4504if (RTC != SemaObjC::RTC_Incompatible && overridden->hasRelatedResultType())4505ObjCMethod->setRelatedResultType();45064507// Then merge the declarations.4508SemaRef.mergeObjCMethodDecls(ObjCMethod, overridden);45094510if (ObjCMethod->isImplicit() && overridden->isImplicit())4511continue; // Conflicting properties are detected elsewhere.45124513// Check for overriding methods4514if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||4515isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext()))4516CheckConflictingOverridingMethod(ObjCMethod, overridden,4517isa<ObjCProtocolDecl>(overridden->getDeclContext()));45184519if (CurrentClass && overridden->getDeclContext() != CurrentClass &&4520isa<ObjCInterfaceDecl>(overridden->getDeclContext()) &&4521!overridden->isImplicit() /* not meant for properties */) {4522ObjCMethodDecl::param_iterator ParamI = ObjCMethod->param_begin(),4523E = ObjCMethod->param_end();4524ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(),4525PrevE = overridden->param_end();4526for (; ParamI != E && PrevI != PrevE; ++ParamI, ++PrevI) {4527assert(PrevI != overridden->param_end() && "Param mismatch");4528QualType T1 = Context.getCanonicalType((*ParamI)->getType());4529QualType T2 = Context.getCanonicalType((*PrevI)->getType());4530// If type of argument of method in this class does not match its4531// respective argument type in the super class method, issue warning;4532if (!Context.typesAreCompatible(T1, T2)) {4533Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)4534<< T1 << T2;4535Diag(overridden->getLocation(), diag::note_previous_declaration);4536break;4537}4538}4539}4540}45414542ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol);4543}45444545/// Merge type nullability from for a redeclaration of the same entity,4546/// producing the updated type of the redeclared entity.4547static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,4548QualType type,4549bool usesCSKeyword,4550SourceLocation prevLoc,4551QualType prevType,4552bool prevUsesCSKeyword) {4553// Determine the nullability of both types.4554auto nullability = type->getNullability();4555auto prevNullability = prevType->getNullability();45564557// Easy case: both have nullability.4558if (nullability.has_value() == prevNullability.has_value()) {4559// Neither has nullability; continue.4560if (!nullability)4561return type;45624563// The nullabilities are equivalent; do nothing.4564if (*nullability == *prevNullability)4565return type;45664567// Complain about mismatched nullability.4568S.Diag(loc, diag::err_nullability_conflicting)4569<< DiagNullabilityKind(*nullability, usesCSKeyword)4570<< DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);4571return type;4572}45734574// If it's the redeclaration that has nullability, don't change anything.4575if (nullability)4576return type;45774578// Otherwise, provide the result with the same nullability.4579return S.Context.getAttributedType(4580AttributedType::getNullabilityAttrKind(*prevNullability),4581type, type);4582}45834584/// Merge information from the declaration of a method in the \@interface4585/// (or a category/extension) into the corresponding method in the4586/// @implementation (for a class or category).4587static void mergeInterfaceMethodToImpl(Sema &S,4588ObjCMethodDecl *method,4589ObjCMethodDecl *prevMethod) {4590// Merge the objc_requires_super attribute.4591if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() &&4592!method->hasAttr<ObjCRequiresSuperAttr>()) {4593// merge the attribute into implementation.4594method->addAttr(4595ObjCRequiresSuperAttr::CreateImplicit(S.Context,4596method->getLocation()));4597}45984599// Merge nullability of the result type.4600QualType newReturnType4601= mergeTypeNullabilityForRedecl(4602S, method->getReturnTypeSourceRange().getBegin(),4603method->getReturnType(),4604method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,4605prevMethod->getReturnTypeSourceRange().getBegin(),4606prevMethod->getReturnType(),4607prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);4608method->setReturnType(newReturnType);46094610// Handle each of the parameters.4611unsigned numParams = method->param_size();4612unsigned numPrevParams = prevMethod->param_size();4613for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) {4614ParmVarDecl *param = method->param_begin()[i];4615ParmVarDecl *prevParam = prevMethod->param_begin()[i];46164617// Merge nullability.4618QualType newParamType4619= mergeTypeNullabilityForRedecl(4620S, param->getLocation(), param->getType(),4621param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,4622prevParam->getLocation(), prevParam->getType(),4623prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);4624param->setType(newParamType);4625}4626}46274628/// Verify that the method parameters/return value have types that are supported4629/// by the x86 target.4630static void checkObjCMethodX86VectorTypes(Sema &SemaRef,4631const ObjCMethodDecl *Method) {4632assert(SemaRef.getASTContext().getTargetInfo().getTriple().getArch() ==4633llvm::Triple::x86 &&4634"x86-specific check invoked for a different target");4635SourceLocation Loc;4636QualType T;4637for (const ParmVarDecl *P : Method->parameters()) {4638if (P->getType()->isVectorType()) {4639Loc = P->getBeginLoc();4640T = P->getType();4641break;4642}4643}4644if (Loc.isInvalid()) {4645if (Method->getReturnType()->isVectorType()) {4646Loc = Method->getReturnTypeSourceRange().getBegin();4647T = Method->getReturnType();4648} else4649return;4650}46514652// Vector parameters/return values are not supported by objc_msgSend on x86 in4653// iOS < 9 and macOS < 10.11.4654const auto &Triple = SemaRef.getASTContext().getTargetInfo().getTriple();4655VersionTuple AcceptedInVersion;4656if (Triple.getOS() == llvm::Triple::IOS)4657AcceptedInVersion = VersionTuple(/*Major=*/9);4658else if (Triple.isMacOSX())4659AcceptedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/11);4660else4661return;4662if (SemaRef.getASTContext().getTargetInfo().getPlatformMinVersion() >=4663AcceptedInVersion)4664return;4665SemaRef.Diag(Loc, diag::err_objc_method_unsupported_param_ret_type)4666<< T << (Method->getReturnType()->isVectorType() ? /*return value*/ 14667: /*parameter*/ 0)4668<< (Triple.isMacOSX() ? "macOS 10.11" : "iOS 9");4669}46704671static void mergeObjCDirectMembers(Sema &S, Decl *CD, ObjCMethodDecl *Method) {4672if (!Method->isDirectMethod() && !Method->hasAttr<UnavailableAttr>() &&4673CD->hasAttr<ObjCDirectMembersAttr>()) {4674Method->addAttr(4675ObjCDirectAttr::CreateImplicit(S.Context, Method->getLocation()));4676}4677}46784679static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl,4680ObjCMethodDecl *Method,4681ObjCImplDecl *ImpDecl = nullptr) {4682auto Sel = Method->getSelector();4683bool isInstance = Method->isInstanceMethod();4684bool diagnosed = false;46854686auto diagClash = [&](const ObjCMethodDecl *IMD) {4687if (diagnosed || IMD->isImplicit())4688return;4689if (Method->isDirectMethod() || IMD->isDirectMethod()) {4690S.Diag(Method->getLocation(), diag::err_objc_direct_duplicate_decl)4691<< Method->isDirectMethod() << /* method */ 0 << IMD->isDirectMethod()4692<< Method->getDeclName();4693S.Diag(IMD->getLocation(), diag::note_previous_declaration);4694diagnosed = true;4695}4696};46974698// Look for any other declaration of this method anywhere we can see in this4699// compilation unit.4700//4701// We do not use IDecl->lookupMethod() because we have specific needs:4702//4703// - we absolutely do not need to walk protocols, because4704// diag::err_objc_direct_on_protocol has already been emitted4705// during parsing if there's a conflict,4706//4707// - when we do not find a match in a given @interface container,4708// we need to attempt looking it up in the @implementation block if the4709// translation unit sees it to find more clashes.47104711if (auto *IMD = IDecl->getMethod(Sel, isInstance))4712diagClash(IMD);4713else if (auto *Impl = IDecl->getImplementation())4714if (Impl != ImpDecl)4715if (auto *IMD = IDecl->getImplementation()->getMethod(Sel, isInstance))4716diagClash(IMD);47174718for (const auto *Cat : IDecl->visible_categories())4719if (auto *IMD = Cat->getMethod(Sel, isInstance))4720diagClash(IMD);4721else if (auto CatImpl = Cat->getImplementation())4722if (CatImpl != ImpDecl)4723if (auto *IMD = Cat->getMethod(Sel, isInstance))4724diagClash(IMD);4725}47264727Decl *SemaObjC::ActOnMethodDeclaration(4728Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,4729tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,4730ArrayRef<SourceLocation> SelectorLocs, Selector Sel,4731// optional arguments. The number of types/arguments is obtained4732// from the Sel.getNumArgs().4733ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,4734unsigned CNumArgs, // c-style args4735const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,4736bool isVariadic, bool MethodDefinition) {4737ASTContext &Context = getASTContext();4738// Make sure we can establish a context for the method.4739if (!SemaRef.CurContext->isObjCContainer()) {4740Diag(MethodLoc, diag::err_missing_method_context);4741return nullptr;4742}47434744Decl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext);4745QualType resultDeclType;47464747bool HasRelatedResultType = false;4748TypeSourceInfo *ReturnTInfo = nullptr;4749if (ReturnType) {4750resultDeclType = SemaRef.GetTypeFromParser(ReturnType, &ReturnTInfo);47514752if (SemaRef.CheckFunctionReturnType(resultDeclType, MethodLoc))4753return nullptr;47544755QualType bareResultType = resultDeclType;4756(void)AttributedType::stripOuterNullability(bareResultType);4757HasRelatedResultType = (bareResultType == Context.getObjCInstanceType());4758} else { // get the type for "id".4759resultDeclType = Context.getObjCIdType();4760Diag(MethodLoc, diag::warn_missing_method_return_type)4761<< FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");4762}47634764ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(4765Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo,4766SemaRef.CurContext, MethodType == tok::minus, isVariadic,4767/*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,4768/*isImplicitlyDeclared=*/false, /*isDefined=*/false,4769MethodDeclKind == tok::objc_optional4770? ObjCImplementationControl::Optional4771: ObjCImplementationControl::Required,4772HasRelatedResultType);47734774SmallVector<ParmVarDecl*, 16> Params;47754776for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) {4777QualType ArgType;4778TypeSourceInfo *DI;47794780if (!ArgInfo[i].Type) {4781ArgType = Context.getObjCIdType();4782DI = nullptr;4783} else {4784ArgType = SemaRef.GetTypeFromParser(ArgInfo[i].Type, &DI);4785}47864787LookupResult R(SemaRef, ArgInfo[i].Name, ArgInfo[i].NameLoc,4788Sema::LookupOrdinaryName,4789SemaRef.forRedeclarationInCurContext());4790SemaRef.LookupName(R, S);4791if (R.isSingleResult()) {4792NamedDecl *PrevDecl = R.getFoundDecl();4793if (S->isDeclScope(PrevDecl)) {4794Diag(ArgInfo[i].NameLoc,4795(MethodDefinition ? diag::warn_method_param_redefinition4796: diag::warn_method_param_declaration))4797<< ArgInfo[i].Name;4798Diag(PrevDecl->getLocation(),4799diag::note_previous_declaration);4800}4801}48024803SourceLocation StartLoc = DI4804? DI->getTypeLoc().getBeginLoc()4805: ArgInfo[i].NameLoc;48064807ParmVarDecl *Param =4808SemaRef.CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc,4809ArgInfo[i].Name, ArgType, DI, SC_None);48104811Param->setObjCMethodScopeInfo(i);48124813Param->setObjCDeclQualifier(4814CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier()));48154816// Apply the attributes to the parameter.4817SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param,4818ArgInfo[i].ArgAttrs);4819SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);4820SemaRef.ProcessAPINotes(Param);48214822if (Param->hasAttr<BlocksAttr>()) {4823Diag(Param->getLocation(), diag::err_block_on_nonlocal);4824Param->setInvalidDecl();4825}4826S->AddDecl(Param);4827SemaRef.IdResolver.AddDecl(Param);48284829Params.push_back(Param);4830}48314832for (unsigned i = 0, e = CNumArgs; i != e; ++i) {4833ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);4834QualType ArgType = Param->getType();4835if (ArgType.isNull())4836ArgType = Context.getObjCIdType();4837else4838// Perform the default array/function conversions (C99 6.7.5.3p[7,8]).4839ArgType = Context.getAdjustedParameterType(ArgType);48404841Param->setDeclContext(ObjCMethod);4842Params.push_back(Param);4843}48444845ObjCMethod->setMethodParams(Context, Params, SelectorLocs);4846ObjCMethod->setObjCDeclQualifier(4847CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));48484849SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, ObjCMethod, AttrList);4850SemaRef.AddPragmaAttributes(SemaRef.TUScope, ObjCMethod);4851SemaRef.ProcessAPINotes(ObjCMethod);48524853// Add the method now.4854const ObjCMethodDecl *PrevMethod = nullptr;4855if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {4856if (MethodType == tok::minus) {4857PrevMethod = ImpDecl->getInstanceMethod(Sel);4858ImpDecl->addInstanceMethod(ObjCMethod);4859} else {4860PrevMethod = ImpDecl->getClassMethod(Sel);4861ImpDecl->addClassMethod(ObjCMethod);4862}48634864// If this method overrides a previous @synthesize declaration,4865// register it with the property. Linear search through all4866// properties here, because the autosynthesized stub hasn't been4867// made visible yet, so it can be overridden by a later4868// user-specified implementation.4869for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) {4870if (auto *Setter = PropertyImpl->getSetterMethodDecl())4871if (Setter->getSelector() == Sel &&4872Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {4873assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected");4874PropertyImpl->setSetterMethodDecl(ObjCMethod);4875}4876if (auto *Getter = PropertyImpl->getGetterMethodDecl())4877if (Getter->getSelector() == Sel &&4878Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {4879assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected");4880PropertyImpl->setGetterMethodDecl(ObjCMethod);4881break;4882}4883}48844885// A method is either tagged direct explicitly, or inherits it from its4886// canonical declaration.4887//4888// We have to do the merge upfront and not in mergeInterfaceMethodToImpl()4889// because IDecl->lookupMethod() returns more possible matches than just4890// the canonical declaration.4891if (!ObjCMethod->isDirectMethod()) {4892const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl();4893if (CanonicalMD->isDirectMethod()) {4894const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>();4895ObjCMethod->addAttr(4896ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));4897}4898}48994900// Merge information from the @interface declaration into the4901// @implementation.4902if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {4903if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),4904ObjCMethod->isInstanceMethod())) {4905mergeInterfaceMethodToImpl(SemaRef, ObjCMethod, IMD);49064907// The Idecl->lookupMethod() above will find declarations for ObjCMethod4908// in one of these places:4909//4910// (1) the canonical declaration in an @interface container paired4911// with the ImplDecl,4912// (2) non canonical declarations in @interface not paired with the4913// ImplDecl for the same Class,4914// (3) any superclass container.4915//4916// Direct methods only allow for canonical declarations in the matching4917// container (case 1).4918//4919// Direct methods overriding a superclass declaration (case 3) is4920// handled during overrides checks in CheckObjCMethodOverrides().4921//4922// We deal with same-class container mismatches (Case 2) here.4923if (IDecl == IMD->getClassInterface()) {4924auto diagContainerMismatch = [&] {4925int decl = 0, impl = 0;49264927if (auto *Cat = dyn_cast<ObjCCategoryDecl>(IMD->getDeclContext()))4928decl = Cat->IsClassExtension() ? 1 : 2;49294930if (isa<ObjCCategoryImplDecl>(ImpDecl))4931impl = 1 + (decl != 0);49324933Diag(ObjCMethod->getLocation(),4934diag::err_objc_direct_impl_decl_mismatch)4935<< decl << impl;4936Diag(IMD->getLocation(), diag::note_previous_declaration);4937};49384939if (ObjCMethod->isDirectMethod()) {4940const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>();4941if (ObjCMethod->getCanonicalDecl() != IMD) {4942diagContainerMismatch();4943} else if (!IMD->isDirectMethod()) {4944Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl);4945Diag(IMD->getLocation(), diag::note_previous_declaration);4946}4947} else if (IMD->isDirectMethod()) {4948const auto *attr = IMD->getAttr<ObjCDirectAttr>();4949if (ObjCMethod->getCanonicalDecl() != IMD) {4950diagContainerMismatch();4951} else {4952ObjCMethod->addAttr(4953ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));4954}4955}4956}49574958// Warn about defining -dealloc in a category.4959if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() &&4960ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) {4961Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)4962<< ObjCMethod->getDeclName();4963}4964} else {4965mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);4966checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod, ImpDecl);4967}49684969// Warn if a method declared in a protocol to which a category or4970// extension conforms is non-escaping and the implementation's method is4971// escaping.4972for (auto *C : IDecl->visible_categories())4973for (auto &P : C->protocols())4974if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(),4975ObjCMethod->isInstanceMethod())) {4976assert(ObjCMethod->parameters().size() ==4977IMD->parameters().size() &&4978"Methods have different number of parameters");4979auto OI = IMD->param_begin(), OE = IMD->param_end();4980auto NI = ObjCMethod->param_begin();4981for (; OI != OE; ++OI, ++NI)4982diagnoseNoescape(*NI, *OI, C, P, SemaRef);4983}4984}4985} else {4986if (!isa<ObjCProtocolDecl>(ClassDecl)) {4987mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);49884989ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl);4990if (!IDecl)4991IDecl = cast<ObjCCategoryDecl>(ClassDecl)->getClassInterface();4992// For valid code, we should always know the primary interface4993// declaration by now, however for invalid code we'll keep parsing4994// but we won't find the primary interface and IDecl will be nil.4995if (IDecl)4996checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod);4997}49984999cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);5000}50015002if (PrevMethod) {5003// You can never have two method definitions with the same name.5004Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)5005<< ObjCMethod->getDeclName();5006Diag(PrevMethod->getLocation(), diag::note_previous_declaration);5007ObjCMethod->setInvalidDecl();5008return ObjCMethod;5009}50105011// If this Objective-C method does not have a related result type, but we5012// are allowed to infer related result types, try to do so based on the5013// method family.5014ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl);5015if (!CurrentClass) {5016if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl))5017CurrentClass = Cat->getClassInterface();5018else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl))5019CurrentClass = Impl->getClassInterface();5020else if (ObjCCategoryImplDecl *CatImpl5021= dyn_cast<ObjCCategoryImplDecl>(ClassDecl))5022CurrentClass = CatImpl->getClassInterface();5023}50245025ResultTypeCompatibilityKind RTC =5026CheckRelatedResultTypeCompatibility(SemaRef, ObjCMethod, CurrentClass);50275028CheckObjCMethodOverrides(ObjCMethod, CurrentClass, RTC);50295030bool ARCError = false;5031if (getLangOpts().ObjCAutoRefCount)5032ARCError = CheckARCMethodDecl(ObjCMethod);50335034// Infer the related result type when possible.5035if (!ARCError && RTC == SemaObjC::RTC_Compatible &&5036!ObjCMethod->hasRelatedResultType() &&5037getLangOpts().ObjCInferRelatedResultType) {5038bool InferRelatedResultType = false;5039switch (ObjCMethod->getMethodFamily()) {5040case OMF_None:5041case OMF_copy:5042case OMF_dealloc:5043case OMF_finalize:5044case OMF_mutableCopy:5045case OMF_release:5046case OMF_retainCount:5047case OMF_initialize:5048case OMF_performSelector:5049break;50505051case OMF_alloc:5052case OMF_new:5053InferRelatedResultType = ObjCMethod->isClassMethod();5054break;50555056case OMF_init:5057case OMF_autorelease:5058case OMF_retain:5059case OMF_self:5060InferRelatedResultType = ObjCMethod->isInstanceMethod();5061break;5062}50635064if (InferRelatedResultType &&5065!ObjCMethod->getReturnType()->isObjCIndependentClassType())5066ObjCMethod->setRelatedResultType();5067}50685069if (MethodDefinition &&5070Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)5071checkObjCMethodX86VectorTypes(SemaRef, ObjCMethod);50725073// + load method cannot have availability attributes. It get called on5074// startup, so it has to have the availability of the deployment target.5075if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) {5076if (ObjCMethod->isClassMethod() &&5077ObjCMethod->getSelector().getAsString() == "load") {5078Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)5079<< 0;5080ObjCMethod->dropAttr<AvailabilityAttr>();5081}5082}50835084// Insert the invisible arguments, self and _cmd!5085ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface());50865087SemaRef.ActOnDocumentableDecl(ObjCMethod);50885089return ObjCMethod;5090}50915092bool SemaObjC::CheckObjCDeclScope(Decl *D) {5093// Following is also an error. But it is caused by a missing @end5094// and diagnostic is issued elsewhere.5095if (isa<ObjCContainerDecl>(SemaRef.CurContext->getRedeclContext()))5096return false;50975098// If we switched context to translation unit while we are still lexically in5099// an objc container, it means the parser missed emitting an error.5100if (isa<TranslationUnitDecl>(5101SemaRef.getCurLexicalContext()->getRedeclContext()))5102return false;51035104Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);5105D->setInvalidDecl();51065107return true;5108}51095110/// Called whenever \@defs(ClassName) is encountered in the source. Inserts the5111/// instance variables of ClassName into Decls.5112void SemaObjC::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,5113const IdentifierInfo *ClassName,5114SmallVectorImpl<Decl *> &Decls) {5115ASTContext &Context = getASTContext();5116// Check that ClassName is a valid class5117ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);5118if (!Class) {5119Diag(DeclStart, diag::err_undef_interface) << ClassName;5120return;5121}5122if (getLangOpts().ObjCRuntime.isNonFragile()) {5123Diag(DeclStart, diag::err_atdef_nonfragile_interface);5124return;5125}51265127// Collect the instance variables5128SmallVector<const ObjCIvarDecl*, 32> Ivars;5129Context.DeepCollectObjCIvars(Class, true, Ivars);5130// For each ivar, create a fresh ObjCAtDefsFieldDecl.5131for (unsigned i = 0; i < Ivars.size(); i++) {5132const FieldDecl* ID = Ivars[i];5133RecordDecl *Record = dyn_cast<RecordDecl>(TagD);5134Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,5135/*FIXME: StartL=*/ID->getLocation(),5136ID->getLocation(),5137ID->getIdentifier(), ID->getType(),5138ID->getBitWidth());5139Decls.push_back(FD);5140}51415142// Introduce all of these fields into the appropriate scope.5143for (SmallVectorImpl<Decl*>::iterator D = Decls.begin();5144D != Decls.end(); ++D) {5145FieldDecl *FD = cast<FieldDecl>(*D);5146if (getLangOpts().CPlusPlus)5147SemaRef.PushOnScopeChains(FD, S);5148else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))5149Record->addDecl(FD);5150}5151}51525153/// Build a type-check a new Objective-C exception variable declaration.5154VarDecl *SemaObjC::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,5155SourceLocation StartLoc,5156SourceLocation IdLoc,5157const IdentifierInfo *Id,5158bool Invalid) {5159ASTContext &Context = getASTContext();5160// ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage5161// duration shall not be qualified by an address-space qualifier."5162// Since all parameters have automatic store duration, they can not have5163// an address space.5164if (T.getAddressSpace() != LangAS::Default) {5165Diag(IdLoc, diag::err_arg_with_address_space);5166Invalid = true;5167}51685169// An @catch parameter must be an unqualified object pointer type;5170// FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?5171if (Invalid) {5172// Don't do any further checking.5173} else if (T->isDependentType()) {5174// Okay: we don't know what this type will instantiate to.5175} else if (T->isObjCQualifiedIdType()) {5176Invalid = true;5177Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);5178} else if (T->isObjCIdType()) {5179// Okay: we don't know what this type will instantiate to.5180} else if (!T->isObjCObjectPointerType()) {5181Invalid = true;5182Diag(IdLoc, diag::err_catch_param_not_objc_type);5183} else if (!T->castAs<ObjCObjectPointerType>()->getInterfaceType()) {5184Invalid = true;5185Diag(IdLoc, diag::err_catch_param_not_objc_type);5186}51875188VarDecl *New = VarDecl::Create(Context, SemaRef.CurContext, StartLoc, IdLoc,5189Id, T, TInfo, SC_None);5190New->setExceptionVariable(true);51915192// In ARC, infer 'retaining' for variables of retainable type.5193if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New))5194Invalid = true;51955196if (Invalid)5197New->setInvalidDecl();5198return New;5199}52005201Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {5202const DeclSpec &DS = D.getDeclSpec();52035204// We allow the "register" storage class on exception variables because5205// GCC did, but we drop it completely. Any other storage class is an error.5206if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {5207Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)5208<< FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));5209} else if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) {5210Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)5211<< DeclSpec::getSpecifierName(SCS);5212}5213if (DS.isInlineSpecified())5214Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)5215<< getLangOpts().CPlusPlus17;5216if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())5217Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),5218diag::err_invalid_thread)5219<< DeclSpec::getSpecifierName(TSCS);5220D.getMutableDeclSpec().ClearStorageClassSpecs();52215222SemaRef.DiagnoseFunctionSpecifiers(D.getDeclSpec());52235224// Check that there are no default arguments inside the type of this5225// exception object (C++ only).5226if (getLangOpts().CPlusPlus)5227SemaRef.CheckExtraCXXDefaultArguments(D);52285229TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);5230QualType ExceptionType = TInfo->getType();52315232VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType,5233D.getSourceRange().getBegin(),5234D.getIdentifierLoc(),5235D.getIdentifier(),5236D.isInvalidType());52375238// Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).5239if (D.getCXXScopeSpec().isSet()) {5240Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)5241<< D.getCXXScopeSpec().getRange();5242New->setInvalidDecl();5243}52445245// Add the parameter declaration into this scope.5246S->AddDecl(New);5247if (D.getIdentifier())5248SemaRef.IdResolver.AddDecl(New);52495250SemaRef.ProcessDeclAttributes(S, New, D);52515252if (New->hasAttr<BlocksAttr>())5253Diag(New->getLocation(), diag::err_block_on_nonlocal);5254return New;5255}52565257/// CollectIvarsToConstructOrDestruct - Collect those ivars which require5258/// initialization.5259void SemaObjC::CollectIvarsToConstructOrDestruct(5260ObjCInterfaceDecl *OI, SmallVectorImpl<ObjCIvarDecl *> &Ivars) {5261ASTContext &Context = getASTContext();5262for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;5263Iv= Iv->getNextIvar()) {5264QualType QT = Context.getBaseElementType(Iv->getType());5265if (QT->isRecordType())5266Ivars.push_back(Iv);5267}5268}52695270void SemaObjC::DiagnoseUseOfUnimplementedSelectors() {5271ASTContext &Context = getASTContext();5272// Load referenced selectors from the external source.5273if (SemaRef.ExternalSource) {5274SmallVector<std::pair<Selector, SourceLocation>, 4> Sels;5275SemaRef.ExternalSource->ReadReferencedSelectors(Sels);5276for (unsigned I = 0, N = Sels.size(); I != N; ++I)5277ReferencedSelectors[Sels[I].first] = Sels[I].second;5278}52795280// Warning will be issued only when selector table is5281// generated (which means there is at lease one implementation5282// in the TU). This is to match gcc's behavior.5283if (ReferencedSelectors.empty() ||5284!Context.AnyObjCImplementation())5285return;5286for (auto &SelectorAndLocation : ReferencedSelectors) {5287Selector Sel = SelectorAndLocation.first;5288SourceLocation Loc = SelectorAndLocation.second;5289if (!LookupImplementedMethodInGlobalPool(Sel))5290Diag(Loc, diag::warn_unimplemented_selector) << Sel;5291}5292}52935294ObjCIvarDecl *5295SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,5296const ObjCPropertyDecl *&PDecl) const {5297if (Method->isClassMethod())5298return nullptr;5299const ObjCInterfaceDecl *IDecl = Method->getClassInterface();5300if (!IDecl)5301return nullptr;5302Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,5303/*shallowCategoryLookup=*/false,5304/*followSuper=*/false);5305if (!Method || !Method->isPropertyAccessor())5306return nullptr;5307if ((PDecl = Method->findPropertyDecl()))5308if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {5309// property backing ivar must belong to property's class5310// or be a private ivar in class's implementation.5311// FIXME. fix the const-ness issue.5312IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable(5313IV->getIdentifier());5314return IV;5315}5316return nullptr;5317}53185319namespace {5320/// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property5321/// accessor references the backing ivar.5322class UnusedBackingIvarChecker5323: public RecursiveASTVisitor<UnusedBackingIvarChecker> {5324public:5325Sema &S;5326const ObjCMethodDecl *Method;5327const ObjCIvarDecl *IvarD;5328bool AccessedIvar;5329bool InvokedSelfMethod;53305331UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method,5332const ObjCIvarDecl *IvarD)5333: S(S), Method(Method), IvarD(IvarD), AccessedIvar(false),5334InvokedSelfMethod(false) {5335assert(IvarD);5336}53375338bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {5339if (E->getDecl() == IvarD) {5340AccessedIvar = true;5341return false;5342}5343return true;5344}53455346bool VisitObjCMessageExpr(ObjCMessageExpr *E) {5347if (E->getReceiverKind() == ObjCMessageExpr::Instance &&5348S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) {5349InvokedSelfMethod = true;5350}5351return true;5352}5353};5354} // end anonymous namespace53555356void SemaObjC::DiagnoseUnusedBackingIvarInAccessor(5357Scope *S, const ObjCImplementationDecl *ImplD) {5358if (S->hasUnrecoverableErrorOccurred())5359return;53605361for (const auto *CurMethod : ImplD->instance_methods()) {5362unsigned DIAG = diag::warn_unused_property_backing_ivar;5363SourceLocation Loc = CurMethod->getLocation();5364if (getDiagnostics().isIgnored(DIAG, Loc))5365continue;53665367const ObjCPropertyDecl *PDecl;5368const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);5369if (!IV)5370continue;53715372if (CurMethod->isSynthesizedAccessorStub())5373continue;53745375UnusedBackingIvarChecker Checker(SemaRef, CurMethod, IV);5376Checker.TraverseStmt(CurMethod->getBody());5377if (Checker.AccessedIvar)5378continue;53795380// Do not issue this warning if backing ivar is used somewhere and accessor5381// implementation makes a self call. This is to prevent false positive in5382// cases where the ivar is accessed by another method that the accessor5383// delegates to.5384if (!IV->isReferenced() || !Checker.InvokedSelfMethod) {5385Diag(Loc, DIAG) << IV;5386Diag(PDecl->getLocation(), diag::note_property_declare);5387}5388}5389}53905391QualType SemaObjC::AdjustParameterTypeForObjCAutoRefCount(5392QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo) {5393ASTContext &Context = getASTContext();5394// In ARC, infer a lifetime qualifier for appropriate parameter types.5395if (!getLangOpts().ObjCAutoRefCount ||5396T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType())5397return T;53985399Qualifiers::ObjCLifetime Lifetime;54005401// Special cases for arrays:5402// - if it's const, use __unsafe_unretained5403// - otherwise, it's an error5404if (T->isArrayType()) {5405if (!T.isConstQualified()) {5406if (SemaRef.DelayedDiagnostics.shouldDelayDiagnostics())5407SemaRef.DelayedDiagnostics.add(5408sema::DelayedDiagnostic::makeForbiddenType(5409NameLoc, diag::err_arc_array_param_no_ownership, T, false));5410else5411Diag(NameLoc, diag::err_arc_array_param_no_ownership)5412<< TSInfo->getTypeLoc().getSourceRange();5413}5414Lifetime = Qualifiers::OCL_ExplicitNone;5415} else {5416Lifetime = T->getObjCARCImplicitLifetime();5417}5418T = Context.getLifetimeQualifiedType(T, Lifetime);54195420return T;5421}54225423ObjCInterfaceDecl *SemaObjC::getObjCInterfaceDecl(const IdentifierInfo *&Id,5424SourceLocation IdLoc,5425bool DoTypoCorrection) {5426// The third "scope" argument is 0 since we aren't enabling lazy built-in5427// creation from this context.5428NamedDecl *IDecl = SemaRef.LookupSingleName(SemaRef.TUScope, Id, IdLoc,5429Sema::LookupOrdinaryName);54305431if (!IDecl && DoTypoCorrection) {5432// Perform typo correction at the given location, but only if we5433// find an Objective-C class name.5434DeclFilterCCC<ObjCInterfaceDecl> CCC{};5435if (TypoCorrection C = SemaRef.CorrectTypo(5436DeclarationNameInfo(Id, IdLoc), Sema::LookupOrdinaryName,5437SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) {5438SemaRef.diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);5439IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();5440Id = IDecl->getIdentifier();5441}5442}5443ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);5444// This routine must always return a class definition, if any.5445if (Def && Def->getDefinition())5446Def = Def->getDefinition();5447return Def;5448}54495450bool SemaObjC::inferObjCARCLifetime(ValueDecl *decl) {5451ASTContext &Context = getASTContext();5452QualType type = decl->getType();5453Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();5454if (lifetime == Qualifiers::OCL_Autoreleasing) {5455// Various kinds of declaration aren't allowed to be __autoreleasing.5456unsigned kind = -1U;5457if (VarDecl *var = dyn_cast<VarDecl>(decl)) {5458if (var->hasAttr<BlocksAttr>())5459kind = 0; // __block5460else if (!var->hasLocalStorage())5461kind = 1; // global5462} else if (isa<ObjCIvarDecl>(decl)) {5463kind = 3; // ivar5464} else if (isa<FieldDecl>(decl)) {5465kind = 2; // field5466}54675468if (kind != -1U) {5469Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind;5470}5471} else if (lifetime == Qualifiers::OCL_None) {5472// Try to infer lifetime.5473if (!type->isObjCLifetimeType())5474return false;54755476lifetime = type->getObjCARCImplicitLifetime();5477type = Context.getLifetimeQualifiedType(type, lifetime);5478decl->setType(type);5479}54805481if (VarDecl *var = dyn_cast<VarDecl>(decl)) {5482// Thread-local variables cannot have lifetime.5483if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&5484var->getTLSKind()) {5485Diag(var->getLocation(), diag::err_arc_thread_ownership)5486<< var->getType();5487return true;5488}5489}54905491return false;5492}54935494ObjCContainerDecl *SemaObjC::getObjCDeclContext() const {5495return (dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext));5496}54975498void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {5499if (!getLangOpts().CPlusPlus)5500return;5501if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {5502ASTContext &Context = getASTContext();5503SmallVector<ObjCIvarDecl *, 8> ivars;5504CollectIvarsToConstructOrDestruct(OID, ivars);5505if (ivars.empty())5506return;5507SmallVector<CXXCtorInitializer *, 32> AllToInit;5508for (unsigned i = 0; i < ivars.size(); i++) {5509FieldDecl *Field = ivars[i];5510if (Field->isInvalidDecl())5511continue;55125513CXXCtorInitializer *Member;5514InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);5515InitializationKind InitKind =5516InitializationKind::CreateDefault(ObjCImplementation->getLocation());55175518InitializationSequence InitSeq(SemaRef, InitEntity, InitKind,5519std::nullopt);5520ExprResult MemberInit =5521InitSeq.Perform(SemaRef, InitEntity, InitKind, std::nullopt);5522MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);5523// Note, MemberInit could actually come back empty if no initialization5524// is required (e.g., because it would call a trivial default constructor)5525if (!MemberInit.get() || MemberInit.isInvalid())5526continue;55275528Member = new (Context)5529CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(),5530MemberInit.getAs<Expr>(), SourceLocation());5531AllToInit.push_back(Member);55325533// Be sure that the destructor is accessible and is marked as referenced.5534if (const RecordType *RecordTy =5535Context.getBaseElementType(Field->getType())5536->getAs<RecordType>()) {5537CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());5538if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) {5539SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor);5540SemaRef.CheckDestructorAccess(5541Field->getLocation(), Destructor,5542PDiag(diag::err_access_dtor_ivar)5543<< Context.getBaseElementType(Field->getType()));5544}5545}5546}5547ObjCImplementation->setIvarInitializers(Context, AllToInit.data(),5548AllToInit.size());5549}5550}55515552/// TranslateIvarVisibility - Translate visibility from a token ID to an5553/// AST enum value.5554static ObjCIvarDecl::AccessControl5555TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {5556switch (ivarVisibility) {5557default:5558llvm_unreachable("Unknown visitibility kind");5559case tok::objc_private:5560return ObjCIvarDecl::Private;5561case tok::objc_public:5562return ObjCIvarDecl::Public;5563case tok::objc_protected:5564return ObjCIvarDecl::Protected;5565case tok::objc_package:5566return ObjCIvarDecl::Package;5567}5568}55695570/// ActOnIvar - Each ivar field of an objective-c class is passed into this5571/// in order to create an IvarDecl object for it.5572Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D,5573Expr *BitWidth, tok::ObjCKeywordKind Visibility) {55745575const IdentifierInfo *II = D.getIdentifier();5576SourceLocation Loc = DeclStart;5577if (II)5578Loc = D.getIdentifierLoc();55795580// FIXME: Unnamed fields can be handled in various different ways, for5581// example, unnamed unions inject all members into the struct namespace!55825583TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);5584QualType T = TInfo->getType();55855586if (BitWidth) {5587// 6.7.2.1p3, 6.7.2.1p45588BitWidth =5589SemaRef.VerifyBitField(Loc, II, T, /*IsMsStruct*/ false, BitWidth)5590.get();5591if (!BitWidth)5592D.setInvalidType();5593} else {5594// Not a bitfield.55955596// validate II.5597}5598if (T->isReferenceType()) {5599Diag(Loc, diag::err_ivar_reference_type);5600D.setInvalidType();5601}5602// C99 6.7.2.1p8: A member of a structure or union may have any type other5603// than a variably modified type.5604else if (T->isVariablyModifiedType()) {5605if (!SemaRef.tryToFixVariablyModifiedVarType(5606TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))5607D.setInvalidType();5608}56095610// Get the visibility (access control) for this ivar.5611ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword5612? TranslateIvarVisibility(Visibility)5613: ObjCIvarDecl::None;5614// Must set ivar's DeclContext to its enclosing interface.5615ObjCContainerDecl *EnclosingDecl =5616cast<ObjCContainerDecl>(SemaRef.CurContext);5617if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())5618return nullptr;5619ObjCContainerDecl *EnclosingContext;5620if (ObjCImplementationDecl *IMPDecl =5621dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {5622if (getLangOpts().ObjCRuntime.isFragile()) {5623// Case of ivar declared in an implementation. Context is that of its5624// class.5625EnclosingContext = IMPDecl->getClassInterface();5626assert(EnclosingContext && "Implementation has no class interface!");5627} else5628EnclosingContext = EnclosingDecl;5629} else {5630if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {5631if (getLangOpts().ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {5632Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();5633return nullptr;5634}5635}5636EnclosingContext = EnclosingDecl;5637}56385639// Construct the decl.5640ObjCIvarDecl *NewID =5641ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc,5642II, T, TInfo, ac, BitWidth);56435644if (T->containsErrors())5645NewID->setInvalidDecl();56465647if (II) {5648NamedDecl *PrevDecl =5649SemaRef.LookupSingleName(S, II, Loc, Sema::LookupMemberName,5650RedeclarationKind::ForVisibleRedeclaration);5651if (PrevDecl && SemaRef.isDeclInScope(PrevDecl, EnclosingContext, S) &&5652!isa<TagDecl>(PrevDecl)) {5653Diag(Loc, diag::err_duplicate_member) << II;5654Diag(PrevDecl->getLocation(), diag::note_previous_declaration);5655NewID->setInvalidDecl();5656}5657}56585659// Process attributes attached to the ivar.5660SemaRef.ProcessDeclAttributes(S, NewID, D);56615662if (D.isInvalidType())5663NewID->setInvalidDecl();56645665// In ARC, infer 'retaining' for ivars of retainable type.5666if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID))5667NewID->setInvalidDecl();56685669if (D.getDeclSpec().isModulePrivateSpecified())5670NewID->setModulePrivate();56715672if (II) {5673// FIXME: When interfaces are DeclContexts, we'll need to add5674// these to the interface.5675S->AddDecl(NewID);5676SemaRef.IdResolver.AddDecl(NewID);5677}56785679if (getLangOpts().ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() &&5680isa<ObjCInterfaceDecl>(EnclosingDecl))5681Diag(Loc, diag::warn_ivars_in_interface);56825683return NewID;5684}568556865687