5693 lines · cpp
1//===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements semantic analysis for Objective C declarations.10//11//===----------------------------------------------------------------------===//12 13#include "TypeLocBuilder.h"14#include "clang/AST/ASTConsumer.h"15#include "clang/AST/ASTContext.h"16#include "clang/AST/ASTMutationListener.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/DynamicRecursiveASTVisitor.h"19#include "clang/AST/Expr.h"20#include "clang/AST/ExprObjC.h"21#include "clang/Basic/SourceManager.h"22#include "clang/Basic/TargetInfo.h"23#include "clang/Sema/DeclSpec.h"24#include "clang/Sema/DelayedDiagnostic.h"25#include "clang/Sema/Initialization.h"26#include "clang/Sema/Lookup.h"27#include "clang/Sema/Scope.h"28#include "clang/Sema/ScopeInfo.h"29#include "clang/Sema/SemaObjC.h"30#include "llvm/ADT/DenseMap.h"31#include "llvm/ADT/DenseSet.h"32 33using namespace clang;34 35/// 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,45 QualType receiverTypeIfCall) {46 ASTContext &Context = getASTContext();47 if (method->isInvalidDecl()) return true;48 49 // 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).52 53 // We ignore protocols here. Should we? What about Class?54 55 const ObjCObjectType *result =56 method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType();57 58 if (result->isObjCId()) {59 return false;60 } else if (result->isObjCClass()) {61 // fall through: always an error62 } else {63 ObjCInterfaceDecl *resultClass = result->getInterface();64 assert(resultClass && "unexpected object type!");65 66 // It's okay for the result type to still be a forward declaration67 // if we're checking an interface declaration.68 if (!resultClass->hasDefinition()) {69 if (receiverTypeIfCall.isNull() &&70 !isa<ObjCImplementationDecl>(method->getDeclContext()))71 return false;72 73 // 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.77 const ObjCInterfaceDecl *receiverClass = nullptr;78 if (isa<ObjCProtocolDecl>(method->getDeclContext())) {79 if (receiverTypeIfCall.isNull())80 return false;81 82 receiverClass = receiverTypeIfCall->castAs<ObjCObjectPointerType>()83 ->getInterfaceDecl();84 85 // This can be null for calls to e.g. id<Foo>.86 if (!receiverClass) return false;87 } else {88 receiverClass = method->getClassInterface();89 assert(receiverClass && "method not associated with a class!");90 }91 92 // If either class is a subclass of the other, it's fine.93 if (receiverClass->isSuperClassOf(resultClass) ||94 resultClass->isSuperClassOf(receiverClass))95 return false;96 }97 }98 99 SourceLocation loc = method->getLocation();100 101 // If we're in a system header, and this is not a call, just make102 // the method unusable.103 if (receiverTypeIfCall.isNull() &&104 SemaRef.getSourceManager().isInSystemHeader(loc)) {105 method->addAttr(UnavailableAttr::CreateImplicit(Context, "",106 UnavailableAttr::IR_ARCInitReturnsUnrelated, loc));107 return true;108 }109 110 // Otherwise, it's an error.111 Diag(loc, diag::err_arc_init_method_unrelated_result_type);112 method->setInvalidDecl();113 return true;114}115 116/// 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,119 Sema &S) {120 if (OldD->hasAttr<NoEscapeAttr>() && !NewD->hasAttr<NoEscapeAttr>()) {121 S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape);122 S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape);123 return false;124 }125 126 return true;127}128 129/// 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,132 const ObjCCategoryDecl *CD,133 const ObjCProtocolDecl *PD, Sema &S) {134 if (!diagnoseNoescape(NewD, OldD, S))135 S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot)136 << CD->IsClassExtension() << PD137 << cast<ObjCMethodDecl>(NewD->getDeclContext());138}139 140void SemaObjC::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,141 const ObjCMethodDecl *Overridden) {142 ASTContext &Context = getASTContext();143 if (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.149 QualType ResultType = NewMethod->getReturnType();150 SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange();151 152 // Figure out which class this method is part of, if any.153 ObjCInterfaceDecl *CurrentClass154 = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext());155 if (!CurrentClass) {156 DeclContext *DC = NewMethod->getDeclContext();157 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC))158 CurrentClass = Cat->getClassInterface();159 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC))160 CurrentClass = Impl->getClassInterface();161 else if (ObjCCategoryImplDecl *CatImpl162 = dyn_cast<ObjCCategoryImplDecl>(DC))163 CurrentClass = CatImpl->getClassInterface();164 }165 166 if (CurrentClass) {167 Diag(NewMethod->getLocation(),168 diag::warn_related_result_type_compatibility_class)169 << Context.getObjCInterfaceType(CurrentClass)170 << ResultType171 << ResultTypeRange;172 } else {173 Diag(NewMethod->getLocation(),174 diag::warn_related_result_type_compatibility_protocol)175 << ResultType176 << ResultTypeRange;177 }178 179 if (ObjCMethodFamily Family = Overridden->getMethodFamily())180 Diag(Overridden->getLocation(),181 diag::note_related_result_type_family)182 << /*overridden method*/ 0183 << Family;184 else185 Diag(Overridden->getLocation(),186 diag::note_related_result_type_overridden);187 }188 189 if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=190 Overridden->hasAttr<NSReturnsRetainedAttr>())) {191 Diag(NewMethod->getLocation(),192 getLangOpts().ObjCAutoRefCount193 ? diag::err_nsreturns_retained_attribute_mismatch194 : diag::warn_nsreturns_retained_attribute_mismatch)195 << 1;196 Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";197 }198 if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=199 Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {200 Diag(NewMethod->getLocation(),201 getLangOpts().ObjCAutoRefCount202 ? diag::err_nsreturns_retained_attribute_mismatch203 : diag::warn_nsreturns_retained_attribute_mismatch)204 << 0;205 Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";206 }207 208 ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),209 oe = Overridden->param_end();210 for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(),211 ne = NewMethod->param_end();212 ni != ne && oi != oe; ++ni, ++oi) {213 const ParmVarDecl *oldDecl = (*oi);214 ParmVarDecl *newDecl = (*ni);215 if (newDecl->hasAttr<NSConsumedAttr>() !=216 oldDecl->hasAttr<NSConsumedAttr>()) {217 Diag(newDecl->getLocation(),218 getLangOpts().ObjCAutoRefCount219 ? diag::err_nsconsumed_attribute_mismatch220 : diag::warn_nsconsumed_attribute_mismatch);221 Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";222 }223 224 diagnoseNoescape(newDecl, oldDecl, SemaRef);225 }226}227 228/// Check a method declaration for compatibility with the Objective-C229/// ARC conventions.230bool SemaObjC::CheckARCMethodDecl(ObjCMethodDecl *method) {231 ASTContext &Context = getASTContext();232 ObjCMethodFamily family = method->getMethodFamily();233 switch (family) {234 case OMF_None:235 case OMF_finalize:236 case OMF_retain:237 case OMF_release:238 case OMF_autorelease:239 case OMF_retainCount:240 case OMF_self:241 case OMF_initialize:242 case OMF_performSelector:243 return false;244 245 case OMF_dealloc:246 if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) {247 SourceRange ResultTypeRange = method->getReturnTypeSourceRange();248 if (ResultTypeRange.isInvalid())249 Diag(method->getLocation(), diag::err_dealloc_bad_result_type)250 << method->getReturnType()251 << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");252 else253 Diag(method->getLocation(), diag::err_dealloc_bad_result_type)254 << method->getReturnType()255 << FixItHint::CreateReplacement(ResultTypeRange, "void");256 return true;257 }258 return false;259 260 case OMF_init:261 // If the method doesn't obey the init rules, don't bother annotating it.262 if (checkInitMethod(method, QualType()))263 return true;264 265 method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context));266 267 // Don't add a second copy of this attribute, but otherwise don't268 // let it be suppressed.269 if (method->hasAttr<NSReturnsRetainedAttr>())270 return false;271 break;272 273 case OMF_alloc:274 case OMF_copy:275 case OMF_mutableCopy:276 case OMF_new:277 if (method->hasAttr<NSReturnsRetainedAttr>() ||278 method->hasAttr<NSReturnsNotRetainedAttr>() ||279 method->hasAttr<NSReturnsAutoreleasedAttr>())280 return false;281 break;282 }283 284 method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context));285 return false;286}287 288static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND,289 SourceLocation ImplLoc) {290 if (!ND)291 return;292 bool IsCategory = false;293 StringRef RealizedPlatform;294 AvailabilityResult Availability = ND->getAvailability(295 /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(),296 &RealizedPlatform);297 if (Availability != AR_Deprecated) {298 if (isa<ObjCMethodDecl>(ND)) {299 if (Availability != AR_Unavailable)300 return;301 if (RealizedPlatform.empty())302 RealizedPlatform = S.Context.getTargetInfo().getPlatformName();303 // Warn about implementing unavailable methods, unless the unavailable304 // is for an app extension.305 if (RealizedPlatform.ends_with("_app_extension"))306 return;307 S.Diag(ImplLoc, diag::warn_unavailable_def);308 S.Diag(ND->getLocation(), diag::note_method_declared_at)309 << ND->getDeclName();310 return;311 }312 if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND)) {313 if (!CD->getClassInterface()->isDeprecated())314 return;315 ND = CD->getClassInterface();316 IsCategory = true;317 } else318 return;319 }320 S.Diag(ImplLoc, diag::warn_deprecated_def)321 << (isa<ObjCMethodDecl>(ND)322 ? /*Method*/ 0323 : isa<ObjCCategoryDecl>(ND) || IsCategory ? /*Category*/ 2324 : /*Class*/ 1);325 if (isa<ObjCMethodDecl>(ND))326 S.Diag(ND->getLocation(), diag::note_method_declared_at)327 << ND->getDeclName();328 else329 S.Diag(ND->getLocation(), diag::note_previous_decl)330 << (isa<ObjCCategoryDecl>(ND) ? "category" : "class");331}332 333/// AddAnyMethodToGlobalPool - Add any method, instance or factory to global334/// pool.335void SemaObjC::AddAnyMethodToGlobalPool(Decl *D) {336 ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);337 338 // If we don't have a valid method decl, simply return.339 if (!MDecl)340 return;341 if (MDecl->isInstanceMethod())342 AddInstanceMethodToGlobalPool(MDecl, true);343 else344 AddFactoryMethodToGlobalPool(MDecl, true);345}346 347/// HasExplicitOwnershipAttr - returns true when pointer to ObjC pointer348/// has explicit ownership attribute; false otherwise.349static bool350HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) {351 QualType T = Param->getType();352 353 if (const PointerType *PT = T->getAs<PointerType>()) {354 T = PT->getPointeeType();355 } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) {356 T = RT->getPointeeType();357 } else {358 return true;359 }360 361 // If we have a lifetime qualifier, but it's local, we must have362 // inferred it. So, it is implicit.363 return !T.getLocalQualifiers().hasObjCLifetime();364}365 366/// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible367/// and user declared, in the method definition's AST.368void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) {369 ASTContext &Context = getASTContext();370 SemaRef.ImplicitlyRetainedSelfLocs.clear();371 assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused");372 ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D);373 374 SemaRef.PushExpressionEvaluationContext(375 SemaRef.ExprEvalContexts.back().Context);376 377 // If we don't have a valid method decl, simply return.378 if (!MDecl)379 return;380 381 QualType ResultType = MDecl->getReturnType();382 if (!ResultType->isDependentType() && !ResultType->isVoidType() &&383 !MDecl->isInvalidDecl() &&384 SemaRef.RequireCompleteType(MDecl->getLocation(), ResultType,385 diag::err_func_def_incomplete_result))386 MDecl->setInvalidDecl();387 388 // Allow all of Sema to see that we are entering a method definition.389 SemaRef.PushDeclContext(FnBodyScope, MDecl);390 SemaRef.PushFunctionScope();391 392 // Create Decl objects for each parameter, entrring them in the scope for393 // binding to their use.394 395 // Insert the invisible arguments, self and _cmd!396 MDecl->createImplicitParams(Context, MDecl->getClassInterface());397 398 SemaRef.PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope);399 SemaRef.PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope);400 401 // The ObjC parser requires parameter names so there's no need to check.402 SemaRef.CheckParmsForFunctionDef(MDecl->parameters(),403 /*CheckParameterNames=*/false);404 405 // Introduce all of the other parameters into this scope.406 for (auto *Param : MDecl->parameters()) {407 if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount &&408 !HasExplicitOwnershipAttr(SemaRef, Param))409 Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) <<410 Param->getType();411 412 if (Param->getIdentifier())413 SemaRef.PushOnScopeChains(Param, FnBodyScope);414 }415 416 // In ARC, disallow definition of retain/release/autorelease/retainCount417 if (getLangOpts().ObjCAutoRefCount) {418 switch (MDecl->getMethodFamily()) {419 case OMF_retain:420 case OMF_retainCount:421 case OMF_release:422 case OMF_autorelease:423 Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def)424 << 0 << MDecl->getSelector();425 break;426 427 case OMF_None:428 case OMF_dealloc:429 case OMF_finalize:430 case OMF_alloc:431 case OMF_init:432 case OMF_mutableCopy:433 case OMF_copy:434 case OMF_new:435 case OMF_self:436 case OMF_initialize:437 case OMF_performSelector:438 break;439 }440 }441 442 // Warn on deprecated methods under -Wdeprecated-implementations,443 // and prepare for warning on missing super calls.444 if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) {445 ObjCMethodDecl *IMD =446 IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod());447 448 if (IMD) {449 ObjCImplDecl *ImplDeclOfMethodDef =450 dyn_cast<ObjCImplDecl>(MDecl->getDeclContext());451 ObjCContainerDecl *ContDeclOfMethodDecl =452 dyn_cast<ObjCContainerDecl>(IMD->getDeclContext());453 ObjCImplDecl *ImplDeclOfMethodDecl = nullptr;454 if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl))455 ImplDeclOfMethodDecl = OID->getImplementation();456 else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) {457 if (CD->IsClassExtension()) {458 if (ObjCInterfaceDecl *OID = CD->getClassInterface())459 ImplDeclOfMethodDecl = OID->getImplementation();460 } else461 ImplDeclOfMethodDecl = 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).465 if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef)466 DiagnoseObjCImplementedDeprecations(SemaRef, IMD, MDecl->getLocation());467 }468 469 if (MDecl->getMethodFamily() == OMF_init) {470 if (MDecl->isDesignatedInitializerForTheInterface()) {471 SemaRef.getCurFunction()->ObjCIsDesignatedInit = true;472 SemaRef.getCurFunction()->ObjCWarnForNoDesignatedInitChain =473 IC->getSuperClass() != nullptr;474 } else if (IC->hasDesignatedInitializers()) {475 SemaRef.getCurFunction()->ObjCIsSecondaryInit = true;476 SemaRef.getCurFunction()->ObjCWarnForNoInitDelegation = true;477 }478 }479 480 // 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.484 if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) {485 ObjCMethodFamily Family = MDecl->getMethodFamily();486 if (Family == OMF_dealloc) {487 if (!(getLangOpts().ObjCAutoRefCount ||488 getLangOpts().getGC() == LangOptions::GCOnly))489 SemaRef.getCurFunction()->ObjCShouldCallSuper = true;490 491 } else if (Family == OMF_finalize) {492 if (Context.getLangOpts().getGC() != LangOptions::NonGC)493 SemaRef.getCurFunction()->ObjCShouldCallSuper = true;494 495 } else {496 const ObjCMethodDecl *SuperMethod =497 SuperClass->lookupMethod(MDecl->getSelector(),498 MDecl->isInstanceMethod());499 SemaRef.getCurFunction()->ObjCShouldCallSuper =500 (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>());501 }502 }503 }504 505 // Some function attributes (like OptimizeNoneAttr) need actions before506 // parsing body started.507 SemaRef.applyFunctionAttributesBeforeParsingBody(D);508}509 510namespace {511 512// 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 {516 public:517 ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {}518 explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl)519 : CurrentIDecl(IDecl) {}520 521 bool ValidateCandidate(const TypoCorrection &candidate) override {522 ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>();523 return ID && !declaresSameEntity(ID, CurrentIDecl);524 }525 526 std::unique_ptr<CorrectionCandidateCallback> clone() override {527 return std::make_unique<ObjCInterfaceValidatorCCC>(*this);528 }529 530 private:531 ObjCInterfaceDecl *CurrentIDecl;532};533 534} // end anonymous namespace535 536static void diagnoseUseOfProtocols(Sema &TheSema,537 ObjCContainerDecl *CD,538 ObjCProtocolDecl *const *ProtoRefs,539 unsigned NumProtoRefs,540 const SourceLocation *ProtoLocs) {541 assert(ProtoRefs);542 // Diagnose availability in the context of the ObjC container.543 Sema::ContextRAII SavedContext(TheSema, CD);544 for (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}551 552void SemaObjC::ActOnSuperClassOfClassInterface(553 Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl,554 IdentifierInfo *ClassName, SourceLocation ClassLoc,555 IdentifierInfo *SuperName, SourceLocation SuperLoc,556 ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange) {557 ASTContext &Context = getASTContext();558 // Check if a different kind of symbol declared in this scope.559 NamedDecl *PrevDecl = SemaRef.LookupSingleName(560 SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);561 562 if (!PrevDecl) {563 // Try to correct for a typo in the superclass name without correcting564 // to the class we're defining.565 ObjCInterfaceValidatorCCC CCC(IDecl);566 if (TypoCorrection Corrected = SemaRef.CorrectTypo(567 DeclarationNameInfo(SuperName, SuperLoc), Sema::LookupOrdinaryName,568 SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::ErrorRecovery)) {569 SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest)570 << SuperName << ClassName);571 PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>();572 }573 }574 575 if (declaresSameEntity(PrevDecl, IDecl)) {576 Diag(SuperLoc, diag::err_recursive_superclass)577 << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);578 IDecl->setEndOfDefinitionLoc(ClassLoc);579 } else {580 ObjCInterfaceDecl *SuperClassDecl =581 dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);582 QualType SuperClassType;583 584 // Diagnose classes that inherit from deprecated classes.585 if (SuperClassDecl) {586 (void)SemaRef.DiagnoseUseOfDecl(SuperClassDecl, SuperLoc);587 SuperClassType = Context.getObjCInterfaceType(SuperClassDecl);588 }589 590 if (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.593 if (const TypedefNameDecl *TDecl =594 dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {595 QualType T = TDecl->getUnderlyingType();596 if (T->isObjCObjectType()) {597 if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {598 SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl);599 SuperClassType = Context.getTypeDeclType(600 ElaboratedTypeKeyword::None, /*Qualifier=*/std::nullopt, TDecl);601 602 // This handles the following case:603 // @interface NewI @end604 // typedef NewI DeprI __attribute__((deprecated("blah")))605 // @interface SI : DeprI /* warn here */ @end606 (void)SemaRef.DiagnoseUseOfDecl(607 const_cast<TypedefNameDecl *>(TDecl), SuperLoc);608 }609 }610 }611 612 // This handles the following case:613 //614 // typedef int SuperClass;615 // @interface MyClass : SuperClass {} @end616 //617 if (!SuperClassDecl) {618 Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;619 Diag(PrevDecl->getLocation(), diag::note_previous_definition);620 }621 }622 623 if (!isa_and_nonnull<TypedefNameDecl>(PrevDecl)) {624 if (!SuperClassDecl)625 Diag(SuperLoc, diag::err_undef_superclass)626 << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc);627 else if (SemaRef.RequireCompleteType(628 SuperLoc, SuperClassType, diag::err_forward_superclass,629 SuperClassDecl->getDeclName(), ClassName,630 SourceRange(AtInterfaceLoc, ClassLoc))) {631 SuperClassDecl = nullptr;632 SuperClassType = QualType();633 }634 }635 636 if (SuperClassType.isNull()) {637 assert(!SuperClassDecl && "Failed to set SuperClassType?");638 return;639 }640 641 // Handle type arguments on the superclass.642 TypeSourceInfo *SuperClassTInfo = nullptr;643 if (!SuperTypeArgs.empty()) {644 TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers(645 S, SuperLoc, SemaRef.CreateParsedType(SuperClassType, nullptr),646 SuperTypeArgsRange.getBegin(), SuperTypeArgs,647 SuperTypeArgsRange.getEnd(), SourceLocation(), {}, {},648 SourceLocation());649 if (!fullSuperClassType.isUsable())650 return;651 652 SuperClassType =653 SemaRef.GetTypeFromParser(fullSuperClassType.get(), &SuperClassTInfo);654 }655 656 if (!SuperClassTInfo) {657 SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType,658 SuperLoc);659 }660 661 IDecl->setSuperClass(SuperClassTInfo);662 IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc());663 getASTContext().addObjCSubClass(IDecl->getSuperClass(), IDecl);664 }665}666 667DeclResult SemaObjC::actOnObjCTypeParam(668 Scope *S, ObjCTypeParamVariance variance, SourceLocation varianceLoc,669 unsigned index, IdentifierInfo *paramName, SourceLocation paramLoc,670 SourceLocation colonLoc, ParsedType parsedTypeBound) {671 ASTContext &Context = getASTContext();672 // If there was an explicitly-provided type bound, check it.673 TypeSourceInfo *typeBoundInfo = nullptr;674 if (parsedTypeBound) {675 // The type bound can be any Objective-C pointer type.676 QualType typeBound =677 SemaRef.GetTypeFromParser(parsedTypeBound, &typeBoundInfo);678 if (typeBound->isObjCObjectPointerType()) {679 // okay680 } else if (typeBound->isObjCObjectType()) {681 // The user forgot the * on an Objective-C pointer type, e.g.,682 // "T : NSView".683 SourceLocation starLoc =684 SemaRef.getLocForEndOfToken(typeBoundInfo->getTypeLoc().getEndLoc());685 Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),686 diag::err_objc_type_param_bound_missing_pointer)687 << typeBound << paramName688 << FixItHint::CreateInsertion(starLoc, " *");689 690 // Create a new type location builder so we can update the type691 // location information we have.692 TypeLocBuilder builder;693 builder.pushFullCopy(typeBoundInfo->getTypeLoc());694 695 // Create the Objective-C pointer type.696 typeBound = Context.getObjCObjectPointerType(typeBound);697 ObjCObjectPointerTypeLoc newT698 = builder.push<ObjCObjectPointerTypeLoc>(typeBound);699 newT.setStarLoc(starLoc);700 701 // Form the new type source information.702 typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound);703 } else {704 // Not a valid type bound.705 Diag(typeBoundInfo->getTypeLoc().getBeginLoc(),706 diag::err_objc_type_param_bound_nonobject)707 << typeBound << paramName;708 709 // Forget the bound; we'll default to id later.710 typeBoundInfo = nullptr;711 }712 713 // Type bounds cannot have qualifiers (even indirectly) or explicit714 // nullability.715 if (typeBoundInfo) {716 QualType typeBound = typeBoundInfo->getType();717 TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc();718 if (qual || typeBound.hasQualifiers()) {719 bool diagnosed = false;720 SourceRange rangeToRemove;721 if (qual) {722 if (auto attr = qual.getAs<AttributedTypeLoc>()) {723 rangeToRemove = attr.getLocalSourceRange();724 if (attr.getTypePtr()->getImmediateNullability()) {725 Diag(attr.getBeginLoc(),726 diag::err_objc_type_param_bound_explicit_nullability)727 << paramName << typeBound728 << FixItHint::CreateRemoval(rangeToRemove);729 diagnosed = true;730 }731 }732 }733 734 if (!diagnosed) {735 Diag(qual ? qual.getBeginLoc()736 : typeBoundInfo->getTypeLoc().getBeginLoc(),737 diag::err_objc_type_param_bound_qualified)738 << paramName << typeBound739 << typeBound.getQualifiers().getAsString()740 << FixItHint::CreateRemoval(rangeToRemove);741 }742 743 // If the type bound has qualifiers other than CVR, we need to strip744 // them or we'll probably assert later when trying to apply new745 // qualifiers.746 Qualifiers quals = typeBound.getQualifiers();747 quals.removeCVRQualifiers();748 if (!quals.empty()) {749 typeBoundInfo =750 Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType());751 }752 }753 }754 }755 756 // If there was no explicit type bound (or we removed it due to an error),757 // use 'id' instead.758 if (!typeBoundInfo) {759 colonLoc = SourceLocation();760 typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType());761 }762 763 // Create the type parameter.764 return ObjCTypeParamDecl::Create(Context, SemaRef.CurContext, variance,765 varianceLoc, index, paramLoc, paramName,766 colonLoc, typeBoundInfo);767}768 769ObjCTypeParamList *770SemaObjC::actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc,771 ArrayRef<Decl *> typeParamsIn,772 SourceLocation rAngleLoc) {773 ASTContext &Context = getASTContext();774 // We know that the array only contains Objective-C type parameters.775 ArrayRef<ObjCTypeParamDecl *>776 typeParams(777 reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()),778 typeParamsIn.size());779 780 // Diagnose redeclarations of type parameters.781 // We do this now because Objective-C type parameters aren't pushed into782 // scope until later (after the instance variable block), but we want the783 // diagnostics to occur right after we parse the type parameter list.784 llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams;785 for (auto *typeParam : typeParams) {786 auto known = knownParams.find(typeParam->getIdentifier());787 if (known != knownParams.end()) {788 Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl)789 << typeParam->getIdentifier()790 << SourceRange(known->second->getLocation());791 792 typeParam->setInvalidDecl();793 } else {794 knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam));795 796 // Push the type parameter into scope.797 SemaRef.PushOnScopeChains(typeParam, S, /*AddToContext=*/false);798 }799 }800 801 // Create the parameter list.802 return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc);803}804 805void SemaObjC::popObjCTypeParamList(Scope *S,806 ObjCTypeParamList *typeParamList) {807 for (auto *typeParam : *typeParamList) {808 if (!typeParam->isInvalidDecl()) {809 S->RemoveDecl(typeParam);810 SemaRef.IdResolver.RemoveDecl(typeParam);811 }812 }813}814 815namespace {816 /// The context in which an Objective-C type parameter list occurs, for use817 /// in diagnostics.818 enum class TypeParamListContext {819 ForwardDeclaration,820 Definition,821 Category,822 Extension823 };824} // end anonymous namespace825 826/// Check consistency between two Objective-C type parameter lists, e.g.,827/// between a category/extension and an \@interface or between an \@class and an828/// \@interface.829static bool checkTypeParamListConsistency(Sema &S,830 ObjCTypeParamList *prevTypeParams,831 ObjCTypeParamList *newTypeParams,832 TypeParamListContext newContext) {833 // If the sizes don't match, complain about that.834 if (prevTypeParams->size() != newTypeParams->size()) {835 SourceLocation diagLoc;836 if (newTypeParams->size() > prevTypeParams->size()) {837 diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation();838 } else {839 diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc());840 }841 842 S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch)843 << static_cast<unsigned>(newContext)844 << (newTypeParams->size() > prevTypeParams->size())845 << prevTypeParams->size()846 << newTypeParams->size();847 848 return true;849 }850 851 // Match up the type parameters.852 for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) {853 ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i];854 ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i];855 856 // Check for consistency of the variance.857 if (newTypeParam->getVariance() != prevTypeParam->getVariance()) {858 if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant &&859 newContext != TypeParamListContext::Definition) {860 // When the new type parameter is invariant and is not part861 // of the definition, just propagate the variance.862 newTypeParam->setVariance(prevTypeParam->getVariance());863 } else if (prevTypeParam->getVariance()864 == ObjCTypeParamVariance::Invariant &&865 !(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) &&866 cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext())867 ->getDefinition() == prevTypeParam->getDeclContext())) {868 // When the old parameter is invariant and was not part of the869 // definition, just ignore the difference because it doesn't870 // matter.871 } else {872 {873 // Diagnose the conflict and update the second declaration.874 SourceLocation diagLoc = newTypeParam->getVarianceLoc();875 if (diagLoc.isInvalid())876 diagLoc = newTypeParam->getBeginLoc();877 878 auto diag = S.Diag(diagLoc,879 diag::err_objc_type_param_variance_conflict)880 << static_cast<unsigned>(newTypeParam->getVariance())881 << newTypeParam->getDeclName()882 << static_cast<unsigned>(prevTypeParam->getVariance())883 << prevTypeParam->getDeclName();884 switch (prevTypeParam->getVariance()) {885 case ObjCTypeParamVariance::Invariant:886 diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc());887 break;888 889 case ObjCTypeParamVariance::Covariant:890 case ObjCTypeParamVariance::Contravariant: {891 StringRef newVarianceStr892 = prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant893 ? "__covariant"894 : "__contravariant";895 if (newTypeParam->getVariance()896 == ObjCTypeParamVariance::Invariant) {897 diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(),898 (newVarianceStr + " ").str());899 } else {900 diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(),901 newVarianceStr);902 }903 }904 }905 }906 907 S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)908 << prevTypeParam->getDeclName();909 910 // Override the variance.911 newTypeParam->setVariance(prevTypeParam->getVariance());912 }913 }914 915 // If the bound types match, there's nothing to do.916 if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(),917 newTypeParam->getUnderlyingType()))918 continue;919 920 // If the new type parameter's bound was explicit, complain about it being921 // different from the original.922 if (newTypeParam->hasExplicitBound()) {923 SourceRange newBoundRange = newTypeParam->getTypeSourceInfo()924 ->getTypeLoc().getSourceRange();925 S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict)926 << newTypeParam->getUnderlyingType()927 << newTypeParam->getDeclName()928 << prevTypeParam->hasExplicitBound()929 << prevTypeParam->getUnderlyingType()930 << (newTypeParam->getDeclName() == prevTypeParam->getDeclName())931 << prevTypeParam->getDeclName()932 << FixItHint::CreateReplacement(933 newBoundRange,934 prevTypeParam->getUnderlyingType().getAsString(935 S.Context.getPrintingPolicy()));936 937 S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)938 << prevTypeParam->getDeclName();939 940 // Override the new type parameter's bound type with the previous type,941 // so that it's consistent.942 S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);943 continue;944 }945 946 // The new type parameter got the implicit bound of 'id'. That's okay for947 // categories and extensions (overwrite it later), but not for forward948 // declarations and @interfaces, because those must be standalone.949 if (newContext == TypeParamListContext::ForwardDeclaration ||950 newContext == TypeParamListContext::Definition) {951 // Diagnose this problem for forward declarations and definitions.952 SourceLocation insertionLoc953 = S.getLocForEndOfToken(newTypeParam->getLocation());954 std::string newCode955 = " : " + prevTypeParam->getUnderlyingType().getAsString(956 S.Context.getPrintingPolicy());957 S.Diag(newTypeParam->getLocation(),958 diag::err_objc_type_param_bound_missing)959 << prevTypeParam->getUnderlyingType()960 << newTypeParam->getDeclName()961 << (newContext == TypeParamListContext::ForwardDeclaration)962 << FixItHint::CreateInsertion(insertionLoc, newCode);963 964 S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here)965 << prevTypeParam->getDeclName();966 }967 968 // Update the new type parameter's bound to match the previous one.969 S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam);970 }971 972 return false;973}974 975ObjCInterfaceDecl *SemaObjC::ActOnStartClassInterface(976 Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName,977 SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,978 IdentifierInfo *SuperName, SourceLocation SuperLoc,979 ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange,980 Decl *const *ProtoRefs, unsigned NumProtoRefs,981 const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,982 const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {983 assert(ClassName && "Missing class identifier");984 985 ASTContext &Context = getASTContext();986 // Check for another declaration kind with the same name.987 NamedDecl *PrevDecl = SemaRef.LookupSingleName(988 SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,989 SemaRef.forRedeclarationInCurContext());990 991 if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {992 Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;993 Diag(PrevDecl->getLocation(), diag::note_previous_definition);994 }995 996 // Create a declaration to describe this @interface.997 ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);998 999 if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {1000 // A previous decl with a different name is because of1001 // @compatibility_alias, for example:1002 // \code1003 // @class NewImage;1004 // @compatibility_alias OldImage NewImage;1005 // \endcode1006 // A lookup for 'OldImage' will return the 'NewImage' decl.1007 //1008 // In such a case use the real declaration name, instead of the alias one,1009 // otherwise we will break IdentifierResolver and redecls-chain invariants.1010 // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl1011 // has been aliased.1012 ClassName = PrevIDecl->getIdentifier();1013 }1014 1015 // If there was a forward declaration with type parameters, check1016 // for consistency.1017 if (PrevIDecl) {1018 if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) {1019 if (typeParamList) {1020 // Both have type parameter lists; check for consistency.1021 if (checkTypeParamListConsistency(SemaRef, prevTypeParamList,1022 typeParamList,1023 TypeParamListContext::Definition)) {1024 typeParamList = nullptr;1025 }1026 } else {1027 Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first)1028 << ClassName;1029 Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl)1030 << ClassName;1031 1032 // Clone the type parameter list.1033 SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams;1034 for (auto *typeParam : *prevTypeParamList) {1035 clonedTypeParams.push_back(ObjCTypeParamDecl::Create(1036 Context, SemaRef.CurContext, typeParam->getVariance(),1037 SourceLocation(), typeParam->getIndex(), SourceLocation(),1038 typeParam->getIdentifier(), SourceLocation(),1039 Context.getTrivialTypeSourceInfo(1040 typeParam->getUnderlyingType())));1041 }1042 1043 typeParamList = ObjCTypeParamList::create(Context,1044 SourceLocation(),1045 clonedTypeParams,1046 SourceLocation());1047 }1048 }1049 }1050 1051 ObjCInterfaceDecl *IDecl =1052 ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,1053 ClassName, typeParamList, PrevIDecl, ClassLoc);1054 if (PrevIDecl) {1055 // Class already seen. Was it a definition?1056 if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {1057 if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {1058 SkipBody->CheckSameAsPrevious = true;1059 SkipBody->New = IDecl;1060 SkipBody->Previous = Def;1061 } else {1062 Diag(AtInterfaceLoc, diag::err_duplicate_class_def)1063 << PrevIDecl->getDeclName();1064 Diag(Def->getLocation(), diag::note_previous_definition);1065 IDecl->setInvalidDecl();1066 }1067 }1068 }1069 1070 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IDecl, AttrList);1071 SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);1072 SemaRef.ProcessAPINotes(IDecl);1073 1074 // Merge attributes from previous declarations.1075 if (PrevIDecl)1076 SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);1077 1078 SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);1079 1080 // Start the definition of this class. If we're in a redefinition case, there1081 // may already be a definition, so we'll end up adding to it.1082 if (SkipBody && SkipBody->CheckSameAsPrevious)1083 IDecl->startDuplicateDefinitionForComparison();1084 else if (!IDecl->hasDefinition())1085 IDecl->startDefinition();1086 1087 if (SuperName) {1088 // Diagnose availability in the context of the @interface.1089 Sema::ContextRAII SavedContext(SemaRef, IDecl);1090 1091 ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl,1092 ClassName, ClassLoc,1093 SuperName, SuperLoc, SuperTypeArgs,1094 SuperTypeArgsRange);1095 } else { // we have a root class.1096 IDecl->setEndOfDefinitionLoc(ClassLoc);1097 }1098 1099 // Check then save referenced protocols.1100 if (NumProtoRefs) {1101 diagnoseUseOfProtocols(SemaRef, IDecl, (ObjCProtocolDecl *const *)ProtoRefs,1102 NumProtoRefs, ProtoLocs);1103 IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1104 ProtoLocs, Context);1105 IDecl->setEndOfDefinitionLoc(EndProtoLoc);1106 }1107 1108 CheckObjCDeclScope(IDecl);1109 ActOnObjCContainerStartDefinition(IDecl);1110 return IDecl;1111}1112 1113/// ActOnTypedefedProtocols - this action finds protocol list as part of the1114/// typedef'ed use for a qualified super class and adds them to the list1115/// of the protocols.1116void SemaObjC::ActOnTypedefedProtocols(1117 SmallVectorImpl<Decl *> &ProtocolRefs,1118 SmallVectorImpl<SourceLocation> &ProtocolLocs, IdentifierInfo *SuperName,1119 SourceLocation SuperLoc) {1120 if (!SuperName)1121 return;1122 NamedDecl *IDecl = SemaRef.LookupSingleName(1123 SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName);1124 if (!IDecl)1125 return;1126 1127 if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) {1128 QualType T = TDecl->getUnderlyingType();1129 if (T->isObjCObjectType())1130 if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) {1131 ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end());1132 // FIXME: Consider whether this should be an invalid loc since the loc1133 // is not actually pointing to a protocol name reference but to the1134 // typedef reference. Note that the base class name loc is also pointing1135 // at the typedef.1136 ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc);1137 }1138 }1139}1140 1141/// ActOnCompatibilityAlias - this action is called after complete parsing of1142/// a \@compatibility_alias declaration. It sets up the alias relationships.1143Decl *SemaObjC::ActOnCompatibilityAlias(SourceLocation AtLoc,1144 IdentifierInfo *AliasName,1145 SourceLocation AliasLocation,1146 IdentifierInfo *ClassName,1147 SourceLocation ClassLocation) {1148 ASTContext &Context = getASTContext();1149 // Look for previous declaration of alias name1150 NamedDecl *ADecl = SemaRef.LookupSingleName(1151 SemaRef.TUScope, AliasName, AliasLocation, Sema::LookupOrdinaryName,1152 SemaRef.forRedeclarationInCurContext());1153 if (ADecl) {1154 Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName;1155 Diag(ADecl->getLocation(), diag::note_previous_declaration);1156 return nullptr;1157 }1158 // Check for class declaration1159 NamedDecl *CDeclU = SemaRef.LookupSingleName(1160 SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,1161 SemaRef.forRedeclarationInCurContext());1162 if (const TypedefNameDecl *TDecl =1163 dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {1164 QualType T = TDecl->getUnderlyingType();1165 if (T->isObjCObjectType()) {1166 if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) {1167 ClassName = IDecl->getIdentifier();1168 CDeclU = SemaRef.LookupSingleName(1169 SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName,1170 SemaRef.forRedeclarationInCurContext());1171 }1172 }1173 }1174 ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU);1175 if (!CDecl) {1176 Diag(ClassLocation, diag::warn_undef_interface) << ClassName;1177 if (CDeclU)1178 Diag(CDeclU->getLocation(), diag::note_previous_declaration);1179 return nullptr;1180 }1181 1182 // Everything checked out, instantiate a new alias declaration AST.1183 ObjCCompatibleAliasDecl *AliasDecl = ObjCCompatibleAliasDecl::Create(1184 Context, SemaRef.CurContext, AtLoc, AliasName, CDecl);1185 1186 if (!CheckObjCDeclScope(AliasDecl))1187 SemaRef.PushOnScopeChains(AliasDecl, SemaRef.TUScope);1188 1189 return AliasDecl;1190}1191 1192bool SemaObjC::CheckForwardProtocolDeclarationForCircularDependency(1193 IdentifierInfo *PName, SourceLocation &Ploc, SourceLocation PrevLoc,1194 const ObjCList<ObjCProtocolDecl> &PList) {1195 1196 bool res = false;1197 for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(),1198 E = PList.end(); I != E; ++I) {1199 if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), Ploc)) {1200 if (PDecl->getIdentifier() == PName) {1201 Diag(Ploc, diag::err_protocol_has_circular_dependency);1202 Diag(PrevLoc, diag::note_previous_definition);1203 res = true;1204 }1205 1206 if (!PDecl->hasDefinition())1207 continue;1208 1209 if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc,1210 PDecl->getLocation(), PDecl->getReferencedProtocols()))1211 res = true;1212 }1213 }1214 return res;1215}1216 1217ObjCProtocolDecl *SemaObjC::ActOnStartProtocolInterface(1218 SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName,1219 SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs,1220 const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,1221 const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) {1222 ASTContext &Context = getASTContext();1223 bool err = false;1224 // FIXME: Deal with AttrList.1225 assert(ProtocolName && "Missing protocol identifier");1226 ObjCProtocolDecl *PrevDecl = LookupProtocol(1227 ProtocolName, ProtocolLoc, SemaRef.forRedeclarationInCurContext());1228 ObjCProtocolDecl *PDecl = nullptr;1229 if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) {1230 // Create a new protocol that is completely distinct from previous1231 // declarations, and do not make this protocol available for name lookup.1232 // That way, we'll end up completely ignoring the duplicate.1233 // FIXME: Can we turn this into an error?1234 PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,1235 ProtocolLoc, AtProtoInterfaceLoc,1236 /*PrevDecl=*/Def);1237 1238 if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) {1239 SkipBody->CheckSameAsPrevious = true;1240 SkipBody->New = PDecl;1241 SkipBody->Previous = Def;1242 } else {1243 // If we already have a definition, complain.1244 Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName;1245 Diag(Def->getLocation(), diag::note_previous_definition);1246 }1247 1248 // If we are using modules, add the decl to the context in order to1249 // serialize something meaningful.1250 if (getLangOpts().Modules)1251 SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1252 PDecl->startDuplicateDefinitionForComparison();1253 } else {1254 if (PrevDecl) {1255 // Check for circular dependencies among protocol declarations. This can1256 // only happen if this protocol was forward-declared.1257 ObjCList<ObjCProtocolDecl> PList;1258 PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context);1259 err = CheckForwardProtocolDeclarationForCircularDependency(1260 ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList);1261 }1262 1263 // Create the new declaration.1264 PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName,1265 ProtocolLoc, AtProtoInterfaceLoc,1266 /*PrevDecl=*/PrevDecl);1267 1268 SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1269 PDecl->startDefinition();1270 }1271 1272 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, AttrList);1273 SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);1274 SemaRef.ProcessAPINotes(PDecl);1275 1276 // Merge attributes from previous declarations.1277 if (PrevDecl)1278 SemaRef.mergeDeclAttributes(PDecl, PrevDecl);1279 1280 if (!err && NumProtoRefs ) {1281 /// Check then save referenced protocols.1282 diagnoseUseOfProtocols(SemaRef, PDecl, (ObjCProtocolDecl *const *)ProtoRefs,1283 NumProtoRefs, ProtoLocs);1284 PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1285 ProtoLocs, Context);1286 }1287 1288 CheckObjCDeclScope(PDecl);1289 ActOnObjCContainerStartDefinition(PDecl);1290 return PDecl;1291}1292 1293static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl,1294 ObjCProtocolDecl *&UndefinedProtocol) {1295 if (!PDecl->hasDefinition() ||1296 !PDecl->getDefinition()->isUnconditionallyVisible()) {1297 UndefinedProtocol = PDecl;1298 return true;1299 }1300 1301 for (auto *PI : PDecl->protocols())1302 if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) {1303 UndefinedProtocol = PI;1304 return true;1305 }1306 return false;1307}1308 1309/// FindProtocolDeclaration - This routine looks up protocols and1310/// issues an error if they are not declared. It returns list of1311/// protocol declarations in its 'Protocols' argument.1312void SemaObjC::FindProtocolDeclaration(bool WarnOnDeclarations,1313 bool ForObjCContainer,1314 ArrayRef<IdentifierLoc> ProtocolId,1315 SmallVectorImpl<Decl *> &Protocols) {1316 for (const IdentifierLoc &Pair : ProtocolId) {1317 ObjCProtocolDecl *PDecl =1318 LookupProtocol(Pair.getIdentifierInfo(), Pair.getLoc());1319 if (!PDecl) {1320 DeclFilterCCC<ObjCProtocolDecl> CCC{};1321 TypoCorrection Corrected = SemaRef.CorrectTypo(1322 DeclarationNameInfo(Pair.getIdentifierInfo(), Pair.getLoc()),1323 Sema::LookupObjCProtocolName, SemaRef.TUScope, nullptr, CCC,1324 CorrectTypoKind::ErrorRecovery);1325 if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>()))1326 SemaRef.diagnoseTypo(Corrected,1327 PDiag(diag::err_undeclared_protocol_suggest)1328 << Pair.getIdentifierInfo());1329 }1330 1331 if (!PDecl) {1332 Diag(Pair.getLoc(), diag::err_undeclared_protocol)1333 << Pair.getIdentifierInfo();1334 continue;1335 }1336 // If this is a forward protocol declaration, get its definition.1337 if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())1338 PDecl = PDecl->getDefinition();1339 1340 // For an objc container, delay protocol reference checking until after we1341 // can set the objc decl as the availability context, otherwise check now.1342 if (!ForObjCContainer) {1343 (void)SemaRef.DiagnoseUseOfDecl(PDecl, Pair.getLoc());1344 }1345 1346 // If this is a forward declaration and we are supposed to warn in this1347 // case, do it.1348 // FIXME: Recover nicely in the hidden case.1349 ObjCProtocolDecl *UndefinedProtocol;1350 1351 if (WarnOnDeclarations &&1352 NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) {1353 Diag(Pair.getLoc(), diag::warn_undef_protocolref)1354 << Pair.getIdentifierInfo();1355 Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined)1356 << UndefinedProtocol;1357 }1358 Protocols.push_back(PDecl);1359 }1360}1361 1362namespace {1363// Callback to only accept typo corrections that are either1364// Objective-C protocols or valid Objective-C type arguments.1365class ObjCTypeArgOrProtocolValidatorCCC final1366 : public CorrectionCandidateCallback {1367 ASTContext &Context;1368 Sema::LookupNameKind LookupKind;1369 public:1370 ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context,1371 Sema::LookupNameKind lookupKind)1372 : Context(context), LookupKind(lookupKind) { }1373 1374 bool ValidateCandidate(const TypoCorrection &candidate) override {1375 // If we're allowed to find protocols and we have a protocol, accept it.1376 if (LookupKind != Sema::LookupOrdinaryName) {1377 if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>())1378 return true;1379 }1380 1381 // If we're allowed to find type names and we have one, accept it.1382 if (LookupKind != Sema::LookupObjCProtocolName) {1383 // If we have a type declaration, we might accept this result.1384 if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) {1385 // If we found a tag declaration outside of C++, skip it. This1386 // can happy because we look for any name when there is no1387 // bias to protocol or type names.1388 if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus)1389 return false;1390 1391 // Make sure the type is something we would accept as a type1392 // argument.1393 if (CanQualType type = Context.getCanonicalTypeDeclType(typeDecl);1394 type->isDependentType() ||1395 isa<ObjCObjectPointerType, BlockPointerType, ObjCObjectType>(type))1396 return true;1397 1398 return false;1399 }1400 1401 // If we have an Objective-C class type, accept it; there will1402 // be another fix to add the '*'.1403 if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>())1404 return true;1405 1406 return false;1407 }1408 1409 return false;1410 }1411 1412 std::unique_ptr<CorrectionCandidateCallback> clone() override {1413 return std::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this);1414 }1415};1416} // end anonymous namespace1417 1418void SemaObjC::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId,1419 SourceLocation ProtocolLoc,1420 IdentifierInfo *TypeArgId,1421 SourceLocation TypeArgLoc,1422 bool SelectProtocolFirst) {1423 Diag(TypeArgLoc, diag::err_objc_type_args_and_protocols)1424 << SelectProtocolFirst << TypeArgId << ProtocolId1425 << SourceRange(ProtocolLoc);1426}1427 1428void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers(1429 Scope *S, ParsedType baseType, SourceLocation lAngleLoc,1430 ArrayRef<IdentifierInfo *> identifiers,1431 ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc,1432 SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs,1433 SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc,1434 SmallVectorImpl<Decl *> &protocols, SourceLocation &protocolRAngleLoc,1435 bool warnOnIncompleteProtocols) {1436 ASTContext &Context = getASTContext();1437 // Local function that updates the declaration specifiers with1438 // protocol information.1439 unsigned numProtocolsResolved = 0;1440 auto resolvedAsProtocols = [&] {1441 assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols");1442 1443 // Determine whether the base type is a parameterized class, in1444 // which case we want to warn about typos such as1445 // "NSArray<NSObject>" (that should be NSArray<NSObject *>).1446 ObjCInterfaceDecl *baseClass = nullptr;1447 QualType base = SemaRef.GetTypeFromParser(baseType, nullptr);1448 bool allAreTypeNames = false;1449 SourceLocation firstClassNameLoc;1450 if (!base.isNull()) {1451 if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) {1452 baseClass = objcObjectType->getInterface();1453 if (baseClass) {1454 if (auto typeParams = baseClass->getTypeParamList()) {1455 if (typeParams->size() == numProtocolsResolved) {1456 // Note that we should be looking for type names, too.1457 allAreTypeNames = true;1458 }1459 }1460 }1461 }1462 }1463 1464 for (unsigned i = 0, n = protocols.size(); i != n; ++i) {1465 ObjCProtocolDecl *&proto1466 = reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]);1467 // For an objc container, delay protocol reference checking until after we1468 // can set the objc decl as the availability context, otherwise check now.1469 if (!warnOnIncompleteProtocols) {1470 (void)SemaRef.DiagnoseUseOfDecl(proto, identifierLocs[i]);1471 }1472 1473 // If this is a forward protocol declaration, get its definition.1474 if (!proto->isThisDeclarationADefinition() && proto->getDefinition())1475 proto = proto->getDefinition();1476 1477 // If this is a forward declaration and we are supposed to warn in this1478 // case, do it.1479 // FIXME: Recover nicely in the hidden case.1480 ObjCProtocolDecl *forwardDecl = nullptr;1481 if (warnOnIncompleteProtocols &&1482 NestedProtocolHasNoDefinition(proto, forwardDecl)) {1483 Diag(identifierLocs[i], diag::warn_undef_protocolref)1484 << proto->getDeclName();1485 Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined)1486 << forwardDecl;1487 }1488 1489 // If everything this far has been a type name (and we care1490 // about such things), check whether this name refers to a type1491 // as well.1492 if (allAreTypeNames) {1493 if (auto *decl =1494 SemaRef.LookupSingleName(S, identifiers[i], identifierLocs[i],1495 Sema::LookupOrdinaryName)) {1496 if (isa<ObjCInterfaceDecl>(decl)) {1497 if (firstClassNameLoc.isInvalid())1498 firstClassNameLoc = identifierLocs[i];1499 } else if (!isa<TypeDecl>(decl)) {1500 // Not a type.1501 allAreTypeNames = false;1502 }1503 } else {1504 allAreTypeNames = false;1505 }1506 }1507 }1508 1509 // All of the protocols listed also have type names, and at least1510 // one is an Objective-C class name. Check whether all of the1511 // protocol conformances are declared by the base class itself, in1512 // which case we warn.1513 if (allAreTypeNames && firstClassNameLoc.isValid()) {1514 llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols;1515 Context.CollectInheritedProtocols(baseClass, knownProtocols);1516 bool allProtocolsDeclared = true;1517 for (auto *proto : protocols) {1518 if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) {1519 allProtocolsDeclared = false;1520 break;1521 }1522 }1523 1524 if (allProtocolsDeclared) {1525 Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type)1526 << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc)1527 << FixItHint::CreateInsertion(1528 SemaRef.getLocForEndOfToken(firstClassNameLoc), " *");1529 }1530 }1531 1532 protocolLAngleLoc = lAngleLoc;1533 protocolRAngleLoc = rAngleLoc;1534 assert(protocols.size() == identifierLocs.size());1535 };1536 1537 // Attempt to resolve all of the identifiers as protocols.1538 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1539 ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]);1540 protocols.push_back(proto);1541 if (proto)1542 ++numProtocolsResolved;1543 }1544 1545 // If all of the names were protocols, these were protocol qualifiers.1546 if (numProtocolsResolved == identifiers.size())1547 return resolvedAsProtocols();1548 1549 // Attempt to resolve all of the identifiers as type names or1550 // Objective-C class names. The latter is technically ill-formed,1551 // but is probably something like \c NSArray<NSView *> missing the1552 // \c*.1553 typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl;1554 SmallVector<TypeOrClassDecl, 4> typeDecls;1555 unsigned numTypeDeclsResolved = 0;1556 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1557 NamedDecl *decl = SemaRef.LookupSingleName(1558 S, identifiers[i], identifierLocs[i], Sema::LookupOrdinaryName);1559 if (!decl) {1560 typeDecls.push_back(TypeOrClassDecl());1561 continue;1562 }1563 1564 if (auto typeDecl = dyn_cast<TypeDecl>(decl)) {1565 typeDecls.push_back(typeDecl);1566 ++numTypeDeclsResolved;1567 continue;1568 }1569 1570 if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) {1571 typeDecls.push_back(objcClass);1572 ++numTypeDeclsResolved;1573 continue;1574 }1575 1576 typeDecls.push_back(TypeOrClassDecl());1577 }1578 1579 AttributeFactory attrFactory;1580 1581 // Local function that forms a reference to the given type or1582 // Objective-C class declaration.1583 auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc)1584 -> TypeResult {1585 // Form declaration specifiers. They simply refer to the type.1586 DeclSpec DS(attrFactory);1587 const char* prevSpec; // unused1588 unsigned diagID; // unused1589 QualType type;1590 if (auto *actualTypeDecl = dyn_cast<TypeDecl *>(typeDecl))1591 type =1592 Context.getTypeDeclType(ElaboratedTypeKeyword::None,1593 /*Qualifier=*/std::nullopt, actualTypeDecl);1594 else1595 type = Context.getObjCInterfaceType(cast<ObjCInterfaceDecl *>(typeDecl));1596 TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc);1597 ParsedType parsedType = SemaRef.CreateParsedType(type, parsedTSInfo);1598 DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID,1599 parsedType, Context.getPrintingPolicy());1600 // Use the identifier location for the type source range.1601 DS.SetRangeStart(loc);1602 DS.SetRangeEnd(loc);1603 1604 // Form the declarator.1605 Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName);1606 1607 // If we have a typedef of an Objective-C class type that is missing a '*',1608 // add the '*'.1609 if (type->getAs<ObjCInterfaceType>()) {1610 SourceLocation starLoc = SemaRef.getLocForEndOfToken(loc);1611 D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc,1612 SourceLocation(),1613 SourceLocation(),1614 SourceLocation(),1615 SourceLocation(),1616 SourceLocation()),1617 starLoc);1618 1619 // Diagnose the missing '*'.1620 Diag(loc, diag::err_objc_type_arg_missing_star)1621 << type1622 << FixItHint::CreateInsertion(starLoc, " *");1623 }1624 1625 // Convert this to a type.1626 return SemaRef.ActOnTypeName(D);1627 };1628 1629 // Local function that updates the declaration specifiers with1630 // type argument information.1631 auto resolvedAsTypeDecls = [&] {1632 // We did not resolve these as protocols.1633 protocols.clear();1634 1635 assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl");1636 // Map type declarations to type arguments.1637 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1638 // Map type reference to a type.1639 TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]);1640 if (!type.isUsable()) {1641 typeArgs.clear();1642 return;1643 }1644 1645 typeArgs.push_back(type.get());1646 }1647 1648 typeArgsLAngleLoc = lAngleLoc;1649 typeArgsRAngleLoc = rAngleLoc;1650 };1651 1652 // If all of the identifiers can be resolved as type names or1653 // Objective-C class names, we have type arguments.1654 if (numTypeDeclsResolved == identifiers.size())1655 return resolvedAsTypeDecls();1656 1657 // Error recovery: some names weren't found, or we have a mix of1658 // type and protocol names. Go resolve all of the unresolved names1659 // and complain if we can't find a consistent answer.1660 Sema::LookupNameKind lookupKind = Sema::LookupAnyName;1661 for (unsigned i = 0, n = identifiers.size(); i != n; ++i) {1662 // If we already have a protocol or type. Check whether it is the1663 // right thing.1664 if (protocols[i] || typeDecls[i]) {1665 // If we haven't figured out whether we want types or protocols1666 // yet, try to figure it out from this name.1667 if (lookupKind == Sema::LookupAnyName) {1668 // If this name refers to both a protocol and a type (e.g., \c1669 // NSObject), don't conclude anything yet.1670 if (protocols[i] && typeDecls[i])1671 continue;1672 1673 // Otherwise, let this name decide whether we'll be correcting1674 // toward types or protocols.1675 lookupKind = protocols[i] ? Sema::LookupObjCProtocolName1676 : Sema::LookupOrdinaryName;1677 continue;1678 }1679 1680 // If we want protocols and we have a protocol, there's nothing1681 // more to do.1682 if (lookupKind == Sema::LookupObjCProtocolName && protocols[i])1683 continue;1684 1685 // If we want types and we have a type declaration, there's1686 // nothing more to do.1687 if (lookupKind == Sema::LookupOrdinaryName && typeDecls[i])1688 continue;1689 1690 // We have a conflict: some names refer to protocols and others1691 // refer to types.1692 DiagnoseTypeArgsAndProtocols(identifiers[0], identifierLocs[0],1693 identifiers[i], identifierLocs[i],1694 protocols[i] != nullptr);1695 1696 protocols.clear();1697 typeArgs.clear();1698 return;1699 }1700 1701 // Perform typo correction on the name.1702 ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind);1703 TypoCorrection corrected = SemaRef.CorrectTypo(1704 DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S,1705 nullptr, CCC, CorrectTypoKind::ErrorRecovery);1706 if (corrected) {1707 // Did we find a protocol?1708 if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) {1709 SemaRef.diagnoseTypo(corrected,1710 PDiag(diag::err_undeclared_protocol_suggest)1711 << identifiers[i]);1712 lookupKind = Sema::LookupObjCProtocolName;1713 protocols[i] = proto;1714 ++numProtocolsResolved;1715 continue;1716 }1717 1718 // Did we find a type?1719 if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) {1720 SemaRef.diagnoseTypo(corrected,1721 PDiag(diag::err_unknown_typename_suggest)1722 << identifiers[i]);1723 lookupKind = Sema::LookupOrdinaryName;1724 typeDecls[i] = typeDecl;1725 ++numTypeDeclsResolved;1726 continue;1727 }1728 1729 // Did we find an Objective-C class?1730 if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {1731 SemaRef.diagnoseTypo(corrected,1732 PDiag(diag::err_unknown_type_or_class_name_suggest)1733 << identifiers[i] << true);1734 lookupKind = Sema::LookupOrdinaryName;1735 typeDecls[i] = objcClass;1736 ++numTypeDeclsResolved;1737 continue;1738 }1739 }1740 1741 // We couldn't find anything.1742 Diag(identifierLocs[i],1743 (lookupKind == Sema::LookupAnyName ? diag::err_objc_type_arg_missing1744 : lookupKind == Sema::LookupObjCProtocolName1745 ? diag::err_undeclared_protocol1746 : diag::err_unknown_typename))1747 << identifiers[i];1748 protocols.clear();1749 typeArgs.clear();1750 return;1751 }1752 1753 // If all of the names were (corrected to) protocols, these were1754 // protocol qualifiers.1755 if (numProtocolsResolved == identifiers.size())1756 return resolvedAsProtocols();1757 1758 // Otherwise, all of the names were (corrected to) types.1759 assert(numTypeDeclsResolved == identifiers.size() && "Not all types?");1760 return resolvedAsTypeDecls();1761}1762 1763/// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of1764/// a class method in its extension.1765///1766void SemaObjC::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT,1767 ObjCInterfaceDecl *ID) {1768 if (!ID)1769 return; // Possibly due to previous error1770 1771 llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap;1772 for (auto *MD : ID->methods())1773 MethodMap[MD->getSelector()] = MD;1774 1775 if (MethodMap.empty())1776 return;1777 for (const auto *Method : CAT->methods()) {1778 const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()];1779 if (PrevMethod &&1780 (PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) &&1781 !MatchTwoMethodDeclarations(Method, PrevMethod)) {1782 Diag(Method->getLocation(), diag::err_duplicate_method_decl)1783 << Method->getDeclName();1784 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);1785 }1786 }1787}1788 1789/// ActOnForwardProtocolDeclaration - Handle \@protocol foo;1790SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardProtocolDeclaration(1791 SourceLocation AtProtocolLoc, ArrayRef<IdentifierLoc> IdentList,1792 const ParsedAttributesView &attrList) {1793 ASTContext &Context = getASTContext();1794 SmallVector<Decl *, 8> DeclsInGroup;1795 for (const IdentifierLoc &IdentPair : IdentList) {1796 IdentifierInfo *Ident = IdentPair.getIdentifierInfo();1797 ObjCProtocolDecl *PrevDecl = LookupProtocol(1798 Ident, IdentPair.getLoc(), SemaRef.forRedeclarationInCurContext());1799 ObjCProtocolDecl *PDecl =1800 ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident,1801 IdentPair.getLoc(), AtProtocolLoc, PrevDecl);1802 1803 SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope);1804 CheckObjCDeclScope(PDecl);1805 1806 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, attrList);1807 SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl);1808 1809 if (PrevDecl)1810 SemaRef.mergeDeclAttributes(PDecl, PrevDecl);1811 1812 DeclsInGroup.push_back(PDecl);1813 }1814 1815 return SemaRef.BuildDeclaratorGroup(DeclsInGroup);1816}1817 1818ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface(1819 SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName,1820 SourceLocation ClassLoc, ObjCTypeParamList *typeParamList,1821 const IdentifierInfo *CategoryName, SourceLocation CategoryLoc,1822 Decl *const *ProtoRefs, unsigned NumProtoRefs,1823 const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc,1824 const ParsedAttributesView &AttrList) {1825 ASTContext &Context = getASTContext();1826 ObjCCategoryDecl *CDecl;1827 ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);1828 1829 /// Check that class of this category is already completely declared.1830 1831 if (!IDecl ||1832 SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),1833 diag::err_category_forward_interface,1834 CategoryName == nullptr)) {1835 // Create an invalid ObjCCategoryDecl to serve as context for1836 // the enclosing method declarations. We mark the decl invalid1837 // to make it clear that this isn't a valid AST.1838 CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext,1839 AtInterfaceLoc, ClassLoc, CategoryLoc,1840 CategoryName, IDecl, typeParamList);1841 CDecl->setInvalidDecl();1842 SemaRef.CurContext->addDecl(CDecl);1843 1844 if (!IDecl)1845 Diag(ClassLoc, diag::err_undef_interface) << ClassName;1846 ActOnObjCContainerStartDefinition(CDecl);1847 return CDecl;1848 }1849 1850 if (!CategoryName && IDecl->getImplementation()) {1851 Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName;1852 Diag(IDecl->getImplementation()->getLocation(),1853 diag::note_implementation_declared);1854 }1855 1856 if (CategoryName) {1857 /// Check for duplicate interface declaration for this category1858 if (ObjCCategoryDecl *Previous1859 = IDecl->FindCategoryDeclaration(CategoryName)) {1860 // Class extensions can be declared multiple times, categories cannot.1861 Diag(CategoryLoc, diag::warn_dup_category_def)1862 << ClassName << CategoryName;1863 Diag(Previous->getLocation(), diag::note_previous_definition);1864 }1865 }1866 1867 // If we have a type parameter list, check it.1868 if (typeParamList) {1869 if (auto prevTypeParamList = IDecl->getTypeParamList()) {1870 if (checkTypeParamListConsistency(1871 SemaRef, prevTypeParamList, typeParamList,1872 CategoryName ? TypeParamListContext::Category1873 : TypeParamListContext::Extension))1874 typeParamList = nullptr;1875 } else {1876 Diag(typeParamList->getLAngleLoc(),1877 diag::err_objc_parameterized_category_nonclass)1878 << (CategoryName != nullptr)1879 << ClassName1880 << typeParamList->getSourceRange();1881 1882 typeParamList = nullptr;1883 }1884 }1885 1886 CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc,1887 ClassLoc, CategoryLoc, CategoryName, IDecl,1888 typeParamList);1889 // FIXME: PushOnScopeChains?1890 SemaRef.CurContext->addDecl(CDecl);1891 1892 // Process the attributes before looking at protocols to ensure that the1893 // availability attribute is attached to the category to provide availability1894 // checking for protocol uses.1895 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList);1896 SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);1897 1898 if (NumProtoRefs) {1899 diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs,1900 NumProtoRefs, ProtoLocs);1901 CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs,1902 ProtoLocs, Context);1903 // Protocols in the class extension belong to the class.1904 if (CDecl->IsClassExtension())1905 IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs,1906 NumProtoRefs, Context);1907 }1908 1909 CheckObjCDeclScope(CDecl);1910 ActOnObjCContainerStartDefinition(CDecl);1911 return CDecl;1912}1913 1914/// ActOnStartCategoryImplementation - Perform semantic checks on the1915/// category implementation declaration and build an ObjCCategoryImplDecl1916/// object.1917ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation(1918 SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName,1919 SourceLocation ClassLoc, const IdentifierInfo *CatName,1920 SourceLocation CatLoc, const ParsedAttributesView &Attrs) {1921 ASTContext &Context = getASTContext();1922 ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true);1923 ObjCCategoryDecl *CatIDecl = nullptr;1924 if (IDecl && IDecl->hasDefinition()) {1925 CatIDecl = IDecl->FindCategoryDeclaration(CatName);1926 if (!CatIDecl) {1927 // Category @implementation with no corresponding @interface.1928 // Create and install one.1929 CatIDecl =1930 ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtCatImplLoc,1931 ClassLoc, CatLoc, CatName, IDecl,1932 /*typeParamList=*/nullptr);1933 CatIDecl->setImplicit();1934 }1935 }1936 1937 ObjCCategoryImplDecl *CDecl =1938 ObjCCategoryImplDecl::Create(Context, SemaRef.CurContext, CatName, IDecl,1939 ClassLoc, AtCatImplLoc, CatLoc);1940 /// Check that class of this category is already completely declared.1941 if (!IDecl) {1942 Diag(ClassLoc, diag::err_undef_interface) << ClassName;1943 CDecl->setInvalidDecl();1944 } else if (SemaRef.RequireCompleteType(ClassLoc,1945 Context.getObjCInterfaceType(IDecl),1946 diag::err_undef_interface)) {1947 CDecl->setInvalidDecl();1948 }1949 1950 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs);1951 SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl);1952 1953 // FIXME: PushOnScopeChains?1954 SemaRef.CurContext->addDecl(CDecl);1955 1956 // If the interface has the objc_runtime_visible attribute, we1957 // cannot implement a category for it.1958 if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) {1959 Diag(ClassLoc, diag::err_objc_runtime_visible_category)1960 << IDecl->getDeclName();1961 }1962 1963 /// Check that CatName, category name, is not used in another implementation.1964 if (CatIDecl) {1965 if (CatIDecl->getImplementation()) {1966 Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName1967 << CatName;1968 Diag(CatIDecl->getImplementation()->getLocation(),1969 diag::note_previous_definition);1970 CDecl->setInvalidDecl();1971 } else {1972 CatIDecl->setImplementation(CDecl);1973 // Warn on implementating category of deprecated class under1974 // -Wdeprecated-implementations flag.1975 DiagnoseObjCImplementedDeprecations(SemaRef, CatIDecl,1976 CDecl->getLocation());1977 }1978 }1979 1980 CheckObjCDeclScope(CDecl);1981 ActOnObjCContainerStartDefinition(CDecl);1982 return CDecl;1983}1984 1985ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation(1986 SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName,1987 SourceLocation ClassLoc, const IdentifierInfo *SuperClassname,1988 SourceLocation SuperClassLoc, const ParsedAttributesView &Attrs) {1989 ASTContext &Context = getASTContext();1990 ObjCInterfaceDecl *IDecl = nullptr;1991 // Check for another declaration kind with the same name.1992 NamedDecl *PrevDecl = SemaRef.LookupSingleName(1993 SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName,1994 SemaRef.forRedeclarationInCurContext());1995 if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {1996 Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;1997 Diag(PrevDecl->getLocation(), diag::note_previous_definition);1998 } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) {1999 // FIXME: This will produce an error if the definition of the interface has2000 // been imported from a module but is not visible.2001 SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl),2002 diag::warn_undef_interface);2003 } else {2004 // We did not find anything with the name ClassName; try to correct for2005 // typos in the class name.2006 ObjCInterfaceValidatorCCC CCC{};2007 TypoCorrection Corrected = SemaRef.CorrectTypo(2008 DeclarationNameInfo(ClassName, ClassLoc), Sema::LookupOrdinaryName,2009 SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::NonError);2010 if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) {2011 // Suggest the (potentially) correct interface name. Don't provide a2012 // code-modification hint or use the typo name for recovery, because2013 // this is just a warning. The program may actually be correct.2014 SemaRef.diagnoseTypo(2015 Corrected, PDiag(diag::warn_undef_interface_suggest) << ClassName,2016 /*ErrorRecovery*/ false);2017 } else {2018 Diag(ClassLoc, diag::warn_undef_interface) << ClassName;2019 }2020 }2021 2022 // Check that super class name is valid class name2023 ObjCInterfaceDecl *SDecl = nullptr;2024 if (SuperClassname) {2025 // Check if a different kind of symbol declared in this scope.2026 PrevDecl =2027 SemaRef.LookupSingleName(SemaRef.TUScope, SuperClassname, SuperClassLoc,2028 Sema::LookupOrdinaryName);2029 if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {2030 Diag(SuperClassLoc, diag::err_redefinition_different_kind)2031 << SuperClassname;2032 Diag(PrevDecl->getLocation(), diag::note_previous_definition);2033 } else {2034 SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);2035 if (SDecl && !SDecl->hasDefinition())2036 SDecl = nullptr;2037 if (!SDecl)2038 Diag(SuperClassLoc, diag::err_undef_superclass)2039 << SuperClassname << ClassName;2040 else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) {2041 // This implementation and its interface do not have the same2042 // super class.2043 Diag(SuperClassLoc, diag::err_conflicting_super_class)2044 << SDecl->getDeclName();2045 Diag(SDecl->getLocation(), diag::note_previous_definition);2046 }2047 }2048 }2049 2050 if (!IDecl) {2051 // Legacy case of @implementation with no corresponding @interface.2052 // Build, chain & install the interface decl into the identifier.2053 2054 // FIXME: Do we support attributes on the @implementation? If so we should2055 // copy them over.2056 IDecl =2057 ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtClassImplLoc,2058 ClassName, /*typeParamList=*/nullptr,2059 /*PrevDecl=*/nullptr, ClassLoc, true);2060 SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl);2061 IDecl->startDefinition();2062 if (SDecl) {2063 IDecl->setSuperClass(Context.getTrivialTypeSourceInfo(2064 Context.getObjCInterfaceType(SDecl),2065 SuperClassLoc));2066 IDecl->setEndOfDefinitionLoc(SuperClassLoc);2067 } else {2068 IDecl->setEndOfDefinitionLoc(ClassLoc);2069 }2070 2071 SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);2072 } else {2073 // Mark the interface as being completed, even if it was just as2074 // @class ....;2075 // declaration; the user cannot reopen it.2076 if (!IDecl->hasDefinition())2077 IDecl->startDefinition();2078 }2079 2080 ObjCImplementationDecl *IMPDecl =2081 ObjCImplementationDecl::Create(Context, SemaRef.CurContext, IDecl, SDecl,2082 ClassLoc, AtClassImplLoc, SuperClassLoc);2083 2084 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs);2085 SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl);2086 2087 if (CheckObjCDeclScope(IMPDecl)) {2088 ActOnObjCContainerStartDefinition(IMPDecl);2089 return IMPDecl;2090 }2091 2092 // Check that there is no duplicate implementation of this class.2093 if (IDecl->getImplementation()) {2094 // FIXME: Don't leak everything!2095 Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName;2096 Diag(IDecl->getImplementation()->getLocation(),2097 diag::note_previous_definition);2098 IMPDecl->setInvalidDecl();2099 } else { // add it to the list.2100 IDecl->setImplementation(IMPDecl);2101 SemaRef.PushOnScopeChains(IMPDecl, SemaRef.TUScope);2102 // Warn on implementating deprecated class under2103 // -Wdeprecated-implementations flag.2104 DiagnoseObjCImplementedDeprecations(SemaRef, IDecl, IMPDecl->getLocation());2105 }2106 2107 // If the superclass has the objc_runtime_visible attribute, we2108 // cannot implement a subclass of it.2109 if (IDecl->getSuperClass() &&2110 IDecl->getSuperClass()->hasAttr<ObjCRuntimeVisibleAttr>()) {2111 Diag(ClassLoc, diag::err_objc_runtime_visible_subclass)2112 << IDecl->getDeclName()2113 << IDecl->getSuperClass()->getDeclName();2114 }2115 2116 ActOnObjCContainerStartDefinition(IMPDecl);2117 return IMPDecl;2118}2119 2120SemaObjC::DeclGroupPtrTy2121SemaObjC::ActOnFinishObjCImplementation(Decl *ObjCImpDecl,2122 ArrayRef<Decl *> Decls) {2123 SmallVector<Decl *, 64> DeclsInGroup;2124 DeclsInGroup.reserve(Decls.size() + 1);2125 2126 for (unsigned i = 0, e = Decls.size(); i != e; ++i) {2127 Decl *Dcl = Decls[i];2128 if (!Dcl)2129 continue;2130 if (Dcl->getDeclContext()->isFileContext())2131 Dcl->setTopLevelDeclInObjCContainer();2132 DeclsInGroup.push_back(Dcl);2133 }2134 2135 DeclsInGroup.push_back(ObjCImpDecl);2136 2137 // Reset the cached layout if there are any ivars added to2138 // the implementation.2139 if (auto *ImplD = dyn_cast<ObjCImplementationDecl>(ObjCImpDecl))2140 if (!ImplD->ivar_empty())2141 getASTContext().ResetObjCLayout(ImplD->getClassInterface());2142 2143 return SemaRef.BuildDeclaratorGroup(DeclsInGroup);2144}2145 2146void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl,2147 ObjCIvarDecl **ivars, unsigned numIvars,2148 SourceLocation RBrace) {2149 assert(ImpDecl && "missing implementation decl");2150 ASTContext &Context = getASTContext();2151 ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface();2152 if (!IDecl)2153 return;2154 /// Check case of non-existing \@interface decl.2155 /// (legacy objective-c \@implementation decl without an \@interface decl).2156 /// Add implementations's ivar to the synthesize class's ivar list.2157 if (IDecl->isImplicitInterfaceDecl()) {2158 IDecl->setEndOfDefinitionLoc(RBrace);2159 // Add ivar's to class's DeclContext.2160 for (unsigned i = 0, e = numIvars; i != e; ++i) {2161 ivars[i]->setLexicalDeclContext(ImpDecl);2162 // In a 'fragile' runtime the ivar was added to the implicit2163 // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is2164 // only in the ObjCImplementationDecl. In the non-fragile case the ivar2165 // therefore also needs to be propagated to the ObjCInterfaceDecl.2166 if (!getLangOpts().ObjCRuntime.isFragile())2167 IDecl->makeDeclVisibleInContext(ivars[i]);2168 ImpDecl->addDecl(ivars[i]);2169 }2170 2171 return;2172 }2173 // If implementation has empty ivar list, just return.2174 if (numIvars == 0)2175 return;2176 2177 assert(ivars && "missing @implementation ivars");2178 if (getLangOpts().ObjCRuntime.isNonFragile()) {2179 if (ImpDecl->getSuperClass())2180 Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use);2181 for (unsigned i = 0; i < numIvars; i++) {2182 ObjCIvarDecl* ImplIvar = ivars[i];2183 if (const ObjCIvarDecl *ClsIvar =2184 IDecl->getIvarDecl(ImplIvar->getIdentifier())) {2185 Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);2186 Diag(ClsIvar->getLocation(), diag::note_previous_definition);2187 continue;2188 }2189 // Check class extensions (unnamed categories) for duplicate ivars.2190 for (const auto *CDecl : IDecl->visible_extensions()) {2191 if (const ObjCIvarDecl *ClsExtIvar =2192 CDecl->getIvarDecl(ImplIvar->getIdentifier())) {2193 Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration);2194 Diag(ClsExtIvar->getLocation(), diag::note_previous_definition);2195 continue;2196 }2197 }2198 // Instance ivar to Implementation's DeclContext.2199 ImplIvar->setLexicalDeclContext(ImpDecl);2200 IDecl->makeDeclVisibleInContext(ImplIvar);2201 ImpDecl->addDecl(ImplIvar);2202 }2203 return;2204 }2205 // Check interface's Ivar list against those in the implementation.2206 // names and types must match.2207 //2208 unsigned j = 0;2209 ObjCInterfaceDecl::ivar_iterator2210 IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end();2211 for (; numIvars > 0 && IVI != IVE; ++IVI) {2212 ObjCIvarDecl* ImplIvar = ivars[j++];2213 ObjCIvarDecl* ClsIvar = *IVI;2214 assert (ImplIvar && "missing implementation ivar");2215 assert (ClsIvar && "missing class ivar");2216 2217 // First, make sure the types match.2218 if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) {2219 Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type)2220 << ImplIvar->getIdentifier()2221 << ImplIvar->getType() << ClsIvar->getType();2222 Diag(ClsIvar->getLocation(), diag::note_previous_definition);2223 } else if (ImplIvar->isBitField() && ClsIvar->isBitField() &&2224 ImplIvar->getBitWidthValue() != ClsIvar->getBitWidthValue()) {2225 Diag(ImplIvar->getBitWidth()->getBeginLoc(),2226 diag::err_conflicting_ivar_bitwidth)2227 << ImplIvar->getIdentifier();2228 Diag(ClsIvar->getBitWidth()->getBeginLoc(),2229 diag::note_previous_definition);2230 }2231 // Make sure the names are identical.2232 if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) {2233 Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name)2234 << ImplIvar->getIdentifier() << ClsIvar->getIdentifier();2235 Diag(ClsIvar->getLocation(), diag::note_previous_definition);2236 }2237 --numIvars;2238 }2239 2240 if (numIvars > 0)2241 Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count);2242 else if (IVI != IVE)2243 Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count);2244}2245 2246static bool shouldWarnUndefinedMethod(const ObjCMethodDecl *M) {2247 // No point warning no definition of method which is 'unavailable'.2248 return M->getAvailability() != AR_Unavailable;2249}2250 2251static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl,2252 ObjCMethodDecl *method, bool &IncompleteImpl,2253 unsigned DiagID,2254 NamedDecl *NeededFor = nullptr) {2255 if (!shouldWarnUndefinedMethod(method))2256 return;2257 2258 // FIXME: For now ignore 'IncompleteImpl'.2259 // Previously we grouped all unimplemented methods under a single2260 // warning, but some users strongly voiced that they would prefer2261 // separate warnings. We will give that approach a try, as that2262 // matches what we do with protocols.2263 {2264 const SemaBase::SemaDiagnosticBuilder &B =2265 S.Diag(Impl->getLocation(), DiagID);2266 B << method;2267 if (NeededFor)2268 B << NeededFor;2269 2270 // Add an empty definition at the end of the @implementation.2271 std::string FixItStr;2272 llvm::raw_string_ostream Out(FixItStr);2273 method->print(Out, Impl->getASTContext().getPrintingPolicy());2274 Out << " {\n}\n\n";2275 2276 SourceLocation Loc = Impl->getAtEndRange().getBegin();2277 B << FixItHint::CreateInsertion(Loc, FixItStr);2278 }2279 2280 // Issue a note to the original declaration.2281 SourceLocation MethodLoc = method->getBeginLoc();2282 if (MethodLoc.isValid())2283 S.Diag(MethodLoc, diag::note_method_declared_at) << method;2284}2285 2286/// Determines if type B can be substituted for type A. Returns true if we can2287/// guarantee that anything that the user will do to an object of type A can2288/// also be done to an object of type B. This is trivially true if the two2289/// types are the same, or if B is a subclass of A. It becomes more complex2290/// in cases where protocols are involved.2291///2292/// Object types in Objective-C describe the minimum requirements for an2293/// object, rather than providing a complete description of a type. For2294/// example, if A is a subclass of B, then B* may refer to an instance of A.2295/// The principle of substitutability means that we may use an instance of A2296/// anywhere that we may use an instance of B - it will implement all of the2297/// ivars of B and all of the methods of B.2298///2299/// This substitutability is important when type checking methods, because2300/// the implementation may have stricter type definitions than the interface.2301/// The interface specifies minimum requirements, but the implementation may2302/// have more accurate ones. For example, a method may privately accept2303/// instances of B, but only publish that it accepts instances of A. Any2304/// object passed to it will be type checked against B, and so will implicitly2305/// by a valid A*. Similarly, a method may return a subclass of the class that2306/// it is declared as returning.2307///2308/// This is most important when considering subclassing. A method in a2309/// subclass must accept any object as an argument that its superclass's2310/// implementation accepts. It may, however, accept a more general type2311/// without breaking substitutability (i.e. you can still use the subclass2312/// anywhere that you can use the superclass, but not vice versa). The2313/// converse requirement applies to return types: the return type for a2314/// subclass method must be a valid object of the kind that the superclass2315/// advertises, but it may be specified more accurately. This avoids the need2316/// for explicit down-casting by callers.2317///2318/// Note: This is a stricter requirement than for assignment.2319static bool isObjCTypeSubstitutable(ASTContext &Context,2320 const ObjCObjectPointerType *A,2321 const ObjCObjectPointerType *B,2322 bool rejectId) {2323 // Reject a protocol-unqualified id.2324 if (rejectId && B->isObjCIdType()) return false;2325 2326 // If B is a qualified id, then A must also be a qualified id and it must2327 // implement all of the protocols in B. It may not be a qualified class.2328 // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a2329 // stricter definition so it is not substitutable for id<A>.2330 if (B->isObjCQualifiedIdType()) {2331 return A->isObjCQualifiedIdType() &&2332 Context.ObjCQualifiedIdTypesAreCompatible(A, B, false);2333 }2334 2335 /*2336 // id is a special type that bypasses type checking completely. We want a2337 // warning when it is used in one place but not another.2338 if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false;2339 2340 2341 // If B is a qualified id, then A must also be a qualified id (which it isn't2342 // if we've got this far)2343 if (B->isObjCQualifiedIdType()) return false;2344 */2345 2346 // Now we know that A and B are (potentially-qualified) class types. The2347 // normal rules for assignment apply.2348 return Context.canAssignObjCInterfaces(A, B);2349}2350 2351static SourceRange getTypeRange(TypeSourceInfo *TSI) {2352 return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange());2353}2354 2355/// Determine whether two set of Objective-C declaration qualifiers conflict.2356static bool objcModifiersConflict(Decl::ObjCDeclQualifier x,2357 Decl::ObjCDeclQualifier y) {2358 return (x & ~Decl::OBJC_TQ_CSNullability) !=2359 (y & ~Decl::OBJC_TQ_CSNullability);2360}2361 2362static bool CheckMethodOverrideReturn(Sema &S,2363 ObjCMethodDecl *MethodImpl,2364 ObjCMethodDecl *MethodDecl,2365 bool IsProtocolMethodDecl,2366 bool IsOverridingMode,2367 bool Warn) {2368 if (IsProtocolMethodDecl &&2369 objcModifiersConflict(MethodDecl->getObjCDeclQualifier(),2370 MethodImpl->getObjCDeclQualifier())) {2371 if (Warn) {2372 S.Diag(MethodImpl->getLocation(),2373 (IsOverridingMode2374 ? diag::warn_conflicting_overriding_ret_type_modifiers2375 : diag::warn_conflicting_ret_type_modifiers))2376 << MethodImpl->getDeclName()2377 << MethodImpl->getReturnTypeSourceRange();2378 S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration)2379 << MethodDecl->getReturnTypeSourceRange();2380 }2381 else2382 return false;2383 }2384 if (Warn && IsOverridingMode &&2385 !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&2386 !S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(),2387 MethodDecl->getReturnType(),2388 false)) {2389 auto nullabilityMethodImpl = *MethodImpl->getReturnType()->getNullability();2390 auto nullabilityMethodDecl = *MethodDecl->getReturnType()->getNullability();2391 S.Diag(MethodImpl->getLocation(),2392 diag::warn_conflicting_nullability_attr_overriding_ret_types)2393 << DiagNullabilityKind(nullabilityMethodImpl,2394 ((MethodImpl->getObjCDeclQualifier() &2395 Decl::OBJC_TQ_CSNullability) != 0))2396 << DiagNullabilityKind(nullabilityMethodDecl,2397 ((MethodDecl->getObjCDeclQualifier() &2398 Decl::OBJC_TQ_CSNullability) != 0));2399 S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration);2400 }2401 2402 if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(),2403 MethodDecl->getReturnType()))2404 return true;2405 if (!Warn)2406 return false;2407 2408 unsigned DiagID =2409 IsOverridingMode ? diag::warn_conflicting_overriding_ret_types2410 : diag::warn_conflicting_ret_types;2411 2412 // Mismatches between ObjC pointers go into a different warning2413 // category, and sometimes they're even completely explicitly allowed.2414 if (const ObjCObjectPointerType *ImplPtrTy =2415 MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) {2416 if (const ObjCObjectPointerType *IfacePtrTy =2417 MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) {2418 // Allow non-matching return types as long as they don't violate2419 // the principle of substitutability. Specifically, we permit2420 // return types that are subclasses of the declared return type,2421 // or that are more-qualified versions of the declared type.2422 if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false))2423 return false;2424 2425 DiagID =2426 IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types2427 : diag::warn_non_covariant_ret_types;2428 }2429 }2430 2431 S.Diag(MethodImpl->getLocation(), DiagID)2432 << MethodImpl->getDeclName() << MethodDecl->getReturnType()2433 << MethodImpl->getReturnType()2434 << MethodImpl->getReturnTypeSourceRange();2435 S.Diag(MethodDecl->getLocation(), IsOverridingMode2436 ? diag::note_previous_declaration2437 : diag::note_previous_definition)2438 << MethodDecl->getReturnTypeSourceRange();2439 return false;2440}2441 2442static bool CheckMethodOverrideParam(Sema &S,2443 ObjCMethodDecl *MethodImpl,2444 ObjCMethodDecl *MethodDecl,2445 ParmVarDecl *ImplVar,2446 ParmVarDecl *IfaceVar,2447 bool IsProtocolMethodDecl,2448 bool IsOverridingMode,2449 bool Warn) {2450 if (IsProtocolMethodDecl &&2451 objcModifiersConflict(ImplVar->getObjCDeclQualifier(),2452 IfaceVar->getObjCDeclQualifier())) {2453 if (Warn) {2454 if (IsOverridingMode)2455 S.Diag(ImplVar->getLocation(),2456 diag::warn_conflicting_overriding_param_modifiers)2457 << getTypeRange(ImplVar->getTypeSourceInfo())2458 << MethodImpl->getDeclName();2459 else S.Diag(ImplVar->getLocation(),2460 diag::warn_conflicting_param_modifiers)2461 << getTypeRange(ImplVar->getTypeSourceInfo())2462 << MethodImpl->getDeclName();2463 S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration)2464 << getTypeRange(IfaceVar->getTypeSourceInfo());2465 }2466 else2467 return false;2468 }2469 2470 QualType ImplTy = ImplVar->getType();2471 QualType IfaceTy = IfaceVar->getType();2472 if (Warn && IsOverridingMode &&2473 !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) &&2474 !S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) {2475 S.Diag(ImplVar->getLocation(),2476 diag::warn_conflicting_nullability_attr_overriding_param_types)2477 << DiagNullabilityKind(*ImplTy->getNullability(),2478 ((ImplVar->getObjCDeclQualifier() &2479 Decl::OBJC_TQ_CSNullability) != 0))2480 << DiagNullabilityKind(*IfaceTy->getNullability(),2481 ((IfaceVar->getObjCDeclQualifier() &2482 Decl::OBJC_TQ_CSNullability) != 0));2483 S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration);2484 }2485 if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy))2486 return true;2487 2488 if (!Warn)2489 return false;2490 unsigned DiagID =2491 IsOverridingMode ? diag::warn_conflicting_overriding_param_types2492 : diag::warn_conflicting_param_types;2493 2494 // Mismatches between ObjC pointers go into a different warning2495 // category, and sometimes they're even completely explicitly allowed..2496 if (const ObjCObjectPointerType *ImplPtrTy =2497 ImplTy->getAs<ObjCObjectPointerType>()) {2498 if (const ObjCObjectPointerType *IfacePtrTy =2499 IfaceTy->getAs<ObjCObjectPointerType>()) {2500 // Allow non-matching argument types as long as they don't2501 // violate the principle of substitutability. Specifically, the2502 // implementation must accept any objects that the superclass2503 // accepts, however it may also accept others.2504 if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true))2505 return false;2506 2507 DiagID =2508 IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types2509 : diag::warn_non_contravariant_param_types;2510 }2511 }2512 2513 S.Diag(ImplVar->getLocation(), DiagID)2514 << getTypeRange(ImplVar->getTypeSourceInfo())2515 << MethodImpl->getDeclName() << IfaceTy << ImplTy;2516 S.Diag(IfaceVar->getLocation(),2517 (IsOverridingMode ? diag::note_previous_declaration2518 : diag::note_previous_definition))2519 << getTypeRange(IfaceVar->getTypeSourceInfo());2520 return false;2521}2522 2523/// In ARC, check whether the conventional meanings of the two methods2524/// match. If they don't, it's a hard error.2525static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl,2526 ObjCMethodDecl *decl) {2527 ObjCMethodFamily implFamily = impl->getMethodFamily();2528 ObjCMethodFamily declFamily = decl->getMethodFamily();2529 if (implFamily == declFamily) return false;2530 2531 // Since conventions are sorted by selector, the only possibility is2532 // that the types differ enough to cause one selector or the other2533 // to fall out of the family.2534 assert(implFamily == OMF_None || declFamily == OMF_None);2535 2536 // No further diagnostics required on invalid declarations.2537 if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true;2538 2539 const ObjCMethodDecl *unmatched = impl;2540 ObjCMethodFamily family = declFamily;2541 unsigned errorID = diag::err_arc_lost_method_convention;2542 unsigned noteID = diag::note_arc_lost_method_convention;2543 if (declFamily == OMF_None) {2544 unmatched = decl;2545 family = implFamily;2546 errorID = diag::err_arc_gained_method_convention;2547 noteID = diag::note_arc_gained_method_convention;2548 }2549 2550 // Indexes into a %select clause in the diagnostic.2551 enum FamilySelector {2552 F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new2553 };2554 FamilySelector familySelector = FamilySelector();2555 2556 switch (family) {2557 case OMF_None: llvm_unreachable("logic error, no method convention");2558 case OMF_retain:2559 case OMF_release:2560 case OMF_autorelease:2561 case OMF_dealloc:2562 case OMF_finalize:2563 case OMF_retainCount:2564 case OMF_self:2565 case OMF_initialize:2566 case OMF_performSelector:2567 // Mismatches for these methods don't change ownership2568 // conventions, so we don't care.2569 return false;2570 2571 case OMF_init: familySelector = F_init; break;2572 case OMF_alloc: familySelector = F_alloc; break;2573 case OMF_copy: familySelector = F_copy; break;2574 case OMF_mutableCopy: familySelector = F_mutableCopy; break;2575 case OMF_new: familySelector = F_new; break;2576 }2577 2578 enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn };2579 ReasonSelector reasonSelector;2580 2581 // The only reason these methods don't fall within their families is2582 // due to unusual result types.2583 if (unmatched->getReturnType()->isObjCObjectPointerType()) {2584 reasonSelector = R_UnrelatedReturn;2585 } else {2586 reasonSelector = R_NonObjectReturn;2587 }2588 2589 S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector);2590 S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector);2591 2592 return true;2593}2594 2595void SemaObjC::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl,2596 ObjCMethodDecl *MethodDecl,2597 bool IsProtocolMethodDecl) {2598 if (getLangOpts().ObjCAutoRefCount &&2599 checkMethodFamilyMismatch(SemaRef, ImpMethodDecl, MethodDecl))2600 return;2601 2602 CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,2603 IsProtocolMethodDecl, false, true);2604 2605 for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),2606 IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),2607 EF = MethodDecl->param_end();2608 IM != EM && IF != EF; ++IM, ++IF) {2609 CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, *IF,2610 IsProtocolMethodDecl, false, true);2611 }2612 2613 if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) {2614 Diag(ImpMethodDecl->getLocation(),2615 diag::warn_conflicting_variadic);2616 Diag(MethodDecl->getLocation(), diag::note_previous_declaration);2617 }2618}2619 2620void SemaObjC::CheckConflictingOverridingMethod(ObjCMethodDecl *Method,2621 ObjCMethodDecl *Overridden,2622 bool IsProtocolMethodDecl) {2623 2624 CheckMethodOverrideReturn(SemaRef, Method, Overridden, IsProtocolMethodDecl,2625 true, true);2626 2627 for (ObjCMethodDecl::param_iterator IM = Method->param_begin(),2628 IF = Overridden->param_begin(), EM = Method->param_end(),2629 EF = Overridden->param_end();2630 IM != EM && IF != EF; ++IM, ++IF) {2631 CheckMethodOverrideParam(SemaRef, Method, Overridden, *IM, *IF,2632 IsProtocolMethodDecl, true, true);2633 }2634 2635 if (Method->isVariadic() != Overridden->isVariadic()) {2636 Diag(Method->getLocation(),2637 diag::warn_conflicting_overriding_variadic);2638 Diag(Overridden->getLocation(), diag::note_previous_declaration);2639 }2640}2641 2642/// WarnExactTypedMethods - This routine issues a warning if method2643/// implementation declaration matches exactly that of its declaration.2644void SemaObjC::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl,2645 ObjCMethodDecl *MethodDecl,2646 bool IsProtocolMethodDecl) {2647 ASTContext &Context = getASTContext();2648 // don't issue warning when protocol method is optional because primary2649 // class is not required to implement it and it is safe for protocol2650 // to implement it.2651 if (MethodDecl->getImplementationControl() ==2652 ObjCImplementationControl::Optional)2653 return;2654 // don't issue warning when primary class's method is2655 // deprecated/unavailable.2656 if (MethodDecl->hasAttr<UnavailableAttr>() ||2657 MethodDecl->hasAttr<DeprecatedAttr>())2658 return;2659 2660 bool match = CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl,2661 IsProtocolMethodDecl, false, false);2662 if (match)2663 for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(),2664 IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(),2665 EF = MethodDecl->param_end();2666 IM != EM && IF != EF; ++IM, ++IF) {2667 match = CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM,2668 *IF, IsProtocolMethodDecl, false, false);2669 if (!match)2670 break;2671 }2672 if (match)2673 match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic());2674 if (match)2675 match = !(MethodDecl->isClassMethod() &&2676 MethodDecl->getSelector() == GetNullarySelector("load", Context));2677 2678 if (match) {2679 Diag(ImpMethodDecl->getLocation(),2680 diag::warn_category_method_impl_match);2681 Diag(MethodDecl->getLocation(), diag::note_method_declared_at)2682 << MethodDecl->getDeclName();2683 }2684}2685 2686/// FIXME: Type hierarchies in Objective-C can be deep. We could most likely2687/// improve the efficiency of selector lookups and type checking by associating2688/// with each protocol / interface / category the flattened instance tables. If2689/// we used an immutable set to keep the table then it wouldn't add significant2690/// memory cost and it would be handy for lookups.2691 2692typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet;2693typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet;2694 2695static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl,2696 ProtocolNameSet &PNS) {2697 if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())2698 PNS.insert(PDecl->getIdentifier());2699 for (const auto *PI : PDecl->protocols())2700 findProtocolsWithExplicitImpls(PI, PNS);2701}2702 2703/// Recursively populates a set with all conformed protocols in a class2704/// hierarchy that have the 'objc_protocol_requires_explicit_implementation'2705/// attribute.2706static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super,2707 ProtocolNameSet &PNS) {2708 if (!Super)2709 return;2710 2711 for (const auto *I : Super->all_referenced_protocols())2712 findProtocolsWithExplicitImpls(I, PNS);2713 2714 findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS);2715}2716 2717/// CheckProtocolMethodDefs - This routine checks unimplemented methods2718/// Declared in protocol, and those referenced by it.2719static void CheckProtocolMethodDefs(2720 Sema &S, ObjCImplDecl *Impl, ObjCProtocolDecl *PDecl, bool &IncompleteImpl,2721 const SemaObjC::SelectorSet &InsMap, const SemaObjC::SelectorSet &ClsMap,2722 ObjCContainerDecl *CDecl, LazyProtocolNameSet &ProtocolsExplictImpl) {2723 ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl);2724 ObjCInterfaceDecl *IDecl = C ? C->getClassInterface()2725 : dyn_cast<ObjCInterfaceDecl>(CDecl);2726 assert (IDecl && "CheckProtocolMethodDefs - IDecl is null");2727 2728 ObjCInterfaceDecl *Super = IDecl->getSuperClass();2729 ObjCInterfaceDecl *NSIDecl = nullptr;2730 2731 // If this protocol is marked 'objc_protocol_requires_explicit_implementation'2732 // then we should check if any class in the super class hierarchy also2733 // conforms to this protocol, either directly or via protocol inheritance.2734 // If so, we can skip checking this protocol completely because we2735 // know that a parent class already satisfies this protocol.2736 //2737 // Note: we could generalize this logic for all protocols, and merely2738 // add the limit on looking at the super class chain for just2739 // specially marked protocols. This may be a good optimization. This2740 // change is restricted to 'objc_protocol_requires_explicit_implementation'2741 // protocols for now for controlled evaluation.2742 if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) {2743 if (!ProtocolsExplictImpl) {2744 ProtocolsExplictImpl.reset(new ProtocolNameSet);2745 findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl);2746 }2747 if (ProtocolsExplictImpl->contains(PDecl->getIdentifier()))2748 return;2749 2750 // If no super class conforms to the protocol, we should not search2751 // for methods in the super class to implicitly satisfy the protocol.2752 Super = nullptr;2753 }2754 2755 if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) {2756 // check to see if class implements forwardInvocation method and objects2757 // of this class are derived from 'NSProxy' so that to forward requests2758 // from one object to another.2759 // Under such conditions, which means that every method possible is2760 // implemented in the class, we should not issue "Method definition not2761 // found" warnings.2762 // FIXME: Use a general GetUnarySelector method for this.2763 const IdentifierInfo *II = &S.Context.Idents.get("forwardInvocation");2764 Selector fISelector = S.Context.Selectors.getSelector(1, &II);2765 if (InsMap.count(fISelector))2766 // Is IDecl derived from 'NSProxy'? If so, no instance methods2767 // need be implemented in the implementation.2768 NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy"));2769 }2770 2771 // If this is a forward protocol declaration, get its definition.2772 if (!PDecl->isThisDeclarationADefinition() &&2773 PDecl->getDefinition())2774 PDecl = PDecl->getDefinition();2775 2776 // If a method lookup fails locally we still need to look and see if2777 // the method was implemented by a base class or an inherited2778 // protocol. This lookup is slow, but occurs rarely in correct code2779 // and otherwise would terminate in a warning.2780 2781 // check unimplemented instance methods.2782 if (!NSIDecl)2783 for (auto *method : PDecl->instance_methods()) {2784 if (method->getImplementationControl() !=2785 ObjCImplementationControl::Optional &&2786 !method->isPropertyAccessor() &&2787 !InsMap.count(method->getSelector()) &&2788 (!Super || !Super->lookupMethod(2789 method->getSelector(), true /* instance */,2790 false /* shallowCategory */, true /* followsSuper */,2791 nullptr /* category */))) {2792 // If a method is not implemented in the category implementation but2793 // has been declared in its primary class, superclass,2794 // or in one of their protocols, no need to issue the warning.2795 // This is because method will be implemented in the primary class2796 // or one of its super class implementation.2797 2798 // Ugly, but necessary. Method declared in protocol might have2799 // have been synthesized due to a property declared in the class which2800 // uses the protocol.2801 if (ObjCMethodDecl *MethodInClass = IDecl->lookupMethod(2802 method->getSelector(), true /* instance */,2803 true /* shallowCategoryLookup */, false /* followSuper */))2804 if (C || MethodInClass->isPropertyAccessor())2805 continue;2806 unsigned DIAG = diag::warn_unimplemented_protocol_method;2807 if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {2808 WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);2809 }2810 }2811 }2812 // check unimplemented class methods2813 for (auto *method : PDecl->class_methods()) {2814 if (method->getImplementationControl() !=2815 ObjCImplementationControl::Optional &&2816 !ClsMap.count(method->getSelector()) &&2817 (!Super || !Super->lookupMethod(2818 method->getSelector(), false /* class method */,2819 false /* shallowCategoryLookup */,2820 true /* followSuper */, nullptr /* category */))) {2821 // See above comment for instance method lookups.2822 if (C && IDecl->lookupMethod(method->getSelector(),2823 false /* class */,2824 true /* shallowCategoryLookup */,2825 false /* followSuper */))2826 continue;2827 2828 unsigned DIAG = diag::warn_unimplemented_protocol_method;2829 if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) {2830 WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl);2831 }2832 }2833 }2834 // Check on this protocols's referenced protocols, recursively.2835 for (auto *PI : PDecl->protocols())2836 CheckProtocolMethodDefs(S, Impl, PI, IncompleteImpl, InsMap, ClsMap, CDecl,2837 ProtocolsExplictImpl);2838}2839 2840/// MatchAllMethodDeclarations - Check methods declared in interface2841/// or protocol against those declared in their implementations.2842///2843void SemaObjC::MatchAllMethodDeclarations(2844 const SelectorSet &InsMap, const SelectorSet &ClsMap,2845 SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl,2846 ObjCContainerDecl *CDecl, bool &IncompleteImpl, bool ImmediateClass,2847 bool WarnCategoryMethodImpl) {2848 // Check and see if instance methods in class interface have been2849 // implemented in the implementation class. If so, their types match.2850 for (auto *I : CDecl->instance_methods()) {2851 if (!InsMapSeen.insert(I->getSelector()).second)2852 continue;2853 if (!I->isPropertyAccessor() &&2854 !InsMap.count(I->getSelector())) {2855 if (ImmediateClass)2856 WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,2857 diag::warn_undef_method_impl);2858 continue;2859 } else {2860 ObjCMethodDecl *ImpMethodDecl =2861 IMPDecl->getInstanceMethod(I->getSelector());2862 assert(CDecl->getInstanceMethod(I->getSelector(), true/*AllowHidden*/) &&2863 "Expected to find the method through lookup as well");2864 // ImpMethodDecl may be null as in a @dynamic property.2865 if (ImpMethodDecl) {2866 // Skip property accessor function stubs.2867 if (ImpMethodDecl->isSynthesizedAccessorStub())2868 continue;2869 if (!WarnCategoryMethodImpl)2870 WarnConflictingTypedMethods(ImpMethodDecl, I,2871 isa<ObjCProtocolDecl>(CDecl));2872 else if (!I->isPropertyAccessor())2873 WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));2874 }2875 }2876 }2877 2878 // Check and see if class methods in class interface have been2879 // implemented in the implementation class. If so, their types match.2880 for (auto *I : CDecl->class_methods()) {2881 if (!ClsMapSeen.insert(I->getSelector()).second)2882 continue;2883 if (!I->isPropertyAccessor() &&2884 !ClsMap.count(I->getSelector())) {2885 if (ImmediateClass)2886 WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl,2887 diag::warn_undef_method_impl);2888 } else {2889 ObjCMethodDecl *ImpMethodDecl =2890 IMPDecl->getClassMethod(I->getSelector());2891 assert(CDecl->getClassMethod(I->getSelector(), true/*AllowHidden*/) &&2892 "Expected to find the method through lookup as well");2893 // ImpMethodDecl may be null as in a @dynamic property.2894 if (ImpMethodDecl) {2895 // Skip property accessor function stubs.2896 if (ImpMethodDecl->isSynthesizedAccessorStub())2897 continue;2898 if (!WarnCategoryMethodImpl)2899 WarnConflictingTypedMethods(ImpMethodDecl, I,2900 isa<ObjCProtocolDecl>(CDecl));2901 else if (!I->isPropertyAccessor())2902 WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl));2903 }2904 }2905 }2906 2907 if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) {2908 // Also, check for methods declared in protocols inherited by2909 // this protocol.2910 for (auto *PI : PD->protocols())2911 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2912 IMPDecl, PI, IncompleteImpl, false,2913 WarnCategoryMethodImpl);2914 }2915 2916 if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {2917 // when checking that methods in implementation match their declaration,2918 // i.e. when WarnCategoryMethodImpl is false, check declarations in class2919 // extension; as well as those in categories.2920 if (!WarnCategoryMethodImpl) {2921 for (auto *Cat : I->visible_categories())2922 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2923 IMPDecl, Cat, IncompleteImpl,2924 ImmediateClass && Cat->IsClassExtension(),2925 WarnCategoryMethodImpl);2926 } else {2927 // Also methods in class extensions need be looked at next.2928 for (auto *Ext : I->visible_extensions())2929 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2930 IMPDecl, Ext, IncompleteImpl, false,2931 WarnCategoryMethodImpl);2932 }2933 2934 // Check for any implementation of a methods declared in protocol.2935 for (auto *PI : I->all_referenced_protocols())2936 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2937 IMPDecl, PI, IncompleteImpl, false,2938 WarnCategoryMethodImpl);2939 2940 // FIXME. For now, we are not checking for exact match of methods2941 // in category implementation and its primary class's super class.2942 if (!WarnCategoryMethodImpl && I->getSuperClass())2943 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2944 IMPDecl,2945 I->getSuperClass(), IncompleteImpl, false);2946 }2947}2948 2949/// CheckCategoryVsClassMethodMatches - Checks that methods implemented in2950/// category matches with those implemented in its primary class and2951/// warns each time an exact match is found.2952void SemaObjC::CheckCategoryVsClassMethodMatches(2953 ObjCCategoryImplDecl *CatIMPDecl) {2954 // Get category's primary class.2955 ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl();2956 if (!CatDecl)2957 return;2958 ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface();2959 if (!IDecl)2960 return;2961 ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass();2962 SelectorSet InsMap, ClsMap;2963 2964 for (const auto *I : CatIMPDecl->instance_methods()) {2965 Selector Sel = I->getSelector();2966 // When checking for methods implemented in the category, skip over2967 // those declared in category class's super class. This is because2968 // the super class must implement the method.2969 if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true))2970 continue;2971 InsMap.insert(Sel);2972 }2973 2974 for (const auto *I : CatIMPDecl->class_methods()) {2975 Selector Sel = I->getSelector();2976 if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false))2977 continue;2978 ClsMap.insert(Sel);2979 }2980 if (InsMap.empty() && ClsMap.empty())2981 return;2982 2983 SelectorSet InsMapSeen, ClsMapSeen;2984 bool IncompleteImpl = false;2985 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,2986 CatIMPDecl, IDecl,2987 IncompleteImpl, false,2988 true /*WarnCategoryMethodImpl*/);2989}2990 2991void SemaObjC::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl,2992 ObjCContainerDecl *CDecl,2993 bool IncompleteImpl) {2994 SelectorSet InsMap;2995 // Check and see if instance methods in class interface have been2996 // implemented in the implementation class.2997 for (const auto *I : IMPDecl->instance_methods())2998 InsMap.insert(I->getSelector());2999 3000 // Add the selectors for getters/setters of @dynamic properties.3001 for (const auto *PImpl : IMPDecl->property_impls()) {3002 // We only care about @dynamic implementations.3003 if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic)3004 continue;3005 3006 const auto *P = PImpl->getPropertyDecl();3007 if (!P) continue;3008 3009 InsMap.insert(P->getGetterName());3010 if (!P->getSetterName().isNull())3011 InsMap.insert(P->getSetterName());3012 }3013 3014 // Check and see if properties declared in the interface have either 1)3015 // an implementation or 2) there is a @synthesize/@dynamic implementation3016 // of the property in the @implementation.3017 if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) {3018 bool SynthesizeProperties = getLangOpts().ObjCDefaultSynthProperties &&3019 getLangOpts().ObjCRuntime.isNonFragile() &&3020 !IDecl->isObjCRequiresPropertyDefs();3021 DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties);3022 }3023 3024 // Diagnose null-resettable synthesized setters.3025 diagnoseNullResettableSynthesizedSetters(IMPDecl);3026 3027 SelectorSet ClsMap;3028 for (const auto *I : IMPDecl->class_methods())3029 ClsMap.insert(I->getSelector());3030 3031 // Check for type conflict of methods declared in a class/protocol and3032 // its implementation; if any.3033 SelectorSet InsMapSeen, ClsMapSeen;3034 MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,3035 IMPDecl, CDecl,3036 IncompleteImpl, true);3037 3038 // check all methods implemented in category against those declared3039 // in its primary class.3040 if (ObjCCategoryImplDecl *CatDecl =3041 dyn_cast<ObjCCategoryImplDecl>(IMPDecl))3042 CheckCategoryVsClassMethodMatches(CatDecl);3043 3044 // Check the protocol list for unimplemented methods in the @implementation3045 // class.3046 // Check and see if class methods in class interface have been3047 // implemented in the implementation class.3048 3049 LazyProtocolNameSet ExplicitImplProtocols;3050 3051 if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {3052 for (auto *PI : I->all_referenced_protocols())3053 CheckProtocolMethodDefs(SemaRef, IMPDecl, PI, IncompleteImpl, InsMap,3054 ClsMap, I, ExplicitImplProtocols);3055 } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) {3056 // For extended class, unimplemented methods in its protocols will3057 // be reported in the primary class.3058 if (!C->IsClassExtension()) {3059 for (auto *P : C->protocols())3060 CheckProtocolMethodDefs(SemaRef, IMPDecl, P, IncompleteImpl, InsMap,3061 ClsMap, CDecl, ExplicitImplProtocols);3062 DiagnoseUnimplementedProperties(S, IMPDecl, CDecl,3063 /*SynthesizeProperties=*/false);3064 }3065 } else3066 llvm_unreachable("invalid ObjCContainerDecl type.");3067}3068 3069SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardClassDeclaration(3070 SourceLocation AtClassLoc, IdentifierInfo **IdentList,3071 SourceLocation *IdentLocs, ArrayRef<ObjCTypeParamList *> TypeParamLists,3072 unsigned NumElts) {3073 ASTContext &Context = getASTContext();3074 SmallVector<Decl *, 8> DeclsInGroup;3075 for (unsigned i = 0; i != NumElts; ++i) {3076 // Check for another declaration kind with the same name.3077 NamedDecl *PrevDecl = SemaRef.LookupSingleName(3078 SemaRef.TUScope, IdentList[i], IdentLocs[i], Sema::LookupOrdinaryName,3079 SemaRef.forRedeclarationInCurContext());3080 if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {3081 // GCC apparently allows the following idiom:3082 //3083 // typedef NSObject < XCElementTogglerP > XCElementToggler;3084 // @class XCElementToggler;3085 //3086 // Here we have chosen to ignore the forward class declaration3087 // with a warning. Since this is the implied behavior.3088 TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);3089 if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {3090 Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];3091 Diag(PrevDecl->getLocation(), diag::note_previous_definition);3092 } else {3093 // a forward class declaration matching a typedef name of a class refers3094 // to the underlying class. Just ignore the forward class with a warning3095 // as this will force the intended behavior which is to lookup the3096 // typedef name.3097 if (isa<ObjCObjectType>(TDD->getUnderlyingType())) {3098 Diag(AtClassLoc, diag::warn_forward_class_redefinition)3099 << IdentList[i];3100 Diag(PrevDecl->getLocation(), diag::note_previous_definition);3101 continue;3102 }3103 }3104 }3105 3106 // Create a declaration to describe this forward declaration.3107 ObjCInterfaceDecl *PrevIDecl3108 = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl);3109 3110 IdentifierInfo *ClassName = IdentList[i];3111 if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) {3112 // A previous decl with a different name is because of3113 // @compatibility_alias, for example:3114 // \code3115 // @class NewImage;3116 // @compatibility_alias OldImage NewImage;3117 // \endcode3118 // A lookup for 'OldImage' will return the 'NewImage' decl.3119 //3120 // In such a case use the real declaration name, instead of the alias one,3121 // otherwise we will break IdentifierResolver and redecls-chain invariants.3122 // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl3123 // has been aliased.3124 ClassName = PrevIDecl->getIdentifier();3125 }3126 3127 // If this forward declaration has type parameters, compare them with the3128 // type parameters of the previous declaration.3129 ObjCTypeParamList *TypeParams = TypeParamLists[i];3130 if (PrevIDecl && TypeParams) {3131 if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) {3132 // Check for consistency with the previous declaration.3133 if (checkTypeParamListConsistency(3134 SemaRef, PrevTypeParams, TypeParams,3135 TypeParamListContext::ForwardDeclaration)) {3136 TypeParams = nullptr;3137 }3138 } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) {3139 // The @interface does not have type parameters. Complain.3140 Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class)3141 << ClassName3142 << TypeParams->getSourceRange();3143 Diag(Def->getLocation(), diag::note_defined_here)3144 << ClassName;3145 3146 TypeParams = nullptr;3147 }3148 }3149 3150 ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create(3151 Context, SemaRef.CurContext, AtClassLoc, ClassName, TypeParams,3152 PrevIDecl, IdentLocs[i]);3153 IDecl->setAtEndRange(IdentLocs[i]);3154 3155 if (PrevIDecl)3156 SemaRef.mergeDeclAttributes(IDecl, PrevIDecl);3157 3158 SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope);3159 CheckObjCDeclScope(IDecl);3160 DeclsInGroup.push_back(IDecl);3161 }3162 3163 return SemaRef.BuildDeclaratorGroup(DeclsInGroup);3164}3165 3166static bool tryMatchRecordTypes(ASTContext &Context,3167 SemaObjC::MethodMatchStrategy strategy,3168 const Type *left, const Type *right);3169 3170static bool matchTypes(ASTContext &Context,3171 SemaObjC::MethodMatchStrategy strategy, QualType leftQT,3172 QualType rightQT) {3173 const Type *left =3174 Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr();3175 const Type *right =3176 Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr();3177 3178 if (left == right) return true;3179 3180 // If we're doing a strict match, the types have to match exactly.3181 if (strategy == SemaObjC::MMS_strict)3182 return false;3183 3184 if (left->isIncompleteType() || right->isIncompleteType()) return false;3185 3186 // Otherwise, use this absurdly complicated algorithm to try to3187 // validate the basic, low-level compatibility of the two types.3188 3189 // As a minimum, require the sizes and alignments to match.3190 TypeInfo LeftTI = Context.getTypeInfo(left);3191 TypeInfo RightTI = Context.getTypeInfo(right);3192 if (LeftTI.Width != RightTI.Width)3193 return false;3194 3195 if (LeftTI.Align != RightTI.Align)3196 return false;3197 3198 // Consider all the kinds of non-dependent canonical types:3199 // - functions and arrays aren't possible as return and parameter types3200 3201 // - vector types of equal size can be arbitrarily mixed3202 if (isa<VectorType>(left)) return isa<VectorType>(right);3203 if (isa<VectorType>(right)) return false;3204 3205 // - references should only match references of identical type3206 // - structs, unions, and Objective-C objects must match more-or-less3207 // exactly3208 // - everything else should be a scalar3209 if (!left->isScalarType() || !right->isScalarType())3210 return tryMatchRecordTypes(Context, strategy, left, right);3211 3212 // Make scalars agree in kind, except count bools as chars, and group3213 // all non-member pointers together.3214 Type::ScalarTypeKind leftSK = left->getScalarTypeKind();3215 Type::ScalarTypeKind rightSK = right->getScalarTypeKind();3216 if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral;3217 if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral;3218 if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer)3219 leftSK = Type::STK_ObjCObjectPointer;3220 if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer)3221 rightSK = Type::STK_ObjCObjectPointer;3222 3223 // Note that data member pointers and function member pointers don't3224 // intermix because of the size differences.3225 3226 return (leftSK == rightSK);3227}3228 3229static bool tryMatchRecordTypes(ASTContext &Context,3230 SemaObjC::MethodMatchStrategy strategy,3231 const Type *lt, const Type *rt) {3232 assert(lt && rt && lt != rt);3233 3234 if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false;3235 RecordDecl *left = cast<RecordType>(lt)->getDecl()->getDefinitionOrSelf();3236 RecordDecl *right = cast<RecordType>(rt)->getDecl()->getDefinitionOrSelf();3237 3238 // Require union-hood to match.3239 if (left->isUnion() != right->isUnion()) return false;3240 3241 // Require an exact match if either is non-POD.3242 if ((isa<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) ||3243 (isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(right)->isPOD()))3244 return false;3245 3246 // Require size and alignment to match.3247 TypeInfo LeftTI = Context.getTypeInfo(lt);3248 TypeInfo RightTI = Context.getTypeInfo(rt);3249 if (LeftTI.Width != RightTI.Width)3250 return false;3251 3252 if (LeftTI.Align != RightTI.Align)3253 return false;3254 3255 // Require fields to match.3256 RecordDecl::field_iterator li = left->field_begin(), le = left->field_end();3257 RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end();3258 for (; li != le && ri != re; ++li, ++ri) {3259 if (!matchTypes(Context, strategy, li->getType(), ri->getType()))3260 return false;3261 }3262 return (li == le && ri == re);3263}3264 3265/// MatchTwoMethodDeclarations - Checks that two methods have matching type and3266/// returns true, or false, accordingly.3267/// TODO: Handle protocol list; such as id<p1,p2> in type comparisons3268bool SemaObjC::MatchTwoMethodDeclarations(const ObjCMethodDecl *left,3269 const ObjCMethodDecl *right,3270 MethodMatchStrategy strategy) {3271 ASTContext &Context = getASTContext();3272 if (!matchTypes(Context, strategy, left->getReturnType(),3273 right->getReturnType()))3274 return false;3275 3276 // If either is hidden, it is not considered to match.3277 if (!left->isUnconditionallyVisible() || !right->isUnconditionallyVisible())3278 return false;3279 3280 if (left->isDirectMethod() != right->isDirectMethod())3281 return false;3282 3283 if (getLangOpts().ObjCAutoRefCount &&3284 (left->hasAttr<NSReturnsRetainedAttr>()3285 != right->hasAttr<NSReturnsRetainedAttr>() ||3286 left->hasAttr<NSConsumesSelfAttr>()3287 != right->hasAttr<NSConsumesSelfAttr>()))3288 return false;3289 3290 ObjCMethodDecl::param_const_iterator3291 li = left->param_begin(), le = left->param_end(), ri = right->param_begin(),3292 re = right->param_end();3293 3294 for (; li != le && ri != re; ++li, ++ri) {3295 assert(ri != right->param_end() && "Param mismatch");3296 const ParmVarDecl *lparm = *li, *rparm = *ri;3297 3298 if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType()))3299 return false;3300 3301 if (getLangOpts().ObjCAutoRefCount &&3302 lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>())3303 return false;3304 }3305 return true;3306}3307 3308static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method,3309 ObjCMethodDecl *MethodInList) {3310 auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());3311 auto *MethodInListProtocol =3312 dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext());3313 // If this method belongs to a protocol but the method in list does not, or3314 // vice versa, we say the context is not the same.3315 if ((MethodProtocol && !MethodInListProtocol) ||3316 (!MethodProtocol && MethodInListProtocol))3317 return false;3318 3319 if (MethodProtocol && MethodInListProtocol)3320 return true;3321 3322 ObjCInterfaceDecl *MethodInterface = Method->getClassInterface();3323 ObjCInterfaceDecl *MethodInListInterface =3324 MethodInList->getClassInterface();3325 return MethodInterface == MethodInListInterface;3326}3327 3328void SemaObjC::addMethodToGlobalList(ObjCMethodList *List,3329 ObjCMethodDecl *Method) {3330 // Record at the head of the list whether there were 0, 1, or >= 2 methods3331 // inside categories.3332 if (ObjCCategoryDecl *CD =3333 dyn_cast<ObjCCategoryDecl>(Method->getDeclContext()))3334 if (!CD->IsClassExtension() && List->getBits() < 2)3335 List->setBits(List->getBits() + 1);3336 3337 // If the list is empty, make it a singleton list.3338 if (List->getMethod() == nullptr) {3339 List->setMethod(Method);3340 List->setNext(nullptr);3341 return;3342 }3343 3344 // We've seen a method with this name, see if we have already seen this type3345 // signature.3346 ObjCMethodList *Previous = List;3347 ObjCMethodList *ListWithSameDeclaration = nullptr;3348 for (; List; Previous = List, List = List->getNext()) {3349 // If we are building a module, keep all of the methods.3350 if (getLangOpts().isCompilingModule())3351 continue;3352 3353 bool SameDeclaration = MatchTwoMethodDeclarations(Method,3354 List->getMethod());3355 // Looking for method with a type bound requires the correct context exists.3356 // We need to insert a method into the list if the context is different.3357 // If the method's declaration matches the list3358 // a> the method belongs to a different context: we need to insert it, in3359 // order to emit the availability message, we need to prioritize over3360 // availability among the methods with the same declaration.3361 // b> the method belongs to the same context: there is no need to insert a3362 // new entry.3363 // If the method's declaration does not match the list, we insert it to the3364 // end.3365 if (!SameDeclaration ||3366 !isMethodContextSameForKindofLookup(Method, List->getMethod())) {3367 // Even if two method types do not match, we would like to say3368 // there is more than one declaration so unavailability/deprecated3369 // warning is not too noisy.3370 if (!Method->isDefined())3371 List->setHasMoreThanOneDecl(true);3372 3373 // For methods with the same declaration, the one that is deprecated3374 // should be put in the front for better diagnostics.3375 if (Method->isDeprecated() && SameDeclaration &&3376 !ListWithSameDeclaration && !List->getMethod()->isDeprecated())3377 ListWithSameDeclaration = List;3378 3379 if (Method->isUnavailable() && SameDeclaration &&3380 !ListWithSameDeclaration &&3381 List->getMethod()->getAvailability() < AR_Deprecated)3382 ListWithSameDeclaration = List;3383 continue;3384 }3385 3386 ObjCMethodDecl *PrevObjCMethod = List->getMethod();3387 3388 // Propagate the 'defined' bit.3389 if (Method->isDefined())3390 PrevObjCMethod->setDefined(true);3391 else {3392 // Objective-C doesn't allow an @interface for a class after its3393 // @implementation. So if Method is not defined and there already is3394 // an entry for this type signature, Method has to be for a different3395 // class than PrevObjCMethod.3396 List->setHasMoreThanOneDecl(true);3397 }3398 3399 // If a method is deprecated, push it in the global pool.3400 // This is used for better diagnostics.3401 if (Method->isDeprecated()) {3402 if (!PrevObjCMethod->isDeprecated())3403 List->setMethod(Method);3404 }3405 // If the new method is unavailable, push it into global pool3406 // unless previous one is deprecated.3407 if (Method->isUnavailable()) {3408 if (PrevObjCMethod->getAvailability() < AR_Deprecated)3409 List->setMethod(Method);3410 }3411 3412 return;3413 }3414 3415 // We have a new signature for an existing method - add it.3416 // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".3417 ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate<ObjCMethodList>();3418 3419 // We insert it right before ListWithSameDeclaration.3420 if (ListWithSameDeclaration) {3421 auto *List = new (Mem) ObjCMethodList(*ListWithSameDeclaration);3422 // FIXME: should we clear the other bits in ListWithSameDeclaration?3423 ListWithSameDeclaration->setMethod(Method);3424 ListWithSameDeclaration->setNext(List);3425 return;3426 }3427 3428 Previous->setNext(new (Mem) ObjCMethodList(Method));3429}3430 3431/// Read the contents of the method pool for a given selector from3432/// external storage.3433void SemaObjC::ReadMethodPool(Selector Sel) {3434 assert(SemaRef.ExternalSource && "We need an external AST source");3435 SemaRef.ExternalSource->ReadMethodPool(Sel);3436}3437 3438void SemaObjC::updateOutOfDateSelector(Selector Sel) {3439 if (!SemaRef.ExternalSource)3440 return;3441 SemaRef.ExternalSource->updateOutOfDateSelector(Sel);3442}3443 3444void SemaObjC::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl,3445 bool instance) {3446 // Ignore methods of invalid containers.3447 if (cast<Decl>(Method->getDeclContext())->isInvalidDecl())3448 return;3449 3450 if (SemaRef.ExternalSource)3451 ReadMethodPool(Method->getSelector());3452 3453 auto &Lists = MethodPool[Method->getSelector()];3454 3455 Method->setDefined(impl);3456 3457 ObjCMethodList &Entry = instance ? Lists.first : Lists.second;3458 addMethodToGlobalList(&Entry, Method);3459}3460 3461/// Determines if this is an "acceptable" loose mismatch in the global3462/// method pool. This exists mostly as a hack to get around certain3463/// global mismatches which we can't afford to make warnings / errors.3464/// Really, what we want is a way to take a method out of the global3465/// method pool.3466static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen,3467 ObjCMethodDecl *other) {3468 if (!chosen->isInstanceMethod())3469 return false;3470 3471 if (chosen->isDirectMethod() != other->isDirectMethod())3472 return false;3473 3474 Selector sel = chosen->getSelector();3475 if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length")3476 return false;3477 3478 // Don't complain about mismatches for -length if the method we3479 // chose has an integral result type.3480 return (chosen->getReturnType()->isIntegerType());3481}3482 3483/// Return true if the given method is wthin the type bound.3484static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method,3485 const ObjCObjectType *TypeBound) {3486 if (!TypeBound)3487 return true;3488 3489 if (TypeBound->isObjCId())3490 // FIXME: should we handle the case of bounding to id<A, B> differently?3491 return true;3492 3493 auto *BoundInterface = TypeBound->getInterface();3494 assert(BoundInterface && "unexpected object type!");3495 3496 // Check if the Method belongs to a protocol. We should allow any method3497 // defined in any protocol, because any subclass could adopt the protocol.3498 auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext());3499 if (MethodProtocol) {3500 return true;3501 }3502 3503 // If the Method belongs to a class, check if it belongs to the class3504 // hierarchy of the class bound.3505 if (ObjCInterfaceDecl *MethodInterface = Method->getClassInterface()) {3506 // We allow methods declared within classes that are part of the hierarchy3507 // of the class bound (superclass of, subclass of, or the same as the class3508 // bound).3509 return MethodInterface == BoundInterface ||3510 MethodInterface->isSuperClassOf(BoundInterface) ||3511 BoundInterface->isSuperClassOf(MethodInterface);3512 }3513 llvm_unreachable("unknown method context");3514}3515 3516/// We first select the type of the method: Instance or Factory, then collect3517/// all methods with that type.3518bool SemaObjC::CollectMultipleMethodsInGlobalPool(3519 Selector Sel, SmallVectorImpl<ObjCMethodDecl *> &Methods,3520 bool InstanceFirst, bool CheckTheOther, const ObjCObjectType *TypeBound) {3521 if (SemaRef.ExternalSource)3522 ReadMethodPool(Sel);3523 3524 GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3525 if (Pos == MethodPool.end())3526 return false;3527 3528 // Gather the non-hidden methods.3529 ObjCMethodList &MethList = InstanceFirst ? Pos->second.first :3530 Pos->second.second;3531 for (ObjCMethodList *M = &MethList; M; M = M->getNext())3532 if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {3533 if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))3534 Methods.push_back(M->getMethod());3535 }3536 3537 // Return if we find any method with the desired kind.3538 if (!Methods.empty())3539 return Methods.size() > 1;3540 3541 if (!CheckTheOther)3542 return false;3543 3544 // Gather the other kind.3545 ObjCMethodList &MethList2 = InstanceFirst ? Pos->second.second :3546 Pos->second.first;3547 for (ObjCMethodList *M = &MethList2; M; M = M->getNext())3548 if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) {3549 if (FilterMethodsByTypeBound(M->getMethod(), TypeBound))3550 Methods.push_back(M->getMethod());3551 }3552 3553 return Methods.size() > 1;3554}3555 3556bool SemaObjC::AreMultipleMethodsInGlobalPool(3557 Selector Sel, ObjCMethodDecl *BestMethod, SourceRange R,3558 bool receiverIdOrClass, SmallVectorImpl<ObjCMethodDecl *> &Methods) {3559 // Diagnose finding more than one method in global pool.3560 SmallVector<ObjCMethodDecl *, 4> FilteredMethods;3561 FilteredMethods.push_back(BestMethod);3562 3563 for (auto *M : Methods)3564 if (M != BestMethod && !M->hasAttr<UnavailableAttr>())3565 FilteredMethods.push_back(M);3566 3567 if (FilteredMethods.size() > 1)3568 DiagnoseMultipleMethodInGlobalPool(FilteredMethods, Sel, R,3569 receiverIdOrClass);3570 3571 GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3572 // Test for no method in the pool which should not trigger any warning by3573 // caller.3574 if (Pos == MethodPool.end())3575 return true;3576 ObjCMethodList &MethList =3577 BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second;3578 return MethList.hasMoreThanOneDecl();3579}3580 3581ObjCMethodDecl *SemaObjC::LookupMethodInGlobalPool(Selector Sel, SourceRange R,3582 bool receiverIdOrClass,3583 bool instance) {3584 if (SemaRef.ExternalSource)3585 ReadMethodPool(Sel);3586 3587 GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3588 if (Pos == MethodPool.end())3589 return nullptr;3590 3591 // Gather the non-hidden methods.3592 ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second;3593 for (ObjCMethodList *M = &MethList; M; M = M->getNext()) {3594 if (M->getMethod() && M->getMethod()->isUnconditionallyVisible())3595 return M->getMethod();3596 }3597 return nullptr;3598}3599 3600void SemaObjC::DiagnoseMultipleMethodInGlobalPool(3601 SmallVectorImpl<ObjCMethodDecl *> &Methods, Selector Sel, SourceRange R,3602 bool receiverIdOrClass) {3603 // We found multiple methods, so we may have to complain.3604 bool issueDiagnostic = false, issueError = false;3605 3606 // We support a warning which complains about *any* difference in3607 // method signature.3608 bool strictSelectorMatch =3609 receiverIdOrClass &&3610 !getDiagnostics().isIgnored(diag::warn_strict_multiple_method_decl,3611 R.getBegin());3612 if (strictSelectorMatch) {3613 for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3614 if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) {3615 issueDiagnostic = true;3616 break;3617 }3618 }3619 }3620 3621 // If we didn't see any strict differences, we won't see any loose3622 // differences. In ARC, however, we also need to check for loose3623 // mismatches, because most of them are errors.3624 if (!strictSelectorMatch ||3625 (issueDiagnostic && getLangOpts().ObjCAutoRefCount))3626 for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3627 // This checks if the methods differ in type mismatch.3628 if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) &&3629 !isAcceptableMethodMismatch(Methods[0], Methods[I])) {3630 issueDiagnostic = true;3631 if (getLangOpts().ObjCAutoRefCount)3632 issueError = true;3633 break;3634 }3635 }3636 3637 if (issueDiagnostic) {3638 if (issueError)3639 Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R;3640 else if (strictSelectorMatch)3641 Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R;3642 else3643 Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;3644 3645 Diag(Methods[0]->getBeginLoc(),3646 issueError ? diag::note_possibility : diag::note_using)3647 << Methods[0]->getSourceRange();3648 for (unsigned I = 1, N = Methods.size(); I != N; ++I) {3649 Diag(Methods[I]->getBeginLoc(), diag::note_also_found)3650 << Methods[I]->getSourceRange();3651 }3652 }3653}3654 3655ObjCMethodDecl *SemaObjC::LookupImplementedMethodInGlobalPool(Selector Sel) {3656 GlobalMethodPool::iterator Pos = MethodPool.find(Sel);3657 if (Pos == MethodPool.end())3658 return nullptr;3659 3660 auto &Methods = Pos->second;3661 for (const ObjCMethodList *Method = &Methods.first; Method;3662 Method = Method->getNext())3663 if (Method->getMethod() &&3664 (Method->getMethod()->isDefined() ||3665 Method->getMethod()->isPropertyAccessor()))3666 return Method->getMethod();3667 3668 for (const ObjCMethodList *Method = &Methods.second; Method;3669 Method = Method->getNext())3670 if (Method->getMethod() &&3671 (Method->getMethod()->isDefined() ||3672 Method->getMethod()->isPropertyAccessor()))3673 return Method->getMethod();3674 return nullptr;3675}3676 3677static void3678HelperSelectorsForTypoCorrection(3679 SmallVectorImpl<const ObjCMethodDecl *> &BestMethod,3680 StringRef Typo, const ObjCMethodDecl * Method) {3681 const unsigned MaxEditDistance = 1;3682 unsigned BestEditDistance = MaxEditDistance + 1;3683 std::string MethodName = Method->getSelector().getAsString();3684 3685 unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size());3686 if (MinPossibleEditDistance > 0 &&3687 Typo.size() / MinPossibleEditDistance < 1)3688 return;3689 unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance);3690 if (EditDistance > MaxEditDistance)3691 return;3692 if (EditDistance == BestEditDistance)3693 BestMethod.push_back(Method);3694 else if (EditDistance < BestEditDistance) {3695 BestMethod.clear();3696 BestMethod.push_back(Method);3697 }3698}3699 3700static bool HelperIsMethodInObjCType(Sema &S, Selector Sel,3701 QualType ObjectType) {3702 if (ObjectType.isNull())3703 return true;3704 if (S.ObjC().LookupMethodInObjectType(Sel, ObjectType,3705 true /*Instance method*/))3706 return true;3707 return S.ObjC().LookupMethodInObjectType(Sel, ObjectType,3708 false /*Class method*/) != nullptr;3709}3710 3711const ObjCMethodDecl *3712SemaObjC::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) {3713 unsigned NumArgs = Sel.getNumArgs();3714 SmallVector<const ObjCMethodDecl *, 8> Methods;3715 bool ObjectIsId = true, ObjectIsClass = true;3716 if (ObjectType.isNull())3717 ObjectIsId = ObjectIsClass = false;3718 else if (!ObjectType->isObjCObjectPointerType())3719 return nullptr;3720 else if (const ObjCObjectPointerType *ObjCPtr =3721 ObjectType->getAsObjCInterfacePointerType()) {3722 ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);3723 ObjectIsId = ObjectIsClass = false;3724 }3725 else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType())3726 ObjectIsClass = false;3727 else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())3728 ObjectIsId = false;3729 else3730 return nullptr;3731 3732 for (GlobalMethodPool::iterator b = MethodPool.begin(),3733 e = MethodPool.end(); b != e; b++) {3734 // instance methods3735 for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())3736 if (M->getMethod() &&3737 (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&3738 (M->getMethod()->getSelector() != Sel)) {3739 if (ObjectIsId)3740 Methods.push_back(M->getMethod());3741 else if (!ObjectIsClass &&3742 HelperIsMethodInObjCType(3743 SemaRef, M->getMethod()->getSelector(), ObjectType))3744 Methods.push_back(M->getMethod());3745 }3746 // class methods3747 for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())3748 if (M->getMethod() &&3749 (M->getMethod()->getSelector().getNumArgs() == NumArgs) &&3750 (M->getMethod()->getSelector() != Sel)) {3751 if (ObjectIsClass)3752 Methods.push_back(M->getMethod());3753 else if (!ObjectIsId &&3754 HelperIsMethodInObjCType(3755 SemaRef, M->getMethod()->getSelector(), ObjectType))3756 Methods.push_back(M->getMethod());3757 }3758 }3759 3760 SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;3761 for (unsigned i = 0, e = Methods.size(); i < e; i++) {3762 HelperSelectorsForTypoCorrection(SelectedMethods,3763 Sel.getAsString(), Methods[i]);3764 }3765 return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr;3766}3767 3768/// DiagnoseDuplicateIvars -3769/// Check for duplicate ivars in the entire class at the start of3770/// \@implementation. This becomes necessary because class extension can3771/// add ivars to a class in random order which will not be known until3772/// class's \@implementation is seen.3773void SemaObjC::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID,3774 ObjCInterfaceDecl *SID) {3775 for (auto *Ivar : ID->ivars()) {3776 if (Ivar->isInvalidDecl())3777 continue;3778 if (IdentifierInfo *II = Ivar->getIdentifier()) {3779 ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II);3780 if (prevIvar) {3781 Diag(Ivar->getLocation(), diag::err_duplicate_member) << II;3782 Diag(prevIvar->getLocation(), diag::note_previous_declaration);3783 Ivar->setInvalidDecl();3784 }3785 }3786 }3787}3788 3789/// Diagnose attempts to define ARC-__weak ivars when __weak is disabled.3790static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) {3791 if (S.getLangOpts().ObjCWeak) return;3792 3793 for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin();3794 ivar; ivar = ivar->getNextIvar()) {3795 if (ivar->isInvalidDecl()) continue;3796 if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) {3797 if (S.getLangOpts().ObjCWeakRuntime) {3798 S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled);3799 } else {3800 S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime);3801 }3802 }3803 }3804}3805 3806/// Diagnose attempts to use flexible array member with retainable object type.3807static void DiagnoseRetainableFlexibleArrayMember(Sema &S,3808 ObjCInterfaceDecl *ID) {3809 if (!S.getLangOpts().ObjCAutoRefCount)3810 return;3811 3812 for (auto ivar = ID->all_declared_ivar_begin(); ivar;3813 ivar = ivar->getNextIvar()) {3814 if (ivar->isInvalidDecl())3815 continue;3816 QualType IvarTy = ivar->getType();3817 if (IvarTy->isIncompleteArrayType() &&3818 (IvarTy.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) &&3819 IvarTy->isObjCLifetimeType()) {3820 S.Diag(ivar->getLocation(), diag::err_flexible_array_arc_retainable);3821 ivar->setInvalidDecl();3822 }3823 }3824}3825 3826SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const {3827 switch (SemaRef.CurContext->getDeclKind()) {3828 case Decl::ObjCInterface:3829 return SemaObjC::OCK_Interface;3830 case Decl::ObjCProtocol:3831 return SemaObjC::OCK_Protocol;3832 case Decl::ObjCCategory:3833 if (cast<ObjCCategoryDecl>(SemaRef.CurContext)->IsClassExtension())3834 return SemaObjC::OCK_ClassExtension;3835 return SemaObjC::OCK_Category;3836 case Decl::ObjCImplementation:3837 return SemaObjC::OCK_Implementation;3838 case Decl::ObjCCategoryImpl:3839 return SemaObjC::OCK_CategoryImplementation;3840 3841 default:3842 return SemaObjC::OCK_None;3843 }3844}3845 3846static bool IsVariableSizedType(QualType T) {3847 if (T->isIncompleteArrayType())3848 return true;3849 const auto *RD = T->getAsRecordDecl();3850 return RD && RD->hasFlexibleArrayMember();3851}3852 3853static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) {3854 ObjCInterfaceDecl *IntfDecl = nullptr;3855 ObjCInterfaceDecl::ivar_range Ivars = llvm::make_range(3856 ObjCInterfaceDecl::ivar_iterator(), ObjCInterfaceDecl::ivar_iterator());3857 if ((IntfDecl = dyn_cast<ObjCInterfaceDecl>(OCD))) {3858 Ivars = IntfDecl->ivars();3859 } else if (auto *ImplDecl = dyn_cast<ObjCImplementationDecl>(OCD)) {3860 IntfDecl = ImplDecl->getClassInterface();3861 Ivars = ImplDecl->ivars();3862 } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(OCD)) {3863 if (CategoryDecl->IsClassExtension()) {3864 IntfDecl = CategoryDecl->getClassInterface();3865 Ivars = CategoryDecl->ivars();3866 }3867 }3868 3869 // Check if variable sized ivar is in interface and visible to subclasses.3870 if (!isa<ObjCInterfaceDecl>(OCD)) {3871 for (auto *ivar : Ivars) {3872 if (!ivar->isInvalidDecl() && IsVariableSizedType(ivar->getType())) {3873 S.Diag(ivar->getLocation(), diag::warn_variable_sized_ivar_visibility)3874 << ivar->getDeclName() << ivar->getType();3875 }3876 }3877 }3878 3879 // Subsequent checks require interface decl.3880 if (!IntfDecl)3881 return;3882 3883 // Check if variable sized ivar is followed by another ivar.3884 for (ObjCIvarDecl *ivar = IntfDecl->all_declared_ivar_begin(); ivar;3885 ivar = ivar->getNextIvar()) {3886 if (ivar->isInvalidDecl() || !ivar->getNextIvar())3887 continue;3888 QualType IvarTy = ivar->getType();3889 bool IsInvalidIvar = false;3890 if (IvarTy->isIncompleteArrayType()) {3891 S.Diag(ivar->getLocation(), diag::err_flexible_array_not_at_end)3892 << ivar->getDeclName() << IvarTy3893 << TagTypeKind::Class; // Use "class" for Obj-C.3894 IsInvalidIvar = true;3895 } else if (const auto *RD = IvarTy->getAsRecordDecl();3896 RD && RD->hasFlexibleArrayMember()) {3897 S.Diag(ivar->getLocation(), diag::err_objc_variable_sized_type_not_at_end)3898 << ivar->getDeclName() << IvarTy;3899 IsInvalidIvar = true;3900 }3901 if (IsInvalidIvar) {3902 S.Diag(ivar->getNextIvar()->getLocation(),3903 diag::note_next_ivar_declaration)3904 << ivar->getNextIvar()->getSynthesize();3905 ivar->setInvalidDecl();3906 }3907 }3908 3909 // Check if ObjC container adds ivars after variable sized ivar in superclass.3910 // Perform the check only if OCD is the first container to declare ivars to3911 // avoid multiple warnings for the same ivar.3912 ObjCIvarDecl *FirstIvar =3913 (Ivars.begin() == Ivars.end()) ? nullptr : *Ivars.begin();3914 if (FirstIvar && (FirstIvar == IntfDecl->all_declared_ivar_begin())) {3915 const ObjCInterfaceDecl *SuperClass = IntfDecl->getSuperClass();3916 while (SuperClass && SuperClass->ivar_empty())3917 SuperClass = SuperClass->getSuperClass();3918 if (SuperClass) {3919 auto IvarIter = SuperClass->ivar_begin();3920 std::advance(IvarIter, SuperClass->ivar_size() - 1);3921 const ObjCIvarDecl *LastIvar = *IvarIter;3922 if (IsVariableSizedType(LastIvar->getType())) {3923 S.Diag(FirstIvar->getLocation(),3924 diag::warn_superclass_variable_sized_type_not_at_end)3925 << FirstIvar->getDeclName() << LastIvar->getDeclName()3926 << LastIvar->getType() << SuperClass->getDeclName();3927 S.Diag(LastIvar->getLocation(), diag::note_entity_declared_at)3928 << LastIvar->getDeclName();3929 }3930 }3931 }3932}3933 3934static void DiagnoseCategoryDirectMembersProtocolConformance(3935 Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl);3936 3937static void DiagnoseCategoryDirectMembersProtocolConformance(3938 Sema &S, ObjCCategoryDecl *CDecl,3939 const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) {3940 for (auto *PI : Protocols)3941 DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl);3942}3943 3944static void DiagnoseCategoryDirectMembersProtocolConformance(3945 Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) {3946 if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition())3947 PDecl = PDecl->getDefinition();3948 3949 llvm::SmallVector<const Decl *, 4> DirectMembers;3950 const auto *IDecl = CDecl->getClassInterface();3951 for (auto *MD : PDecl->methods()) {3952 if (!MD->isPropertyAccessor()) {3953 if (const auto *CMD =3954 IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) {3955 if (CMD->isDirectMethod())3956 DirectMembers.push_back(CMD);3957 }3958 }3959 }3960 for (auto *PD : PDecl->properties()) {3961 if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass(3962 PD->getIdentifier(),3963 PD->isClassProperty()3964 ? ObjCPropertyQueryKind::OBJC_PR_query_class3965 : ObjCPropertyQueryKind::OBJC_PR_query_instance)) {3966 if (CPD->isDirectProperty())3967 DirectMembers.push_back(CPD);3968 }3969 }3970 if (!DirectMembers.empty()) {3971 S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance)3972 << CDecl->IsClassExtension() << CDecl << PDecl << IDecl;3973 for (const auto *MD : DirectMembers)3974 S.Diag(MD->getLocation(), diag::note_direct_member_here);3975 return;3976 }3977 3978 // Check on this protocols's referenced protocols, recursively.3979 DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl,3980 PDecl->protocols());3981}3982 3983// Note: For class/category implementations, allMethods is always null.3984Decl *SemaObjC::ActOnAtEnd(Scope *S, SourceRange AtEnd,3985 ArrayRef<Decl *> allMethods,3986 ArrayRef<DeclGroupPtrTy> allTUVars) {3987 ASTContext &Context = getASTContext();3988 if (getObjCContainerKind() == SemaObjC::OCK_None)3989 return nullptr;3990 3991 assert(AtEnd.isValid() && "Invalid location for '@end'");3992 3993 auto *OCD = cast<ObjCContainerDecl>(SemaRef.CurContext);3994 Decl *ClassDecl = OCD;3995 3996 bool isInterfaceDeclKind =3997 isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl)3998 || isa<ObjCProtocolDecl>(ClassDecl);3999 bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl);4000 4001 // Make synthesized accessor stub functions visible.4002 // ActOnPropertyImplDecl() creates them as not visible in case4003 // they are overridden by an explicit method that is encountered4004 // later.4005 if (auto *OID = dyn_cast<ObjCImplementationDecl>(SemaRef.CurContext)) {4006 for (auto *PropImpl : OID->property_impls()) {4007 if (auto *Getter = PropImpl->getGetterMethodDecl())4008 if (Getter->isSynthesizedAccessorStub())4009 OID->addDecl(Getter);4010 if (auto *Setter = PropImpl->getSetterMethodDecl())4011 if (Setter->isSynthesizedAccessorStub())4012 OID->addDecl(Setter);4013 }4014 }4015 4016 // FIXME: Remove these and use the ObjCContainerDecl/DeclContext.4017 llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap;4018 llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap;4019 4020 for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) {4021 ObjCMethodDecl *Method =4022 cast_or_null<ObjCMethodDecl>(allMethods[i]);4023 4024 if (!Method) continue; // Already issued a diagnostic.4025 if (Method->isInstanceMethod()) {4026 /// Check for instance method of the same name with incompatible types4027 const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()];4028 bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)4029 : false;4030 if ((isInterfaceDeclKind && PrevMethod && !match)4031 || (checkIdenticalMethods && match)) {4032 Diag(Method->getLocation(), diag::err_duplicate_method_decl)4033 << Method->getDeclName();4034 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4035 Method->setInvalidDecl();4036 } else {4037 if (PrevMethod) {4038 Method->setAsRedeclaration(PrevMethod);4039 if (!Context.getSourceManager().isInSystemHeader(4040 Method->getLocation()))4041 Diag(Method->getLocation(), diag::warn_duplicate_method_decl)4042 << Method->getDeclName();4043 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4044 }4045 InsMap[Method->getSelector()] = Method;4046 /// The following allows us to typecheck messages to "id".4047 AddInstanceMethodToGlobalPool(Method);4048 }4049 } else {4050 /// Check for class method of the same name with incompatible types4051 const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()];4052 bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod)4053 : false;4054 if ((isInterfaceDeclKind && PrevMethod && !match)4055 || (checkIdenticalMethods && match)) {4056 Diag(Method->getLocation(), diag::err_duplicate_method_decl)4057 << Method->getDeclName();4058 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4059 Method->setInvalidDecl();4060 } else {4061 if (PrevMethod) {4062 Method->setAsRedeclaration(PrevMethod);4063 if (!Context.getSourceManager().isInSystemHeader(4064 Method->getLocation()))4065 Diag(Method->getLocation(), diag::warn_duplicate_method_decl)4066 << Method->getDeclName();4067 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);4068 }4069 ClsMap[Method->getSelector()] = Method;4070 AddFactoryMethodToGlobalPool(Method);4071 }4072 }4073 }4074 if (isa<ObjCInterfaceDecl>(ClassDecl)) {4075 // Nothing to do here.4076 } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) {4077 // Categories are used to extend the class by declaring new methods.4078 // By the same token, they are also used to add new properties. No4079 // need to compare the added property to those in the class.4080 4081 if (C->IsClassExtension()) {4082 ObjCInterfaceDecl *CCPrimary = C->getClassInterface();4083 DiagnoseClassExtensionDupMethods(C, CCPrimary);4084 }4085 4086 DiagnoseCategoryDirectMembersProtocolConformance(SemaRef, C,4087 C->protocols());4088 }4089 if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) {4090 if (CDecl->getIdentifier())4091 // ProcessPropertyDecl is responsible for diagnosing conflicts with any4092 // user-defined setter/getter. It also synthesizes setter/getter methods4093 // and adds them to the DeclContext and global method pools.4094 for (auto *I : CDecl->properties())4095 ProcessPropertyDecl(I);4096 CDecl->setAtEndRange(AtEnd);4097 }4098 if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) {4099 IC->setAtEndRange(AtEnd);4100 if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) {4101 // Any property declared in a class extension might have user4102 // declared setter or getter in current class extension or one4103 // of the other class extensions. Mark them as synthesized as4104 // property will be synthesized when property with same name is4105 // seen in the @implementation.4106 for (const auto *Ext : IDecl->visible_extensions()) {4107 for (const auto *Property : Ext->instance_properties()) {4108 // Skip over properties declared @dynamic4109 if (const ObjCPropertyImplDecl *PIDecl4110 = IC->FindPropertyImplDecl(Property->getIdentifier(),4111 Property->getQueryKind()))4112 if (PIDecl->getPropertyImplementation()4113 == ObjCPropertyImplDecl::Dynamic)4114 continue;4115 4116 for (const auto *Ext : IDecl->visible_extensions()) {4117 if (ObjCMethodDecl *GetterMethod =4118 Ext->getInstanceMethod(Property->getGetterName()))4119 GetterMethod->setPropertyAccessor(true);4120 if (!Property->isReadOnly())4121 if (ObjCMethodDecl *SetterMethod4122 = Ext->getInstanceMethod(Property->getSetterName()))4123 SetterMethod->setPropertyAccessor(true);4124 }4125 }4126 }4127 ImplMethodsVsClassMethods(S, IC, IDecl);4128 AtomicPropertySetterGetterRules(IC, IDecl);4129 DiagnoseOwningPropertyGetterSynthesis(IC);4130 DiagnoseUnusedBackingIvarInAccessor(S, IC);4131 if (IDecl->hasDesignatedInitializers())4132 DiagnoseMissingDesignatedInitOverrides(IC, IDecl);4133 DiagnoseWeakIvars(SemaRef, IC);4134 DiagnoseRetainableFlexibleArrayMember(SemaRef, IDecl);4135 4136 bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>();4137 if (IDecl->getSuperClass() == nullptr) {4138 // This class has no superclass, so check that it has been marked with4139 // __attribute((objc_root_class)).4140 if (!HasRootClassAttr) {4141 SourceLocation DeclLoc(IDecl->getLocation());4142 SourceLocation SuperClassLoc(SemaRef.getLocForEndOfToken(DeclLoc));4143 Diag(DeclLoc, diag::warn_objc_root_class_missing)4144 << IDecl->getIdentifier();4145 // See if NSObject is in the current scope, and if it is, suggest4146 // adding " : NSObject " to the class declaration.4147 NamedDecl *IF = SemaRef.LookupSingleName(4148 SemaRef.TUScope, NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject),4149 DeclLoc, Sema::LookupOrdinaryName);4150 ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF);4151 if (NSObjectDecl && NSObjectDecl->getDefinition()) {4152 Diag(SuperClassLoc, diag::note_objc_needs_superclass)4153 << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject ");4154 } else {4155 Diag(SuperClassLoc, diag::note_objc_needs_superclass);4156 }4157 }4158 } else if (HasRootClassAttr) {4159 // Complain that only root classes may have this attribute.4160 Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass);4161 }4162 4163 if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) {4164 // An interface can subclass another interface with a4165 // objc_subclassing_restricted attribute when it has that attribute as4166 // well (because of interfaces imported from Swift). Therefore we have4167 // to check if we can subclass in the implementation as well.4168 if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&4169 Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {4170 Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch);4171 Diag(Super->getLocation(), diag::note_class_declared);4172 }4173 }4174 4175 if (IDecl->hasAttr<ObjCClassStubAttr>())4176 Diag(IC->getLocation(), diag::err_implementation_of_class_stub);4177 4178 if (getLangOpts().ObjCRuntime.isNonFragile()) {4179 while (IDecl->getSuperClass()) {4180 DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass());4181 IDecl = IDecl->getSuperClass();4182 }4183 }4184 }4185 SetIvarInitializers(IC);4186 } else if (ObjCCategoryImplDecl* CatImplClass =4187 dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) {4188 CatImplClass->setAtEndRange(AtEnd);4189 4190 // Find category interface decl and then check that all methods declared4191 // in this interface are implemented in the category @implementation.4192 if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) {4193 if (ObjCCategoryDecl *Cat4194 = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) {4195 ImplMethodsVsClassMethods(S, CatImplClass, Cat);4196 }4197 }4198 } else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {4199 if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) {4200 if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() &&4201 Super->hasAttr<ObjCSubclassingRestrictedAttr>()) {4202 Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch);4203 Diag(Super->getLocation(), diag::note_class_declared);4204 }4205 }4206 4207 if (IntfDecl->hasAttr<ObjCClassStubAttr>() &&4208 !IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>())4209 Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch);4210 }4211 DiagnoseVariableSizedIvars(SemaRef, OCD);4212 if (isInterfaceDeclKind) {4213 // Reject invalid vardecls.4214 for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {4215 DeclGroupRef DG = allTUVars[i].get();4216 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)4217 if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) {4218 if (!VDecl->hasExternalStorage())4219 Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass);4220 }4221 }4222 }4223 ActOnObjCContainerFinishDefinition();4224 4225 for (unsigned i = 0, e = allTUVars.size(); i != e; i++) {4226 DeclGroupRef DG = allTUVars[i].get();4227 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)4228 (*I)->setTopLevelDeclInObjCContainer();4229 SemaRef.Consumer.HandleTopLevelDeclInObjCContainer(DG);4230 }4231 4232 SemaRef.ActOnDocumentableDecl(ClassDecl);4233 return ClassDecl;4234}4235 4236/// CvtQTToAstBitMask - utility routine to produce an AST bitmask for4237/// objective-c's type qualifier from the parser version of the same info.4238static Decl::ObjCDeclQualifier4239CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) {4240 return (Decl::ObjCDeclQualifier) (unsigned) PQTVal;4241}4242 4243/// Check whether the declared result type of the given Objective-C4244/// method declaration is compatible with the method's class.4245///4246static SemaObjC::ResultTypeCompatibilityKind4247CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method,4248 ObjCInterfaceDecl *CurrentClass) {4249 QualType ResultType = Method->getReturnType();4250 4251 // If an Objective-C method inherits its related result type, then its4252 // declared result type must be compatible with its own class type. The4253 // declared result type is compatible if:4254 if (const ObjCObjectPointerType *ResultObjectType4255 = ResultType->getAs<ObjCObjectPointerType>()) {4256 // - it is id or qualified id, or4257 if (ResultObjectType->isObjCIdType() ||4258 ResultObjectType->isObjCQualifiedIdType())4259 return SemaObjC::RTC_Compatible;4260 4261 if (CurrentClass) {4262 if (ObjCInterfaceDecl *ResultClass4263 = ResultObjectType->getInterfaceDecl()) {4264 // - it is the same as the method's class type, or4265 if (declaresSameEntity(CurrentClass, ResultClass))4266 return SemaObjC::RTC_Compatible;4267 4268 // - it is a superclass of the method's class type4269 if (ResultClass->isSuperClassOf(CurrentClass))4270 return SemaObjC::RTC_Compatible;4271 }4272 } else {4273 // Any Objective-C pointer type might be acceptable for a protocol4274 // method; we just don't know.4275 return SemaObjC::RTC_Unknown;4276 }4277 }4278 4279 return SemaObjC::RTC_Incompatible;4280}4281 4282namespace {4283/// A helper class for searching for methods which a particular method4284/// overrides.4285class OverrideSearch {4286public:4287 const ObjCMethodDecl *Method;4288 llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden;4289 bool Recursive;4290 4291public:4292 OverrideSearch(Sema &S, const ObjCMethodDecl *method) : Method(method) {4293 Selector selector = method->getSelector();4294 4295 // Bypass this search if we've never seen an instance/class method4296 // with this selector before.4297 SemaObjC::GlobalMethodPool::iterator it =4298 S.ObjC().MethodPool.find(selector);4299 if (it == S.ObjC().MethodPool.end()) {4300 if (!S.getExternalSource()) return;4301 S.ObjC().ReadMethodPool(selector);4302 4303 it = S.ObjC().MethodPool.find(selector);4304 if (it == S.ObjC().MethodPool.end())4305 return;4306 }4307 const ObjCMethodList &list =4308 method->isInstanceMethod() ? it->second.first : it->second.second;4309 if (!list.getMethod()) return;4310 4311 const ObjCContainerDecl *container4312 = cast<ObjCContainerDecl>(method->getDeclContext());4313 4314 // Prevent the search from reaching this container again. This is4315 // important with categories, which override methods from the4316 // interface and each other.4317 if (const ObjCCategoryDecl *Category =4318 dyn_cast<ObjCCategoryDecl>(container)) {4319 searchFromContainer(container);4320 if (const ObjCInterfaceDecl *Interface = Category->getClassInterface())4321 searchFromContainer(Interface);4322 } else {4323 searchFromContainer(container);4324 }4325 }4326 4327 typedef decltype(Overridden)::iterator iterator;4328 iterator begin() const { return Overridden.begin(); }4329 iterator end() const { return Overridden.end(); }4330 4331private:4332 void searchFromContainer(const ObjCContainerDecl *container) {4333 if (container->isInvalidDecl()) return;4334 4335 switch (container->getDeclKind()) {4336#define OBJCCONTAINER(type, base) \4337 case Decl::type: \4338 searchFrom(cast<type##Decl>(container)); \4339 break;4340#define ABSTRACT_DECL(expansion)4341#define DECL(type, base) \4342 case Decl::type:4343#include "clang/AST/DeclNodes.inc"4344 llvm_unreachable("not an ObjC container!");4345 }4346 }4347 4348 void searchFrom(const ObjCProtocolDecl *protocol) {4349 if (!protocol->hasDefinition())4350 return;4351 4352 // A method in a protocol declaration overrides declarations from4353 // referenced ("parent") protocols.4354 search(protocol->getReferencedProtocols());4355 }4356 4357 void searchFrom(const ObjCCategoryDecl *category) {4358 // A method in a category declaration overrides declarations from4359 // the main class and from protocols the category references.4360 // The main class is handled in the constructor.4361 search(category->getReferencedProtocols());4362 }4363 4364 void searchFrom(const ObjCCategoryImplDecl *impl) {4365 // A method in a category definition that has a category4366 // declaration overrides declarations from the category4367 // declaration.4368 if (ObjCCategoryDecl *category = impl->getCategoryDecl()) {4369 search(category);4370 if (ObjCInterfaceDecl *Interface = category->getClassInterface())4371 search(Interface);4372 4373 // Otherwise it overrides declarations from the class.4374 } else if (const auto *Interface = impl->getClassInterface()) {4375 search(Interface);4376 }4377 }4378 4379 void searchFrom(const ObjCInterfaceDecl *iface) {4380 // A method in a class declaration overrides declarations from4381 if (!iface->hasDefinition())4382 return;4383 4384 // - categories,4385 for (auto *Cat : iface->known_categories())4386 search(Cat);4387 4388 // - the super class, and4389 if (ObjCInterfaceDecl *super = iface->getSuperClass())4390 search(super);4391 4392 // - any referenced protocols.4393 search(iface->getReferencedProtocols());4394 }4395 4396 void searchFrom(const ObjCImplementationDecl *impl) {4397 // A method in a class implementation overrides declarations from4398 // the class interface.4399 if (const auto *Interface = impl->getClassInterface())4400 search(Interface);4401 }4402 4403 void search(const ObjCProtocolList &protocols) {4404 for (const auto *Proto : protocols)4405 search(Proto);4406 }4407 4408 void search(const ObjCContainerDecl *container) {4409 // Check for a method in this container which matches this selector.4410 ObjCMethodDecl *meth = container->getMethod(Method->getSelector(),4411 Method->isInstanceMethod(),4412 /*AllowHidden=*/true);4413 4414 // If we find one, record it and bail out.4415 if (meth) {4416 Overridden.insert(meth);4417 return;4418 }4419 4420 // Otherwise, search for methods that a hypothetical method here4421 // would have overridden.4422 4423 // Note that we're now in a recursive case.4424 Recursive = true;4425 4426 searchFromContainer(container);4427 }4428};4429} // end anonymous namespace4430 4431void SemaObjC::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,4432 ObjCMethodDecl *overridden) {4433 if (overridden->isDirectMethod()) {4434 const auto *attr = overridden->getAttr<ObjCDirectAttr>();4435 Diag(method->getLocation(), diag::err_objc_override_direct_method);4436 Diag(attr->getLocation(), diag::note_previous_declaration);4437 } else if (method->isDirectMethod()) {4438 const auto *attr = method->getAttr<ObjCDirectAttr>();4439 Diag(attr->getLocation(), diag::err_objc_direct_on_override)4440 << isa<ObjCProtocolDecl>(overridden->getDeclContext());4441 Diag(overridden->getLocation(), diag::note_previous_declaration);4442 }4443}4444 4445void SemaObjC::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod,4446 ObjCInterfaceDecl *CurrentClass,4447 ResultTypeCompatibilityKind RTC) {4448 ASTContext &Context = getASTContext();4449 if (!ObjCMethod)4450 return;4451 auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) {4452 // Checking canonical decl works across modules.4453 return M->getClassInterface()->getCanonicalDecl() ==4454 CurrentClass->getCanonicalDecl();4455 };4456 // Search for overridden methods and merge information down from them.4457 OverrideSearch overrides(SemaRef, ObjCMethod);4458 // Keep track if the method overrides any method in the class's base classes,4459 // its protocols, or its categories' protocols; we will keep that info4460 // in the ObjCMethodDecl.4461 // For this info, a method in an implementation is not considered as4462 // overriding the same method in the interface or its categories.4463 bool hasOverriddenMethodsInBaseOrProtocol = false;4464 for (ObjCMethodDecl *overridden : overrides) {4465 if (!hasOverriddenMethodsInBaseOrProtocol) {4466 if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) ||4467 !IsMethodInCurrentClass(overridden) || overridden->isOverriding()) {4468 CheckObjCMethodDirectOverrides(ObjCMethod, overridden);4469 hasOverriddenMethodsInBaseOrProtocol = true;4470 } else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) {4471 // OverrideSearch will return as "overridden" the same method in the4472 // interface. For hasOverriddenMethodsInBaseOrProtocol, we need to4473 // check whether a category of a base class introduced a method with the4474 // same selector, after the interface method declaration.4475 // To avoid unnecessary lookups in the majority of cases, we use the4476 // extra info bits in GlobalMethodPool to check whether there were any4477 // category methods with this selector.4478 GlobalMethodPool::iterator It =4479 MethodPool.find(ObjCMethod->getSelector());4480 if (It != MethodPool.end()) {4481 ObjCMethodList &List =4482 ObjCMethod->isInstanceMethod()? It->second.first: It->second.second;4483 unsigned CategCount = List.getBits();4484 if (CategCount > 0) {4485 // If the method is in a category we'll do lookup if there were at4486 // least 2 category methods recorded, otherwise only one will do.4487 if (CategCount > 1 ||4488 !isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) {4489 OverrideSearch overrides(SemaRef, overridden);4490 for (ObjCMethodDecl *SuperOverridden : overrides) {4491 if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) ||4492 !IsMethodInCurrentClass(SuperOverridden)) {4493 CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden);4494 hasOverriddenMethodsInBaseOrProtocol = true;4495 overridden->setOverriding(true);4496 break;4497 }4498 }4499 }4500 }4501 }4502 }4503 }4504 4505 // Propagate down the 'related result type' bit from overridden methods.4506 if (RTC != SemaObjC::RTC_Incompatible && overridden->hasRelatedResultType())4507 ObjCMethod->setRelatedResultType();4508 4509 // Then merge the declarations.4510 SemaRef.mergeObjCMethodDecls(ObjCMethod, overridden);4511 4512 if (ObjCMethod->isImplicit() && overridden->isImplicit())4513 continue; // Conflicting properties are detected elsewhere.4514 4515 // Check for overriding methods4516 if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) ||4517 isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext()))4518 CheckConflictingOverridingMethod(ObjCMethod, overridden,4519 isa<ObjCProtocolDecl>(overridden->getDeclContext()));4520 4521 if (CurrentClass && overridden->getDeclContext() != CurrentClass &&4522 isa<ObjCInterfaceDecl>(overridden->getDeclContext()) &&4523 !overridden->isImplicit() /* not meant for properties */) {4524 ObjCMethodDecl::param_iterator ParamI = ObjCMethod->param_begin(),4525 E = ObjCMethod->param_end();4526 ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(),4527 PrevE = overridden->param_end();4528 for (; ParamI != E && PrevI != PrevE; ++ParamI, ++PrevI) {4529 assert(PrevI != overridden->param_end() && "Param mismatch");4530 QualType T1 = Context.getCanonicalType((*ParamI)->getType());4531 QualType T2 = Context.getCanonicalType((*PrevI)->getType());4532 // If type of argument of method in this class does not match its4533 // respective argument type in the super class method, issue warning;4534 if (!Context.typesAreCompatible(T1, T2)) {4535 Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super)4536 << T1 << T2;4537 Diag(overridden->getLocation(), diag::note_previous_declaration);4538 break;4539 }4540 }4541 }4542 }4543 4544 ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol);4545}4546 4547/// Merge type nullability from for a redeclaration of the same entity,4548/// producing the updated type of the redeclared entity.4549static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc,4550 QualType type,4551 bool usesCSKeyword,4552 SourceLocation prevLoc,4553 QualType prevType,4554 bool prevUsesCSKeyword) {4555 // Determine the nullability of both types.4556 auto nullability = type->getNullability();4557 auto prevNullability = prevType->getNullability();4558 4559 // Easy case: both have nullability.4560 if (nullability.has_value() == prevNullability.has_value()) {4561 // Neither has nullability; continue.4562 if (!nullability)4563 return type;4564 4565 // The nullabilities are equivalent; do nothing.4566 if (*nullability == *prevNullability)4567 return type;4568 4569 // Complain about mismatched nullability.4570 S.Diag(loc, diag::err_nullability_conflicting)4571 << DiagNullabilityKind(*nullability, usesCSKeyword)4572 << DiagNullabilityKind(*prevNullability, prevUsesCSKeyword);4573 return type;4574 }4575 4576 // If it's the redeclaration that has nullability, don't change anything.4577 if (nullability)4578 return type;4579 4580 // Otherwise, provide the result with the same nullability.4581 return S.Context.getAttributedType(*prevNullability, type, type);4582}4583 4584/// 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,4588 ObjCMethodDecl *method,4589 ObjCMethodDecl *prevMethod) {4590 // Merge the objc_requires_super attribute.4591 if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() &&4592 !method->hasAttr<ObjCRequiresSuperAttr>()) {4593 // merge the attribute into implementation.4594 method->addAttr(4595 ObjCRequiresSuperAttr::CreateImplicit(S.Context,4596 method->getLocation()));4597 }4598 4599 // Merge nullability of the result type.4600 QualType newReturnType4601 = mergeTypeNullabilityForRedecl(4602 S, method->getReturnTypeSourceRange().getBegin(),4603 method->getReturnType(),4604 method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,4605 prevMethod->getReturnTypeSourceRange().getBegin(),4606 prevMethod->getReturnType(),4607 prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);4608 method->setReturnType(newReturnType);4609 4610 // Handle each of the parameters.4611 unsigned numParams = method->param_size();4612 unsigned numPrevParams = prevMethod->param_size();4613 for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) {4614 ParmVarDecl *param = method->param_begin()[i];4615 ParmVarDecl *prevParam = prevMethod->param_begin()[i];4616 4617 // Merge nullability.4618 QualType newParamType4619 = mergeTypeNullabilityForRedecl(4620 S, param->getLocation(), param->getType(),4621 param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability,4622 prevParam->getLocation(), prevParam->getType(),4623 prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability);4624 param->setType(newParamType);4625 }4626}4627 4628/// Verify that the method parameters/return value have types that are supported4629/// by the x86 target.4630static void checkObjCMethodX86VectorTypes(Sema &SemaRef,4631 const ObjCMethodDecl *Method) {4632 assert(SemaRef.getASTContext().getTargetInfo().getTriple().getArch() ==4633 llvm::Triple::x86 &&4634 "x86-specific check invoked for a different target");4635 SourceLocation Loc;4636 QualType T;4637 for (const ParmVarDecl *P : Method->parameters()) {4638 if (P->getType()->isVectorType()) {4639 Loc = P->getBeginLoc();4640 T = P->getType();4641 break;4642 }4643 }4644 if (Loc.isInvalid()) {4645 if (Method->getReturnType()->isVectorType()) {4646 Loc = Method->getReturnTypeSourceRange().getBegin();4647 T = Method->getReturnType();4648 } else4649 return;4650 }4651 4652 // Vector parameters/return values are not supported by objc_msgSend on x86 in4653 // iOS < 9 and macOS < 10.11.4654 const auto &Triple = SemaRef.getASTContext().getTargetInfo().getTriple();4655 VersionTuple AcceptedInVersion;4656 if (Triple.getOS() == llvm::Triple::IOS)4657 AcceptedInVersion = VersionTuple(/*Major=*/9);4658 else if (Triple.isMacOSX())4659 AcceptedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/11);4660 else4661 return;4662 if (SemaRef.getASTContext().getTargetInfo().getPlatformMinVersion() >=4663 AcceptedInVersion)4664 return;4665 SemaRef.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}4670 4671static void mergeObjCDirectMembers(Sema &S, Decl *CD, ObjCMethodDecl *Method) {4672 if (!Method->isDirectMethod() && !Method->hasAttr<UnavailableAttr>() &&4673 CD->hasAttr<ObjCDirectMembersAttr>()) {4674 Method->addAttr(4675 ObjCDirectAttr::CreateImplicit(S.Context, Method->getLocation()));4676 }4677}4678 4679static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl,4680 ObjCMethodDecl *Method,4681 ObjCImplDecl *ImpDecl = nullptr) {4682 auto Sel = Method->getSelector();4683 bool isInstance = Method->isInstanceMethod();4684 bool diagnosed = false;4685 4686 auto diagClash = [&](const ObjCMethodDecl *IMD) {4687 if (diagnosed || IMD->isImplicit())4688 return;4689 if (Method->isDirectMethod() || IMD->isDirectMethod()) {4690 S.Diag(Method->getLocation(), diag::err_objc_direct_duplicate_decl)4691 << Method->isDirectMethod() << /* method */ 0 << IMD->isDirectMethod()4692 << Method->getDeclName();4693 S.Diag(IMD->getLocation(), diag::note_previous_declaration);4694 diagnosed = true;4695 }4696 };4697 4698 // 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.4710 4711 if (auto *IMD = IDecl->getMethod(Sel, isInstance))4712 diagClash(IMD);4713 else if (auto *Impl = IDecl->getImplementation())4714 if (Impl != ImpDecl)4715 if (auto *IMD = IDecl->getImplementation()->getMethod(Sel, isInstance))4716 diagClash(IMD);4717 4718 for (const auto *Cat : IDecl->visible_categories())4719 if (auto *IMD = Cat->getMethod(Sel, isInstance))4720 diagClash(IMD);4721 else if (auto CatImpl = Cat->getImplementation())4722 if (CatImpl != ImpDecl)4723 if (auto *IMD = Cat->getMethod(Sel, isInstance))4724 diagClash(IMD);4725}4726 4727ParmVarDecl *SemaObjC::ActOnMethodParmDeclaration(Scope *S,4728 ObjCArgInfo &ArgInfo,4729 int ParamIndex,4730 bool MethodDefinition) {4731 ASTContext &Context = getASTContext();4732 QualType ArgType;4733 TypeSourceInfo *TSI;4734 4735 if (!ArgInfo.Type) {4736 ArgType = Context.getObjCIdType();4737 TSI = nullptr;4738 } else {4739 ArgType = SemaRef.GetTypeFromParser(ArgInfo.Type, &TSI);4740 }4741 LookupResult R(SemaRef, ArgInfo.Name, ArgInfo.NameLoc,4742 Sema::LookupOrdinaryName,4743 SemaRef.forRedeclarationInCurContext());4744 SemaRef.LookupName(R, S);4745 if (R.isSingleResult()) {4746 NamedDecl *PrevDecl = R.getFoundDecl();4747 if (S->isDeclScope(PrevDecl)) {4748 Diag(ArgInfo.NameLoc,4749 (MethodDefinition ? diag::warn_method_param_redefinition4750 : diag::warn_method_param_declaration))4751 << ArgInfo.Name;4752 Diag(PrevDecl->getLocation(), diag::note_previous_declaration);4753 }4754 }4755 SourceLocation StartLoc =4756 TSI ? TSI->getTypeLoc().getBeginLoc() : ArgInfo.NameLoc;4757 4758 // Temporarily put parameter variables in the translation unit. This is what4759 // ActOnParamDeclarator does in the case of C arguments to the Objective-C4760 // method too.4761 ParmVarDecl *Param = SemaRef.CheckParameter(4762 Context.getTranslationUnitDecl(), StartLoc, ArgInfo.NameLoc, ArgInfo.Name,4763 ArgType, TSI, SC_None);4764 Param->setObjCMethodScopeInfo(ParamIndex);4765 Param->setObjCDeclQualifier(4766 CvtQTToAstBitMask(ArgInfo.DeclSpec.getObjCDeclQualifier()));4767 4768 // Apply the attributes to the parameter.4769 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, ArgInfo.ArgAttrs);4770 SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param);4771 if (Param->hasAttr<BlocksAttr>()) {4772 Diag(Param->getLocation(), diag::err_block_on_nonlocal);4773 Param->setInvalidDecl();4774 }4775 4776 S->AddDecl(Param);4777 SemaRef.IdResolver.AddDecl(Param);4778 return Param;4779}4780 4781Decl *SemaObjC::ActOnMethodDeclaration(4782 Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc,4783 tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType,4784 ArrayRef<SourceLocation> SelectorLocs, Selector Sel,4785 // optional arguments. The number of types/arguments is obtained4786 // from the Sel.getNumArgs().4787 ParmVarDecl **ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo,4788 unsigned CNumArgs, // c-style args4789 const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind,4790 bool isVariadic, bool MethodDefinition) {4791 ASTContext &Context = getASTContext();4792 // Make sure we can establish a context for the method.4793 if (!SemaRef.CurContext->isObjCContainer()) {4794 Diag(MethodLoc, diag::err_missing_method_context);4795 return nullptr;4796 }4797 4798 Decl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext);4799 QualType resultDeclType;4800 4801 bool HasRelatedResultType = false;4802 TypeSourceInfo *ReturnTInfo = nullptr;4803 if (ReturnType) {4804 resultDeclType = SemaRef.GetTypeFromParser(ReturnType, &ReturnTInfo);4805 4806 if (SemaRef.CheckFunctionReturnType(resultDeclType, MethodLoc))4807 return nullptr;4808 4809 QualType bareResultType = resultDeclType;4810 (void)AttributedType::stripOuterNullability(bareResultType);4811 HasRelatedResultType = (bareResultType == Context.getObjCInstanceType());4812 } else { // get the type for "id".4813 resultDeclType = Context.getObjCIdType();4814 Diag(MethodLoc, diag::warn_missing_method_return_type)4815 << FixItHint::CreateInsertion(SelectorLocs.front(), "(id)");4816 }4817 4818 ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create(4819 Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo,4820 SemaRef.CurContext, MethodType == tok::minus, isVariadic,4821 /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false,4822 /*isImplicitlyDeclared=*/false, /*isDefined=*/false,4823 MethodDeclKind == tok::objc_optional4824 ? ObjCImplementationControl::Optional4825 : ObjCImplementationControl::Required,4826 HasRelatedResultType);4827 4828 SmallVector<ParmVarDecl*, 16> Params;4829 for (unsigned I = 0; I < Sel.getNumArgs(); ++I) {4830 ParmVarDecl *Param = ArgInfo[I];4831 Param->setDeclContext(ObjCMethod);4832 SemaRef.ProcessAPINotes(Param);4833 Params.push_back(Param);4834 }4835 4836 for (unsigned i = 0, e = CNumArgs; i != e; ++i) {4837 ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param);4838 QualType ArgType = Param->getType();4839 if (ArgType.isNull())4840 ArgType = Context.getObjCIdType();4841 else4842 // Perform the default array/function conversions (C99 6.7.5.3p[7,8]).4843 ArgType = Context.getAdjustedParameterType(ArgType);4844 4845 Param->setDeclContext(ObjCMethod);4846 Params.push_back(Param);4847 }4848 4849 ObjCMethod->setMethodParams(Context, Params, SelectorLocs);4850 ObjCMethod->setObjCDeclQualifier(4851 CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier()));4852 4853 SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, ObjCMethod, AttrList);4854 SemaRef.AddPragmaAttributes(SemaRef.TUScope, ObjCMethod);4855 SemaRef.ProcessAPINotes(ObjCMethod);4856 4857 // Add the method now.4858 const ObjCMethodDecl *PrevMethod = nullptr;4859 if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) {4860 if (MethodType == tok::minus) {4861 PrevMethod = ImpDecl->getInstanceMethod(Sel);4862 ImpDecl->addInstanceMethod(ObjCMethod);4863 } else {4864 PrevMethod = ImpDecl->getClassMethod(Sel);4865 ImpDecl->addClassMethod(ObjCMethod);4866 }4867 4868 // If this method overrides a previous @synthesize declaration,4869 // register it with the property. Linear search through all4870 // properties here, because the autosynthesized stub hasn't been4871 // made visible yet, so it can be overridden by a later4872 // user-specified implementation.4873 for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) {4874 if (auto *Setter = PropertyImpl->getSetterMethodDecl())4875 if (Setter->getSelector() == Sel &&4876 Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {4877 assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected");4878 PropertyImpl->setSetterMethodDecl(ObjCMethod);4879 }4880 if (auto *Getter = PropertyImpl->getGetterMethodDecl())4881 if (Getter->getSelector() == Sel &&4882 Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) {4883 assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected");4884 PropertyImpl->setGetterMethodDecl(ObjCMethod);4885 break;4886 }4887 }4888 4889 // A method is either tagged direct explicitly, or inherits it from its4890 // canonical declaration.4891 //4892 // We have to do the merge upfront and not in mergeInterfaceMethodToImpl()4893 // because IDecl->lookupMethod() returns more possible matches than just4894 // the canonical declaration.4895 if (!ObjCMethod->isDirectMethod()) {4896 const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl();4897 if (CanonicalMD->isDirectMethod()) {4898 const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>();4899 ObjCMethod->addAttr(4900 ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));4901 }4902 }4903 4904 // Merge information from the @interface declaration into the4905 // @implementation.4906 if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) {4907 if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(),4908 ObjCMethod->isInstanceMethod())) {4909 mergeInterfaceMethodToImpl(SemaRef, ObjCMethod, IMD);4910 4911 // The Idecl->lookupMethod() above will find declarations for ObjCMethod4912 // in one of these places:4913 //4914 // (1) the canonical declaration in an @interface container paired4915 // with the ImplDecl,4916 // (2) non canonical declarations in @interface not paired with the4917 // ImplDecl for the same Class,4918 // (3) any superclass container.4919 //4920 // Direct methods only allow for canonical declarations in the matching4921 // container (case 1).4922 //4923 // Direct methods overriding a superclass declaration (case 3) is4924 // handled during overrides checks in CheckObjCMethodOverrides().4925 //4926 // We deal with same-class container mismatches (Case 2) here.4927 if (IDecl == IMD->getClassInterface()) {4928 auto diagContainerMismatch = [&] {4929 int decl = 0, impl = 0;4930 4931 if (auto *Cat = dyn_cast<ObjCCategoryDecl>(IMD->getDeclContext()))4932 decl = Cat->IsClassExtension() ? 1 : 2;4933 4934 if (isa<ObjCCategoryImplDecl>(ImpDecl))4935 impl = 1 + (decl != 0);4936 4937 Diag(ObjCMethod->getLocation(),4938 diag::err_objc_direct_impl_decl_mismatch)4939 << decl << impl;4940 Diag(IMD->getLocation(), diag::note_previous_declaration);4941 };4942 4943 if (ObjCMethod->isDirectMethod()) {4944 const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>();4945 if (ObjCMethod->getCanonicalDecl() != IMD) {4946 diagContainerMismatch();4947 } else if (!IMD->isDirectMethod()) {4948 Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl);4949 Diag(IMD->getLocation(), diag::note_previous_declaration);4950 }4951 } else if (IMD->isDirectMethod()) {4952 const auto *attr = IMD->getAttr<ObjCDirectAttr>();4953 if (ObjCMethod->getCanonicalDecl() != IMD) {4954 diagContainerMismatch();4955 } else {4956 ObjCMethod->addAttr(4957 ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));4958 }4959 }4960 }4961 4962 // Warn about defining -dealloc in a category.4963 if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() &&4964 ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) {4965 Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category)4966 << ObjCMethod->getDeclName();4967 }4968 } else {4969 mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);4970 checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod, ImpDecl);4971 }4972 4973 // Warn if a method declared in a protocol to which a category or4974 // extension conforms is non-escaping and the implementation's method is4975 // escaping.4976 for (auto *C : IDecl->visible_categories())4977 for (auto &P : C->protocols())4978 if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(),4979 ObjCMethod->isInstanceMethod())) {4980 assert(ObjCMethod->parameters().size() ==4981 IMD->parameters().size() &&4982 "Methods have different number of parameters");4983 auto OI = IMD->param_begin(), OE = IMD->param_end();4984 auto NI = ObjCMethod->param_begin();4985 for (; OI != OE; ++OI, ++NI)4986 diagnoseNoescape(*NI, *OI, C, P, SemaRef);4987 }4988 }4989 } else {4990 if (!isa<ObjCProtocolDecl>(ClassDecl)) {4991 mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod);4992 4993 ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl);4994 if (!IDecl)4995 IDecl = cast<ObjCCategoryDecl>(ClassDecl)->getClassInterface();4996 // For valid code, we should always know the primary interface4997 // declaration by now, however for invalid code we'll keep parsing4998 // but we won't find the primary interface and IDecl will be nil.4999 if (IDecl)5000 checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod);5001 }5002 5003 cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod);5004 }5005 5006 if (PrevMethod) {5007 // You can never have two method definitions with the same name.5008 Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl)5009 << ObjCMethod->getDeclName();5010 Diag(PrevMethod->getLocation(), diag::note_previous_declaration);5011 ObjCMethod->setInvalidDecl();5012 return ObjCMethod;5013 }5014 5015 // If this Objective-C method does not have a related result type, but we5016 // are allowed to infer related result types, try to do so based on the5017 // method family.5018 ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl);5019 if (!CurrentClass) {5020 if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl))5021 CurrentClass = Cat->getClassInterface();5022 else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl))5023 CurrentClass = Impl->getClassInterface();5024 else if (ObjCCategoryImplDecl *CatImpl5025 = dyn_cast<ObjCCategoryImplDecl>(ClassDecl))5026 CurrentClass = CatImpl->getClassInterface();5027 }5028 5029 ResultTypeCompatibilityKind RTC =5030 CheckRelatedResultTypeCompatibility(SemaRef, ObjCMethod, CurrentClass);5031 5032 CheckObjCMethodOverrides(ObjCMethod, CurrentClass, RTC);5033 5034 bool ARCError = false;5035 if (getLangOpts().ObjCAutoRefCount)5036 ARCError = CheckARCMethodDecl(ObjCMethod);5037 5038 // Infer the related result type when possible.5039 if (!ARCError && RTC == SemaObjC::RTC_Compatible &&5040 !ObjCMethod->hasRelatedResultType() &&5041 getLangOpts().ObjCInferRelatedResultType) {5042 bool InferRelatedResultType = false;5043 switch (ObjCMethod->getMethodFamily()) {5044 case OMF_None:5045 case OMF_copy:5046 case OMF_dealloc:5047 case OMF_finalize:5048 case OMF_mutableCopy:5049 case OMF_release:5050 case OMF_retainCount:5051 case OMF_initialize:5052 case OMF_performSelector:5053 break;5054 5055 case OMF_alloc:5056 case OMF_new:5057 InferRelatedResultType = ObjCMethod->isClassMethod();5058 break;5059 5060 case OMF_init:5061 case OMF_autorelease:5062 case OMF_retain:5063 case OMF_self:5064 InferRelatedResultType = ObjCMethod->isInstanceMethod();5065 break;5066 }5067 5068 if (InferRelatedResultType &&5069 !ObjCMethod->getReturnType()->isObjCIndependentClassType())5070 ObjCMethod->setRelatedResultType();5071 }5072 5073 if (MethodDefinition &&5074 Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86)5075 checkObjCMethodX86VectorTypes(SemaRef, ObjCMethod);5076 5077 // + load method cannot have availability attributes. It get called on5078 // startup, so it has to have the availability of the deployment target.5079 if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) {5080 if (ObjCMethod->isClassMethod() &&5081 ObjCMethod->getSelector().getAsString() == "load") {5082 Diag(attr->getLocation(), diag::warn_availability_on_static_initializer)5083 << 0;5084 ObjCMethod->dropAttr<AvailabilityAttr>();5085 }5086 }5087 5088 // Insert the invisible arguments, self and _cmd!5089 ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface());5090 5091 SemaRef.ActOnDocumentableDecl(ObjCMethod);5092 5093 return ObjCMethod;5094}5095 5096bool SemaObjC::CheckObjCDeclScope(Decl *D) {5097 // Following is also an error. But it is caused by a missing @end5098 // and diagnostic is issued elsewhere.5099 if (isa<ObjCContainerDecl>(SemaRef.CurContext->getRedeclContext()))5100 return false;5101 5102 // If we switched context to translation unit while we are still lexically in5103 // an objc container, it means the parser missed emitting an error.5104 if (isa<TranslationUnitDecl>(5105 SemaRef.getCurLexicalContext()->getRedeclContext()))5106 return false;5107 5108 Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope);5109 D->setInvalidDecl();5110 5111 return true;5112}5113 5114/// Called whenever \@defs(ClassName) is encountered in the source. Inserts the5115/// instance variables of ClassName into Decls.5116void SemaObjC::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart,5117 const IdentifierInfo *ClassName,5118 SmallVectorImpl<Decl *> &Decls) {5119 ASTContext &Context = getASTContext();5120 // Check that ClassName is a valid class5121 ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart);5122 if (!Class) {5123 Diag(DeclStart, diag::err_undef_interface) << ClassName;5124 return;5125 }5126 if (getLangOpts().ObjCRuntime.isNonFragile()) {5127 Diag(DeclStart, diag::err_atdef_nonfragile_interface);5128 return;5129 }5130 5131 // Collect the instance variables5132 SmallVector<const ObjCIvarDecl*, 32> Ivars;5133 Context.DeepCollectObjCIvars(Class, true, Ivars);5134 // For each ivar, create a fresh ObjCAtDefsFieldDecl.5135 for (unsigned i = 0; i < Ivars.size(); i++) {5136 const FieldDecl* ID = Ivars[i];5137 RecordDecl *Record = dyn_cast<RecordDecl>(TagD);5138 Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record,5139 /*FIXME: StartL=*/ID->getLocation(),5140 ID->getLocation(),5141 ID->getIdentifier(), ID->getType(),5142 ID->getBitWidth());5143 Decls.push_back(FD);5144 }5145 5146 // Introduce all of these fields into the appropriate scope.5147 for (SmallVectorImpl<Decl*>::iterator D = Decls.begin();5148 D != Decls.end(); ++D) {5149 FieldDecl *FD = cast<FieldDecl>(*D);5150 if (getLangOpts().CPlusPlus)5151 SemaRef.PushOnScopeChains(FD, S);5152 else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD))5153 Record->addDecl(FD);5154 }5155}5156 5157/// Build a type-check a new Objective-C exception variable declaration.5158VarDecl *SemaObjC::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T,5159 SourceLocation StartLoc,5160 SourceLocation IdLoc,5161 const IdentifierInfo *Id,5162 bool Invalid) {5163 ASTContext &Context = getASTContext();5164 // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage5165 // duration shall not be qualified by an address-space qualifier."5166 // Since all parameters have automatic store duration, they can not have5167 // an address space.5168 if (T.getAddressSpace() != LangAS::Default) {5169 Diag(IdLoc, diag::err_arg_with_address_space);5170 Invalid = true;5171 }5172 5173 // An @catch parameter must be an unqualified object pointer type;5174 // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"?5175 if (Invalid) {5176 // Don't do any further checking.5177 } else if (T->isDependentType()) {5178 // Okay: we don't know what this type will instantiate to.5179 } else if (T->isObjCQualifiedIdType()) {5180 Invalid = true;5181 Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm);5182 } else if (T->isObjCIdType()) {5183 // Okay: we don't know what this type will instantiate to.5184 } else if (!T->isObjCObjectPointerType()) {5185 Invalid = true;5186 Diag(IdLoc, diag::err_catch_param_not_objc_type);5187 } else if (!T->castAs<ObjCObjectPointerType>()->getInterfaceType()) {5188 Invalid = true;5189 Diag(IdLoc, diag::err_catch_param_not_objc_type);5190 }5191 5192 VarDecl *New = VarDecl::Create(Context, SemaRef.CurContext, StartLoc, IdLoc,5193 Id, T, TInfo, SC_None);5194 New->setExceptionVariable(true);5195 5196 // In ARC, infer 'retaining' for variables of retainable type.5197 if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New))5198 Invalid = true;5199 5200 if (Invalid)5201 New->setInvalidDecl();5202 return New;5203}5204 5205Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) {5206 const DeclSpec &DS = D.getDeclSpec();5207 5208 // We allow the "register" storage class on exception variables because5209 // GCC did, but we drop it completely. Any other storage class is an error.5210 if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {5211 Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm)5212 << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc()));5213 } else if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) {5214 Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm)5215 << DeclSpec::getSpecifierName(SCS);5216 }5217 if (DS.isInlineSpecified())5218 Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function)5219 << getLangOpts().CPlusPlus17;5220 if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec())5221 Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),5222 diag::err_invalid_thread)5223 << DeclSpec::getSpecifierName(TSCS);5224 D.getMutableDeclSpec().ClearStorageClassSpecs();5225 5226 SemaRef.DiagnoseFunctionSpecifiers(D.getDeclSpec());5227 5228 // Check that there are no default arguments inside the type of this5229 // exception object (C++ only).5230 if (getLangOpts().CPlusPlus)5231 SemaRef.CheckExtraCXXDefaultArguments(D);5232 5233 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);5234 QualType ExceptionType = TInfo->getType();5235 5236 VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType,5237 D.getSourceRange().getBegin(),5238 D.getIdentifierLoc(),5239 D.getIdentifier(),5240 D.isInvalidType());5241 5242 // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1).5243 if (D.getCXXScopeSpec().isSet()) {5244 Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm)5245 << D.getCXXScopeSpec().getRange();5246 New->setInvalidDecl();5247 }5248 5249 // Add the parameter declaration into this scope.5250 S->AddDecl(New);5251 if (D.getIdentifier())5252 SemaRef.IdResolver.AddDecl(New);5253 5254 SemaRef.ProcessDeclAttributes(S, New, D);5255 5256 if (New->hasAttr<BlocksAttr>())5257 Diag(New->getLocation(), diag::err_block_on_nonlocal);5258 return New;5259}5260 5261/// CollectIvarsToConstructOrDestruct - Collect those ivars which require5262/// initialization.5263void SemaObjC::CollectIvarsToConstructOrDestruct(5264 ObjCInterfaceDecl *OI, SmallVectorImpl<ObjCIvarDecl *> &Ivars) {5265 ASTContext &Context = getASTContext();5266 for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv;5267 Iv= Iv->getNextIvar()) {5268 QualType QT = Context.getBaseElementType(Iv->getType());5269 if (QT->isRecordType())5270 Ivars.push_back(Iv);5271 }5272}5273 5274void SemaObjC::DiagnoseUseOfUnimplementedSelectors() {5275 ASTContext &Context = getASTContext();5276 // Load referenced selectors from the external source.5277 if (SemaRef.ExternalSource) {5278 SmallVector<std::pair<Selector, SourceLocation>, 4> Sels;5279 SemaRef.ExternalSource->ReadReferencedSelectors(Sels);5280 for (unsigned I = 0, N = Sels.size(); I != N; ++I)5281 ReferencedSelectors[Sels[I].first] = Sels[I].second;5282 }5283 5284 // Warning will be issued only when selector table is5285 // generated (which means there is at lease one implementation5286 // in the TU). This is to match gcc's behavior.5287 if (ReferencedSelectors.empty() ||5288 !Context.AnyObjCImplementation())5289 return;5290 for (auto &SelectorAndLocation : ReferencedSelectors) {5291 Selector Sel = SelectorAndLocation.first;5292 SourceLocation Loc = SelectorAndLocation.second;5293 if (!LookupImplementedMethodInGlobalPool(Sel))5294 Diag(Loc, diag::warn_unimplemented_selector) << Sel;5295 }5296}5297 5298ObjCIvarDecl *5299SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method,5300 const ObjCPropertyDecl *&PDecl) const {5301 if (Method->isClassMethod())5302 return nullptr;5303 const ObjCInterfaceDecl *IDecl = Method->getClassInterface();5304 if (!IDecl)5305 return nullptr;5306 Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true,5307 /*shallowCategoryLookup=*/false,5308 /*followSuper=*/false);5309 if (!Method || !Method->isPropertyAccessor())5310 return nullptr;5311 if ((PDecl = Method->findPropertyDecl()))5312 if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) {5313 // property backing ivar must belong to property's class5314 // or be a private ivar in class's implementation.5315 // FIXME. fix the const-ness issue.5316 IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable(5317 IV->getIdentifier());5318 return IV;5319 }5320 return nullptr;5321}5322 5323namespace {5324/// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property5325/// accessor references the backing ivar.5326class UnusedBackingIvarChecker : public DynamicRecursiveASTVisitor {5327public:5328 Sema &S;5329 const ObjCMethodDecl *Method;5330 const ObjCIvarDecl *IvarD;5331 bool AccessedIvar;5332 bool InvokedSelfMethod;5333 5334 UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method,5335 const ObjCIvarDecl *IvarD)5336 : S(S), Method(Method), IvarD(IvarD), AccessedIvar(false),5337 InvokedSelfMethod(false) {5338 assert(IvarD);5339 }5340 5341 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) override {5342 if (E->getDecl() == IvarD) {5343 AccessedIvar = true;5344 return false;5345 }5346 return true;5347 }5348 5349 bool VisitObjCMessageExpr(ObjCMessageExpr *E) override {5350 if (E->getReceiverKind() == ObjCMessageExpr::Instance &&5351 S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) {5352 InvokedSelfMethod = true;5353 }5354 return true;5355 }5356};5357} // end anonymous namespace5358 5359void SemaObjC::DiagnoseUnusedBackingIvarInAccessor(5360 Scope *S, const ObjCImplementationDecl *ImplD) {5361 if (S->hasUnrecoverableErrorOccurred())5362 return;5363 5364 for (const auto *CurMethod : ImplD->instance_methods()) {5365 unsigned DIAG = diag::warn_unused_property_backing_ivar;5366 SourceLocation Loc = CurMethod->getLocation();5367 if (getDiagnostics().isIgnored(DIAG, Loc))5368 continue;5369 5370 const ObjCPropertyDecl *PDecl;5371 const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl);5372 if (!IV)5373 continue;5374 5375 if (CurMethod->isSynthesizedAccessorStub())5376 continue;5377 5378 UnusedBackingIvarChecker Checker(SemaRef, CurMethod, IV);5379 Checker.TraverseStmt(CurMethod->getBody());5380 if (Checker.AccessedIvar)5381 continue;5382 5383 // Do not issue this warning if backing ivar is used somewhere and accessor5384 // implementation makes a self call. This is to prevent false positive in5385 // cases where the ivar is accessed by another method that the accessor5386 // delegates to.5387 if (!IV->isReferenced() || !Checker.InvokedSelfMethod) {5388 Diag(Loc, DIAG) << IV;5389 Diag(PDecl->getLocation(), diag::note_property_declare);5390 }5391 }5392}5393 5394QualType SemaObjC::AdjustParameterTypeForObjCAutoRefCount(5395 QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo) {5396 ASTContext &Context = getASTContext();5397 // In ARC, infer a lifetime qualifier for appropriate parameter types.5398 if (!getLangOpts().ObjCAutoRefCount ||5399 T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType())5400 return T;5401 5402 Qualifiers::ObjCLifetime Lifetime;5403 5404 // Special cases for arrays:5405 // - if it's const, use __unsafe_unretained5406 // - otherwise, it's an error5407 if (T->isArrayType()) {5408 if (!T.isConstQualified()) {5409 if (SemaRef.DelayedDiagnostics.shouldDelayDiagnostics())5410 SemaRef.DelayedDiagnostics.add(5411 sema::DelayedDiagnostic::makeForbiddenType(5412 NameLoc, diag::err_arc_array_param_no_ownership, T, false));5413 else5414 Diag(NameLoc, diag::err_arc_array_param_no_ownership)5415 << TSInfo->getTypeLoc().getSourceRange();5416 }5417 Lifetime = Qualifiers::OCL_ExplicitNone;5418 } else {5419 Lifetime = T->getObjCARCImplicitLifetime();5420 }5421 T = Context.getLifetimeQualifiedType(T, Lifetime);5422 5423 return T;5424}5425 5426ObjCInterfaceDecl *SemaObjC::getObjCInterfaceDecl(const IdentifierInfo *&Id,5427 SourceLocation IdLoc,5428 bool DoTypoCorrection) {5429 // The third "scope" argument is 0 since we aren't enabling lazy built-in5430 // creation from this context.5431 NamedDecl *IDecl = SemaRef.LookupSingleName(SemaRef.TUScope, Id, IdLoc,5432 Sema::LookupOrdinaryName);5433 5434 if (!IDecl && DoTypoCorrection) {5435 // Perform typo correction at the given location, but only if we5436 // find an Objective-C class name.5437 DeclFilterCCC<ObjCInterfaceDecl> CCC{};5438 if (TypoCorrection C = SemaRef.CorrectTypo(5439 DeclarationNameInfo(Id, IdLoc), Sema::LookupOrdinaryName,5440 SemaRef.TUScope, nullptr, CCC, CorrectTypoKind::ErrorRecovery)) {5441 SemaRef.diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id);5442 IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>();5443 Id = IDecl->getIdentifier();5444 }5445 }5446 ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);5447 // This routine must always return a class definition, if any.5448 if (Def && Def->getDefinition())5449 Def = Def->getDefinition();5450 return Def;5451}5452 5453bool SemaObjC::inferObjCARCLifetime(ValueDecl *decl) {5454 ASTContext &Context = getASTContext();5455 QualType type = decl->getType();5456 Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime();5457 if (lifetime == Qualifiers::OCL_Autoreleasing) {5458 // Various kinds of declaration aren't allowed to be __autoreleasing.5459 unsigned kind = -1U;5460 if (VarDecl *var = dyn_cast<VarDecl>(decl)) {5461 if (var->hasAttr<BlocksAttr>())5462 kind = 0; // __block5463 else if (!var->hasLocalStorage())5464 kind = 1; // global5465 } else if (isa<ObjCIvarDecl>(decl)) {5466 kind = 3; // ivar5467 } else if (isa<FieldDecl>(decl)) {5468 kind = 2; // field5469 }5470 5471 if (kind != -1U) {5472 Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind;5473 }5474 } else if (lifetime == Qualifiers::OCL_None) {5475 // Try to infer lifetime.5476 if (!type->isObjCLifetimeType())5477 return false;5478 5479 lifetime = type->getObjCARCImplicitLifetime();5480 type = Context.getLifetimeQualifiedType(type, lifetime);5481 decl->setType(type);5482 }5483 5484 if (VarDecl *var = dyn_cast<VarDecl>(decl)) {5485 // Thread-local variables cannot have lifetime.5486 if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone &&5487 var->getTLSKind()) {5488 Diag(var->getLocation(), diag::err_arc_thread_ownership)5489 << var->getType();5490 return true;5491 }5492 }5493 5494 return false;5495}5496 5497ObjCContainerDecl *SemaObjC::getObjCDeclContext() const {5498 return (dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext));5499}5500 5501void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) {5502 if (!getLangOpts().CPlusPlus)5503 return;5504 if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) {5505 ASTContext &Context = getASTContext();5506 SmallVector<ObjCIvarDecl *, 8> ivars;5507 CollectIvarsToConstructOrDestruct(OID, ivars);5508 if (ivars.empty())5509 return;5510 SmallVector<CXXCtorInitializer *, 32> AllToInit;5511 for (unsigned i = 0; i < ivars.size(); i++) {5512 FieldDecl *Field = ivars[i];5513 if (Field->isInvalidDecl())5514 continue;5515 5516 CXXCtorInitializer *Member;5517 InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field);5518 InitializationKind InitKind =5519 InitializationKind::CreateDefault(ObjCImplementation->getLocation());5520 5521 InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, {});5522 ExprResult MemberInit =5523 InitSeq.Perform(SemaRef, InitEntity, InitKind, {});5524 MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit);5525 // Note, MemberInit could actually come back empty if no initialization5526 // is required (e.g., because it would call a trivial default constructor)5527 if (!MemberInit.get() || MemberInit.isInvalid())5528 continue;5529 5530 Member = new (Context)5531 CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(),5532 MemberInit.getAs<Expr>(), SourceLocation());5533 AllToInit.push_back(Member);5534 5535 // Be sure that the destructor is accessible and is marked as referenced.5536 if (auto *RD = Context.getBaseElementType(Field->getType())5537 ->getAsCXXRecordDecl()) {5538 if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) {5539 SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor);5540 SemaRef.CheckDestructorAccess(5541 Field->getLocation(), Destructor,5542 PDiag(diag::err_access_dtor_ivar)5543 << Context.getBaseElementType(Field->getType()));5544 }5545 }5546 }5547 ObjCImplementation->setIvarInitializers(Context, AllToInit.data(),5548 AllToInit.size());5549 }5550}5551 5552/// TranslateIvarVisibility - Translate visibility from a token ID to an5553/// AST enum value.5554static ObjCIvarDecl::AccessControl5555TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) {5556 switch (ivarVisibility) {5557 default:5558 llvm_unreachable("Unknown visitibility kind");5559 case tok::objc_private:5560 return ObjCIvarDecl::Private;5561 case tok::objc_public:5562 return ObjCIvarDecl::Public;5563 case tok::objc_protected:5564 return ObjCIvarDecl::Protected;5565 case tok::objc_package:5566 return ObjCIvarDecl::Package;5567 }5568}5569 5570/// 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,5573 Expr *BitWidth, tok::ObjCKeywordKind Visibility) {5574 5575 const IdentifierInfo *II = D.getIdentifier();5576 SourceLocation Loc = DeclStart;5577 if (II)5578 Loc = D.getIdentifierLoc();5579 5580 // FIXME: Unnamed fields can be handled in various different ways, for5581 // example, unnamed unions inject all members into the struct namespace!5582 5583 TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D);5584 QualType T = TInfo->getType();5585 ASTContext &Context = getASTContext();5586 if (Context.getLangOpts().PointerAuthObjcInterfaceSel &&5587 !T.getPointerAuth()) {5588 if (Context.isObjCSelType(T.getUnqualifiedType())) {5589 if (auto PAQ = Context.getObjCMemberSelTypePtrAuth())5590 T = Context.getPointerAuthType(T, PAQ);5591 }5592 }5593 5594 if (BitWidth) {5595 // 6.7.2.1p3, 6.7.2.1p45596 BitWidth =5597 SemaRef.VerifyBitField(Loc, II, T, /*IsMsStruct*/ false, BitWidth)5598 .get();5599 if (!BitWidth)5600 D.setInvalidType();5601 } else {5602 // Not a bitfield.5603 5604 // validate II.5605 }5606 if (T->isReferenceType()) {5607 Diag(Loc, diag::err_ivar_reference_type);5608 D.setInvalidType();5609 }5610 // C99 6.7.2.1p8: A member of a structure or union may have any type other5611 // than a variably modified type.5612 else if (T->isVariablyModifiedType()) {5613 if (!SemaRef.tryToFixVariablyModifiedVarType(5614 TInfo, T, Loc, diag::err_typecheck_ivar_variable_size))5615 D.setInvalidType();5616 }5617 5618 // Get the visibility (access control) for this ivar.5619 ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword5620 ? TranslateIvarVisibility(Visibility)5621 : ObjCIvarDecl::None;5622 // Must set ivar's DeclContext to its enclosing interface.5623 ObjCContainerDecl *EnclosingDecl =5624 cast<ObjCContainerDecl>(SemaRef.CurContext);5625 if (!EnclosingDecl || EnclosingDecl->isInvalidDecl())5626 return nullptr;5627 ObjCContainerDecl *EnclosingContext;5628 if (ObjCImplementationDecl *IMPDecl =5629 dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) {5630 if (getLangOpts().ObjCRuntime.isFragile()) {5631 // Case of ivar declared in an implementation. Context is that of its5632 // class.5633 EnclosingContext = IMPDecl->getClassInterface();5634 assert(EnclosingContext && "Implementation has no class interface!");5635 } else5636 EnclosingContext = EnclosingDecl;5637 } else {5638 if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) {5639 if (getLangOpts().ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) {5640 Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension();5641 return nullptr;5642 }5643 }5644 EnclosingContext = EnclosingDecl;5645 }5646 5647 // Construct the decl.5648 ObjCIvarDecl *NewID =5649 ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc,5650 II, T, TInfo, ac, BitWidth);5651 5652 if (T->containsErrors())5653 NewID->setInvalidDecl();5654 5655 if (II) {5656 NamedDecl *PrevDecl =5657 SemaRef.LookupSingleName(S, II, Loc, Sema::LookupMemberName,5658 RedeclarationKind::ForVisibleRedeclaration);5659 if (PrevDecl && SemaRef.isDeclInScope(PrevDecl, EnclosingContext, S) &&5660 !isa<TagDecl>(PrevDecl)) {5661 Diag(Loc, diag::err_duplicate_member) << II;5662 Diag(PrevDecl->getLocation(), diag::note_previous_declaration);5663 NewID->setInvalidDecl();5664 }5665 }5666 5667 // Process attributes attached to the ivar.5668 SemaRef.ProcessDeclAttributes(S, NewID, D);5669 5670 if (D.isInvalidType())5671 NewID->setInvalidDecl();5672 5673 // In ARC, infer 'retaining' for ivars of retainable type.5674 if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID))5675 NewID->setInvalidDecl();5676 5677 if (D.getDeclSpec().isModulePrivateSpecified())5678 NewID->setModulePrivate();5679 5680 if (II) {5681 // FIXME: When interfaces are DeclContexts, we'll need to add5682 // these to the interface.5683 S->AddDecl(NewID);5684 SemaRef.IdResolver.AddDecl(NewID);5685 }5686 5687 if (getLangOpts().ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() &&5688 isa<ObjCInterfaceDecl>(EnclosingDecl))5689 Diag(Loc, diag::warn_ivars_in_interface);5690 5691 return NewID;5692}5693