10b57cec5SDimitry Andric //===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements semantic analysis for Objective C declarations. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "TypeLocBuilder.h" 140b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h" 150b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 160b57cec5SDimitry Andric #include "clang/AST/ASTMutationListener.h" 170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h" 180b57cec5SDimitry Andric #include "clang/AST/Expr.h" 190b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h" 200b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 210b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h" 225ffd83dbSDimitry Andric #include "clang/Basic/TargetInfo.h" 230b57cec5SDimitry Andric #include "clang/Sema/DeclSpec.h" 24*0fca6ea1SDimitry Andric #include "clang/Sema/DelayedDiagnostic.h" 25*0fca6ea1SDimitry Andric #include "clang/Sema/Initialization.h" 260b57cec5SDimitry Andric #include "clang/Sema/Lookup.h" 270b57cec5SDimitry Andric #include "clang/Sema/Scope.h" 280b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h" 290b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h" 30*0fca6ea1SDimitry Andric #include "clang/Sema/SemaObjC.h" 310b57cec5SDimitry Andric #include "llvm/ADT/DenseMap.h" 320b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric using namespace clang; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric /// Check whether the given method, which must be in the 'init' 370b57cec5SDimitry Andric /// family, is a valid member of that family. 380b57cec5SDimitry Andric /// 390b57cec5SDimitry Andric /// \param receiverTypeIfCall - if null, check this as if declaring it; 400b57cec5SDimitry Andric /// if non-null, check this as if making a call to it with the given 410b57cec5SDimitry Andric /// receiver type 420b57cec5SDimitry Andric /// 430b57cec5SDimitry Andric /// \return true to indicate that there was an error and appropriate 440b57cec5SDimitry Andric /// actions were taken 45*0fca6ea1SDimitry Andric bool SemaObjC::checkInitMethod(ObjCMethodDecl *method, 460b57cec5SDimitry Andric QualType receiverTypeIfCall) { 47*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 480b57cec5SDimitry Andric if (method->isInvalidDecl()) return true; 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric // This castAs is safe: methods that don't return an object 510b57cec5SDimitry Andric // pointer won't be inferred as inits and will reject an explicit 520b57cec5SDimitry Andric // objc_method_family(init). 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric // We ignore protocols here. Should we? What about Class? 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric const ObjCObjectType *result = 570b57cec5SDimitry Andric method->getReturnType()->castAs<ObjCObjectPointerType>()->getObjectType(); 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric if (result->isObjCId()) { 600b57cec5SDimitry Andric return false; 610b57cec5SDimitry Andric } else if (result->isObjCClass()) { 620b57cec5SDimitry Andric // fall through: always an error 630b57cec5SDimitry Andric } else { 640b57cec5SDimitry Andric ObjCInterfaceDecl *resultClass = result->getInterface(); 650b57cec5SDimitry Andric assert(resultClass && "unexpected object type!"); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // It's okay for the result type to still be a forward declaration 680b57cec5SDimitry Andric // if we're checking an interface declaration. 690b57cec5SDimitry Andric if (!resultClass->hasDefinition()) { 700b57cec5SDimitry Andric if (receiverTypeIfCall.isNull() && 710b57cec5SDimitry Andric !isa<ObjCImplementationDecl>(method->getDeclContext())) 720b57cec5SDimitry Andric return false; 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric // Otherwise, we try to compare class types. 750b57cec5SDimitry Andric } else { 760b57cec5SDimitry Andric // If this method was declared in a protocol, we can't check 770b57cec5SDimitry Andric // anything unless we have a receiver type that's an interface. 780b57cec5SDimitry Andric const ObjCInterfaceDecl *receiverClass = nullptr; 790b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(method->getDeclContext())) { 800b57cec5SDimitry Andric if (receiverTypeIfCall.isNull()) 810b57cec5SDimitry Andric return false; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric receiverClass = receiverTypeIfCall->castAs<ObjCObjectPointerType>() 840b57cec5SDimitry Andric ->getInterfaceDecl(); 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric // This can be null for calls to e.g. id<Foo>. 870b57cec5SDimitry Andric if (!receiverClass) return false; 880b57cec5SDimitry Andric } else { 890b57cec5SDimitry Andric receiverClass = method->getClassInterface(); 900b57cec5SDimitry Andric assert(receiverClass && "method not associated with a class!"); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // If either class is a subclass of the other, it's fine. 940b57cec5SDimitry Andric if (receiverClass->isSuperClassOf(resultClass) || 950b57cec5SDimitry Andric resultClass->isSuperClassOf(receiverClass)) 960b57cec5SDimitry Andric return false; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric SourceLocation loc = method->getLocation(); 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric // If we're in a system header, and this is not a call, just make 1030b57cec5SDimitry Andric // the method unusable. 104*0fca6ea1SDimitry Andric if (receiverTypeIfCall.isNull() && 105*0fca6ea1SDimitry Andric SemaRef.getSourceManager().isInSystemHeader(loc)) { 1060b57cec5SDimitry Andric method->addAttr(UnavailableAttr::CreateImplicit(Context, "", 1070b57cec5SDimitry Andric UnavailableAttr::IR_ARCInitReturnsUnrelated, loc)); 1080b57cec5SDimitry Andric return true; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric // Otherwise, it's an error. 1120b57cec5SDimitry Andric Diag(loc, diag::err_arc_init_method_unrelated_result_type); 1130b57cec5SDimitry Andric method->setInvalidDecl(); 1140b57cec5SDimitry Andric return true; 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric /// Issue a warning if the parameter of the overridden method is non-escaping 1180b57cec5SDimitry Andric /// but the parameter of the overriding method is not. 1190b57cec5SDimitry Andric static bool diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD, 1200b57cec5SDimitry Andric Sema &S) { 1210b57cec5SDimitry Andric if (OldD->hasAttr<NoEscapeAttr>() && !NewD->hasAttr<NoEscapeAttr>()) { 1220b57cec5SDimitry Andric S.Diag(NewD->getLocation(), diag::warn_overriding_method_missing_noescape); 1230b57cec5SDimitry Andric S.Diag(OldD->getLocation(), diag::note_overridden_marked_noescape); 1240b57cec5SDimitry Andric return false; 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric return true; 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// Produce additional diagnostics if a category conforms to a protocol that 1310b57cec5SDimitry Andric /// defines a method taking a non-escaping parameter. 1320b57cec5SDimitry Andric static void diagnoseNoescape(const ParmVarDecl *NewD, const ParmVarDecl *OldD, 1330b57cec5SDimitry Andric const ObjCCategoryDecl *CD, 1340b57cec5SDimitry Andric const ObjCProtocolDecl *PD, Sema &S) { 1350b57cec5SDimitry Andric if (!diagnoseNoescape(NewD, OldD, S)) 1360b57cec5SDimitry Andric S.Diag(CD->getLocation(), diag::note_cat_conform_to_noescape_prot) 1370b57cec5SDimitry Andric << CD->IsClassExtension() << PD 1380b57cec5SDimitry Andric << cast<ObjCMethodDecl>(NewD->getDeclContext()); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 141*0fca6ea1SDimitry Andric void SemaObjC::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, 1420b57cec5SDimitry Andric const ObjCMethodDecl *Overridden) { 143*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 1440b57cec5SDimitry Andric if (Overridden->hasRelatedResultType() && 1450b57cec5SDimitry Andric !NewMethod->hasRelatedResultType()) { 1460b57cec5SDimitry Andric // This can only happen when the method follows a naming convention that 1470b57cec5SDimitry Andric // implies a related result type, and the original (overridden) method has 1480b57cec5SDimitry Andric // a suitable return type, but the new (overriding) method does not have 1490b57cec5SDimitry Andric // a suitable return type. 1500b57cec5SDimitry Andric QualType ResultType = NewMethod->getReturnType(); 1510b57cec5SDimitry Andric SourceRange ResultTypeRange = NewMethod->getReturnTypeSourceRange(); 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric // Figure out which class this method is part of, if any. 1540b57cec5SDimitry Andric ObjCInterfaceDecl *CurrentClass 1550b57cec5SDimitry Andric = dyn_cast<ObjCInterfaceDecl>(NewMethod->getDeclContext()); 1560b57cec5SDimitry Andric if (!CurrentClass) { 1570b57cec5SDimitry Andric DeclContext *DC = NewMethod->getDeclContext(); 1580b57cec5SDimitry Andric if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(DC)) 1590b57cec5SDimitry Andric CurrentClass = Cat->getClassInterface(); 1600b57cec5SDimitry Andric else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(DC)) 1610b57cec5SDimitry Andric CurrentClass = Impl->getClassInterface(); 1620b57cec5SDimitry Andric else if (ObjCCategoryImplDecl *CatImpl 1630b57cec5SDimitry Andric = dyn_cast<ObjCCategoryImplDecl>(DC)) 1640b57cec5SDimitry Andric CurrentClass = CatImpl->getClassInterface(); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric if (CurrentClass) { 1680b57cec5SDimitry Andric Diag(NewMethod->getLocation(), 1690b57cec5SDimitry Andric diag::warn_related_result_type_compatibility_class) 1700b57cec5SDimitry Andric << Context.getObjCInterfaceType(CurrentClass) 1710b57cec5SDimitry Andric << ResultType 1720b57cec5SDimitry Andric << ResultTypeRange; 1730b57cec5SDimitry Andric } else { 1740b57cec5SDimitry Andric Diag(NewMethod->getLocation(), 1750b57cec5SDimitry Andric diag::warn_related_result_type_compatibility_protocol) 1760b57cec5SDimitry Andric << ResultType 1770b57cec5SDimitry Andric << ResultTypeRange; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric if (ObjCMethodFamily Family = Overridden->getMethodFamily()) 1810b57cec5SDimitry Andric Diag(Overridden->getLocation(), 1820b57cec5SDimitry Andric diag::note_related_result_type_family) 1830b57cec5SDimitry Andric << /*overridden method*/ 0 1840b57cec5SDimitry Andric << Family; 1850b57cec5SDimitry Andric else 1860b57cec5SDimitry Andric Diag(Overridden->getLocation(), 1870b57cec5SDimitry Andric diag::note_related_result_type_overridden); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() != 1910b57cec5SDimitry Andric Overridden->hasAttr<NSReturnsRetainedAttr>())) { 1920b57cec5SDimitry Andric Diag(NewMethod->getLocation(), 1930b57cec5SDimitry Andric getLangOpts().ObjCAutoRefCount 1940b57cec5SDimitry Andric ? diag::err_nsreturns_retained_attribute_mismatch 1950b57cec5SDimitry Andric : diag::warn_nsreturns_retained_attribute_mismatch) 1960b57cec5SDimitry Andric << 1; 1970b57cec5SDimitry Andric Diag(Overridden->getLocation(), diag::note_previous_decl) << "method"; 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() != 2000b57cec5SDimitry Andric Overridden->hasAttr<NSReturnsNotRetainedAttr>())) { 2010b57cec5SDimitry Andric Diag(NewMethod->getLocation(), 2020b57cec5SDimitry Andric getLangOpts().ObjCAutoRefCount 2030b57cec5SDimitry Andric ? diag::err_nsreturns_retained_attribute_mismatch 2040b57cec5SDimitry Andric : diag::warn_nsreturns_retained_attribute_mismatch) 2050b57cec5SDimitry Andric << 0; 2060b57cec5SDimitry Andric Diag(Overridden->getLocation(), diag::note_previous_decl) << "method"; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(), 2100b57cec5SDimitry Andric oe = Overridden->param_end(); 2110b57cec5SDimitry Andric for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(), 2120b57cec5SDimitry Andric ne = NewMethod->param_end(); 2130b57cec5SDimitry Andric ni != ne && oi != oe; ++ni, ++oi) { 2140b57cec5SDimitry Andric const ParmVarDecl *oldDecl = (*oi); 2150b57cec5SDimitry Andric ParmVarDecl *newDecl = (*ni); 2160b57cec5SDimitry Andric if (newDecl->hasAttr<NSConsumedAttr>() != 2170b57cec5SDimitry Andric oldDecl->hasAttr<NSConsumedAttr>()) { 2180b57cec5SDimitry Andric Diag(newDecl->getLocation(), 2190b57cec5SDimitry Andric getLangOpts().ObjCAutoRefCount 2200b57cec5SDimitry Andric ? diag::err_nsconsumed_attribute_mismatch 2210b57cec5SDimitry Andric : diag::warn_nsconsumed_attribute_mismatch); 2220b57cec5SDimitry Andric Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter"; 2230b57cec5SDimitry Andric } 2240b57cec5SDimitry Andric 225*0fca6ea1SDimitry Andric diagnoseNoescape(newDecl, oldDecl, SemaRef); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric } 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric /// Check a method declaration for compatibility with the Objective-C 2300b57cec5SDimitry Andric /// ARC conventions. 231*0fca6ea1SDimitry Andric bool SemaObjC::CheckARCMethodDecl(ObjCMethodDecl *method) { 232*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 2330b57cec5SDimitry Andric ObjCMethodFamily family = method->getMethodFamily(); 2340b57cec5SDimitry Andric switch (family) { 2350b57cec5SDimitry Andric case OMF_None: 2360b57cec5SDimitry Andric case OMF_finalize: 2370b57cec5SDimitry Andric case OMF_retain: 2380b57cec5SDimitry Andric case OMF_release: 2390b57cec5SDimitry Andric case OMF_autorelease: 2400b57cec5SDimitry Andric case OMF_retainCount: 2410b57cec5SDimitry Andric case OMF_self: 2420b57cec5SDimitry Andric case OMF_initialize: 2430b57cec5SDimitry Andric case OMF_performSelector: 2440b57cec5SDimitry Andric return false; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric case OMF_dealloc: 2470b57cec5SDimitry Andric if (!Context.hasSameType(method->getReturnType(), Context.VoidTy)) { 2480b57cec5SDimitry Andric SourceRange ResultTypeRange = method->getReturnTypeSourceRange(); 2490b57cec5SDimitry Andric if (ResultTypeRange.isInvalid()) 2500b57cec5SDimitry Andric Diag(method->getLocation(), diag::err_dealloc_bad_result_type) 2510b57cec5SDimitry Andric << method->getReturnType() 2520b57cec5SDimitry Andric << FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)"); 2530b57cec5SDimitry Andric else 2540b57cec5SDimitry Andric Diag(method->getLocation(), diag::err_dealloc_bad_result_type) 2550b57cec5SDimitry Andric << method->getReturnType() 2560b57cec5SDimitry Andric << FixItHint::CreateReplacement(ResultTypeRange, "void"); 2570b57cec5SDimitry Andric return true; 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric return false; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric case OMF_init: 2620b57cec5SDimitry Andric // If the method doesn't obey the init rules, don't bother annotating it. 2630b57cec5SDimitry Andric if (checkInitMethod(method, QualType())) 2640b57cec5SDimitry Andric return true; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric method->addAttr(NSConsumesSelfAttr::CreateImplicit(Context)); 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric // Don't add a second copy of this attribute, but otherwise don't 2690b57cec5SDimitry Andric // let it be suppressed. 2700b57cec5SDimitry Andric if (method->hasAttr<NSReturnsRetainedAttr>()) 2710b57cec5SDimitry Andric return false; 2720b57cec5SDimitry Andric break; 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric case OMF_alloc: 2750b57cec5SDimitry Andric case OMF_copy: 2760b57cec5SDimitry Andric case OMF_mutableCopy: 2770b57cec5SDimitry Andric case OMF_new: 2780b57cec5SDimitry Andric if (method->hasAttr<NSReturnsRetainedAttr>() || 2790b57cec5SDimitry Andric method->hasAttr<NSReturnsNotRetainedAttr>() || 2800b57cec5SDimitry Andric method->hasAttr<NSReturnsAutoreleasedAttr>()) 2810b57cec5SDimitry Andric return false; 2820b57cec5SDimitry Andric break; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 2850b57cec5SDimitry Andric method->addAttr(NSReturnsRetainedAttr::CreateImplicit(Context)); 2860b57cec5SDimitry Andric return false; 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND, 2900b57cec5SDimitry Andric SourceLocation ImplLoc) { 2910b57cec5SDimitry Andric if (!ND) 2920b57cec5SDimitry Andric return; 2930b57cec5SDimitry Andric bool IsCategory = false; 2940b57cec5SDimitry Andric StringRef RealizedPlatform; 2950b57cec5SDimitry Andric AvailabilityResult Availability = ND->getAvailability( 2960b57cec5SDimitry Andric /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(), 2970b57cec5SDimitry Andric &RealizedPlatform); 2980b57cec5SDimitry Andric if (Availability != AR_Deprecated) { 2990b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(ND)) { 3000b57cec5SDimitry Andric if (Availability != AR_Unavailable) 3010b57cec5SDimitry Andric return; 3020b57cec5SDimitry Andric if (RealizedPlatform.empty()) 3030b57cec5SDimitry Andric RealizedPlatform = S.Context.getTargetInfo().getPlatformName(); 3040b57cec5SDimitry Andric // Warn about implementing unavailable methods, unless the unavailable 3050b57cec5SDimitry Andric // is for an app extension. 3065f757f3fSDimitry Andric if (RealizedPlatform.ends_with("_app_extension")) 3070b57cec5SDimitry Andric return; 3080b57cec5SDimitry Andric S.Diag(ImplLoc, diag::warn_unavailable_def); 3090b57cec5SDimitry Andric S.Diag(ND->getLocation(), diag::note_method_declared_at) 3100b57cec5SDimitry Andric << ND->getDeclName(); 3110b57cec5SDimitry Andric return; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND)) { 3140b57cec5SDimitry Andric if (!CD->getClassInterface()->isDeprecated()) 3150b57cec5SDimitry Andric return; 3160b57cec5SDimitry Andric ND = CD->getClassInterface(); 3170b57cec5SDimitry Andric IsCategory = true; 3180b57cec5SDimitry Andric } else 3190b57cec5SDimitry Andric return; 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric S.Diag(ImplLoc, diag::warn_deprecated_def) 3220b57cec5SDimitry Andric << (isa<ObjCMethodDecl>(ND) 3230b57cec5SDimitry Andric ? /*Method*/ 0 3240b57cec5SDimitry Andric : isa<ObjCCategoryDecl>(ND) || IsCategory ? /*Category*/ 2 3250b57cec5SDimitry Andric : /*Class*/ 1); 3260b57cec5SDimitry Andric if (isa<ObjCMethodDecl>(ND)) 3270b57cec5SDimitry Andric S.Diag(ND->getLocation(), diag::note_method_declared_at) 3280b57cec5SDimitry Andric << ND->getDeclName(); 3290b57cec5SDimitry Andric else 3300b57cec5SDimitry Andric S.Diag(ND->getLocation(), diag::note_previous_decl) 3310b57cec5SDimitry Andric << (isa<ObjCCategoryDecl>(ND) ? "category" : "class"); 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric 3340b57cec5SDimitry Andric /// AddAnyMethodToGlobalPool - Add any method, instance or factory to global 3350b57cec5SDimitry Andric /// pool. 336*0fca6ea1SDimitry Andric void SemaObjC::AddAnyMethodToGlobalPool(Decl *D) { 3370b57cec5SDimitry Andric ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric // If we don't have a valid method decl, simply return. 3400b57cec5SDimitry Andric if (!MDecl) 3410b57cec5SDimitry Andric return; 3420b57cec5SDimitry Andric if (MDecl->isInstanceMethod()) 3430b57cec5SDimitry Andric AddInstanceMethodToGlobalPool(MDecl, true); 3440b57cec5SDimitry Andric else 3450b57cec5SDimitry Andric AddFactoryMethodToGlobalPool(MDecl, true); 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric 3480b57cec5SDimitry Andric /// HasExplicitOwnershipAttr - returns true when pointer to ObjC pointer 3490b57cec5SDimitry Andric /// has explicit ownership attribute; false otherwise. 3500b57cec5SDimitry Andric static bool 3510b57cec5SDimitry Andric HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) { 3520b57cec5SDimitry Andric QualType T = Param->getType(); 3530b57cec5SDimitry Andric 3540b57cec5SDimitry Andric if (const PointerType *PT = T->getAs<PointerType>()) { 3550b57cec5SDimitry Andric T = PT->getPointeeType(); 3560b57cec5SDimitry Andric } else if (const ReferenceType *RT = T->getAs<ReferenceType>()) { 3570b57cec5SDimitry Andric T = RT->getPointeeType(); 3580b57cec5SDimitry Andric } else { 3590b57cec5SDimitry Andric return true; 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric // If we have a lifetime qualifier, but it's local, we must have 3630b57cec5SDimitry Andric // inferred it. So, it is implicit. 3640b57cec5SDimitry Andric return !T.getLocalQualifiers().hasObjCLifetime(); 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible 3680b57cec5SDimitry Andric /// and user declared, in the method definition's AST. 369*0fca6ea1SDimitry Andric void SemaObjC::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { 370*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 371*0fca6ea1SDimitry Andric SemaRef.ImplicitlyRetainedSelfLocs.clear(); 372*0fca6ea1SDimitry Andric assert((SemaRef.getCurMethodDecl() == nullptr) && "Methodparsing confused"); 3730b57cec5SDimitry Andric ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); 3740b57cec5SDimitry Andric 375*0fca6ea1SDimitry Andric SemaRef.PushExpressionEvaluationContext( 376*0fca6ea1SDimitry Andric SemaRef.ExprEvalContexts.back().Context); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric // If we don't have a valid method decl, simply return. 3790b57cec5SDimitry Andric if (!MDecl) 3800b57cec5SDimitry Andric return; 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric QualType ResultType = MDecl->getReturnType(); 3830b57cec5SDimitry Andric if (!ResultType->isDependentType() && !ResultType->isVoidType() && 3840b57cec5SDimitry Andric !MDecl->isInvalidDecl() && 385*0fca6ea1SDimitry Andric SemaRef.RequireCompleteType(MDecl->getLocation(), ResultType, 3860b57cec5SDimitry Andric diag::err_func_def_incomplete_result)) 3870b57cec5SDimitry Andric MDecl->setInvalidDecl(); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // Allow all of Sema to see that we are entering a method definition. 390*0fca6ea1SDimitry Andric SemaRef.PushDeclContext(FnBodyScope, MDecl); 391*0fca6ea1SDimitry Andric SemaRef.PushFunctionScope(); 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric // Create Decl objects for each parameter, entrring them in the scope for 3940b57cec5SDimitry Andric // binding to their use. 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric // Insert the invisible arguments, self and _cmd! 3970b57cec5SDimitry Andric MDecl->createImplicitParams(Context, MDecl->getClassInterface()); 3980b57cec5SDimitry Andric 399*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(MDecl->getSelfDecl(), FnBodyScope); 400*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(MDecl->getCmdDecl(), FnBodyScope); 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric // The ObjC parser requires parameter names so there's no need to check. 403*0fca6ea1SDimitry Andric SemaRef.CheckParmsForFunctionDef(MDecl->parameters(), 4040b57cec5SDimitry Andric /*CheckParameterNames=*/false); 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric // Introduce all of the other parameters into this scope. 4070b57cec5SDimitry Andric for (auto *Param : MDecl->parameters()) { 408*0fca6ea1SDimitry Andric if (!Param->isInvalidDecl() && getLangOpts().ObjCAutoRefCount && 409*0fca6ea1SDimitry Andric !HasExplicitOwnershipAttr(SemaRef, Param)) 4100b57cec5SDimitry Andric Diag(Param->getLocation(), diag::warn_arc_strong_pointer_objc_pointer) << 4110b57cec5SDimitry Andric Param->getType(); 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric if (Param->getIdentifier()) 414*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(Param, FnBodyScope); 4150b57cec5SDimitry Andric } 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric // In ARC, disallow definition of retain/release/autorelease/retainCount 4180b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) { 4190b57cec5SDimitry Andric switch (MDecl->getMethodFamily()) { 4200b57cec5SDimitry Andric case OMF_retain: 4210b57cec5SDimitry Andric case OMF_retainCount: 4220b57cec5SDimitry Andric case OMF_release: 4230b57cec5SDimitry Andric case OMF_autorelease: 4240b57cec5SDimitry Andric Diag(MDecl->getLocation(), diag::err_arc_illegal_method_def) 4250b57cec5SDimitry Andric << 0 << MDecl->getSelector(); 4260b57cec5SDimitry Andric break; 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric case OMF_None: 4290b57cec5SDimitry Andric case OMF_dealloc: 4300b57cec5SDimitry Andric case OMF_finalize: 4310b57cec5SDimitry Andric case OMF_alloc: 4320b57cec5SDimitry Andric case OMF_init: 4330b57cec5SDimitry Andric case OMF_mutableCopy: 4340b57cec5SDimitry Andric case OMF_copy: 4350b57cec5SDimitry Andric case OMF_new: 4360b57cec5SDimitry Andric case OMF_self: 4370b57cec5SDimitry Andric case OMF_initialize: 4380b57cec5SDimitry Andric case OMF_performSelector: 4390b57cec5SDimitry Andric break; 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric // Warn on deprecated methods under -Wdeprecated-implementations, 4440b57cec5SDimitry Andric // and prepare for warning on missing super calls. 4450b57cec5SDimitry Andric if (ObjCInterfaceDecl *IC = MDecl->getClassInterface()) { 4460b57cec5SDimitry Andric ObjCMethodDecl *IMD = 4470b57cec5SDimitry Andric IC->lookupMethod(MDecl->getSelector(), MDecl->isInstanceMethod()); 4480b57cec5SDimitry Andric 4490b57cec5SDimitry Andric if (IMD) { 4500b57cec5SDimitry Andric ObjCImplDecl *ImplDeclOfMethodDef = 4510b57cec5SDimitry Andric dyn_cast<ObjCImplDecl>(MDecl->getDeclContext()); 4520b57cec5SDimitry Andric ObjCContainerDecl *ContDeclOfMethodDecl = 4530b57cec5SDimitry Andric dyn_cast<ObjCContainerDecl>(IMD->getDeclContext()); 4540b57cec5SDimitry Andric ObjCImplDecl *ImplDeclOfMethodDecl = nullptr; 4550b57cec5SDimitry Andric if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ContDeclOfMethodDecl)) 4560b57cec5SDimitry Andric ImplDeclOfMethodDecl = OID->getImplementation(); 4570b57cec5SDimitry Andric else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContDeclOfMethodDecl)) { 4580b57cec5SDimitry Andric if (CD->IsClassExtension()) { 4590b57cec5SDimitry Andric if (ObjCInterfaceDecl *OID = CD->getClassInterface()) 4600b57cec5SDimitry Andric ImplDeclOfMethodDecl = OID->getImplementation(); 4610b57cec5SDimitry Andric } else 4620b57cec5SDimitry Andric ImplDeclOfMethodDecl = CD->getImplementation(); 4630b57cec5SDimitry Andric } 4640b57cec5SDimitry Andric // No need to issue deprecated warning if deprecated mehod in class/category 4650b57cec5SDimitry Andric // is being implemented in its own implementation (no overriding is involved). 4660b57cec5SDimitry Andric if (!ImplDeclOfMethodDecl || ImplDeclOfMethodDecl != ImplDeclOfMethodDef) 467*0fca6ea1SDimitry Andric DiagnoseObjCImplementedDeprecations(SemaRef, IMD, MDecl->getLocation()); 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric if (MDecl->getMethodFamily() == OMF_init) { 4710b57cec5SDimitry Andric if (MDecl->isDesignatedInitializerForTheInterface()) { 472*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCIsDesignatedInit = true; 473*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCWarnForNoDesignatedInitChain = 4740b57cec5SDimitry Andric IC->getSuperClass() != nullptr; 4750b57cec5SDimitry Andric } else if (IC->hasDesignatedInitializers()) { 476*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCIsSecondaryInit = true; 477*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCWarnForNoInitDelegation = true; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric // If this is "dealloc" or "finalize", set some bit here. 4820b57cec5SDimitry Andric // Then in ActOnSuperMessage() (SemaExprObjC), set it back to false. 4830b57cec5SDimitry Andric // Finally, in ActOnFinishFunctionBody() (SemaDecl), warn if flag is set. 4840b57cec5SDimitry Andric // Only do this if the current class actually has a superclass. 4850b57cec5SDimitry Andric if (const ObjCInterfaceDecl *SuperClass = IC->getSuperClass()) { 4860b57cec5SDimitry Andric ObjCMethodFamily Family = MDecl->getMethodFamily(); 4870b57cec5SDimitry Andric if (Family == OMF_dealloc) { 4880b57cec5SDimitry Andric if (!(getLangOpts().ObjCAutoRefCount || 4890b57cec5SDimitry Andric getLangOpts().getGC() == LangOptions::GCOnly)) 490*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCShouldCallSuper = true; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric } else if (Family == OMF_finalize) { 4930b57cec5SDimitry Andric if (Context.getLangOpts().getGC() != LangOptions::NonGC) 494*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCShouldCallSuper = true; 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric } else { 4970b57cec5SDimitry Andric const ObjCMethodDecl *SuperMethod = 4980b57cec5SDimitry Andric SuperClass->lookupMethod(MDecl->getSelector(), 4990b57cec5SDimitry Andric MDecl->isInstanceMethod()); 500*0fca6ea1SDimitry Andric SemaRef.getCurFunction()->ObjCShouldCallSuper = 5010b57cec5SDimitry Andric (SuperMethod && SuperMethod->hasAttr<ObjCRequiresSuperAttr>()); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric } 505*0fca6ea1SDimitry Andric 506*0fca6ea1SDimitry Andric // Some function attributes (like OptimizeNoneAttr) need actions before 507*0fca6ea1SDimitry Andric // parsing body started. 508*0fca6ea1SDimitry Andric SemaRef.applyFunctionAttributesBeforeParsingBody(D); 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric namespace { 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric // Callback to only accept typo corrections that are Objective-C classes. 5140b57cec5SDimitry Andric // If an ObjCInterfaceDecl* is given to the constructor, then the validation 5150b57cec5SDimitry Andric // function will reject corrections to that class. 5160b57cec5SDimitry Andric class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback { 5170b57cec5SDimitry Andric public: 5180b57cec5SDimitry Andric ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {} 5190b57cec5SDimitry Andric explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl) 5200b57cec5SDimitry Andric : CurrentIDecl(IDecl) {} 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric bool ValidateCandidate(const TypoCorrection &candidate) override { 5230b57cec5SDimitry Andric ObjCInterfaceDecl *ID = candidate.getCorrectionDeclAs<ObjCInterfaceDecl>(); 5240b57cec5SDimitry Andric return ID && !declaresSameEntity(ID, CurrentIDecl); 5250b57cec5SDimitry Andric } 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric std::unique_ptr<CorrectionCandidateCallback> clone() override { 528a7dea167SDimitry Andric return std::make_unique<ObjCInterfaceValidatorCCC>(*this); 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric private: 5320b57cec5SDimitry Andric ObjCInterfaceDecl *CurrentIDecl; 5330b57cec5SDimitry Andric }; 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric } // end anonymous namespace 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric static void diagnoseUseOfProtocols(Sema &TheSema, 5380b57cec5SDimitry Andric ObjCContainerDecl *CD, 5390b57cec5SDimitry Andric ObjCProtocolDecl *const *ProtoRefs, 5400b57cec5SDimitry Andric unsigned NumProtoRefs, 5410b57cec5SDimitry Andric const SourceLocation *ProtoLocs) { 5420b57cec5SDimitry Andric assert(ProtoRefs); 5430b57cec5SDimitry Andric // Diagnose availability in the context of the ObjC container. 5440b57cec5SDimitry Andric Sema::ContextRAII SavedContext(TheSema, CD); 5450b57cec5SDimitry Andric for (unsigned i = 0; i < NumProtoRefs; ++i) { 5460b57cec5SDimitry Andric (void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i], 5470b57cec5SDimitry Andric /*UnknownObjCClass=*/nullptr, 5480b57cec5SDimitry Andric /*ObjCPropertyAccess=*/false, 5490b57cec5SDimitry Andric /*AvoidPartialAvailabilityChecks=*/true); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric } 5520b57cec5SDimitry Andric 553*0fca6ea1SDimitry Andric void SemaObjC::ActOnSuperClassOfClassInterface( 554*0fca6ea1SDimitry Andric Scope *S, SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *IDecl, 555*0fca6ea1SDimitry Andric IdentifierInfo *ClassName, SourceLocation ClassLoc, 556*0fca6ea1SDimitry Andric IdentifierInfo *SuperName, SourceLocation SuperLoc, 557*0fca6ea1SDimitry Andric ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange) { 558*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 5590b57cec5SDimitry Andric // Check if a different kind of symbol declared in this scope. 560*0fca6ea1SDimitry Andric NamedDecl *PrevDecl = SemaRef.LookupSingleName( 561*0fca6ea1SDimitry Andric SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName); 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric if (!PrevDecl) { 5640b57cec5SDimitry Andric // Try to correct for a typo in the superclass name without correcting 5650b57cec5SDimitry Andric // to the class we're defining. 5660b57cec5SDimitry Andric ObjCInterfaceValidatorCCC CCC(IDecl); 567*0fca6ea1SDimitry Andric if (TypoCorrection Corrected = SemaRef.CorrectTypo( 568*0fca6ea1SDimitry Andric DeclarationNameInfo(SuperName, SuperLoc), Sema::LookupOrdinaryName, 569*0fca6ea1SDimitry Andric SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) { 570*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) 5710b57cec5SDimitry Andric << SuperName << ClassName); 5720b57cec5SDimitry Andric PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); 5730b57cec5SDimitry Andric } 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric if (declaresSameEntity(PrevDecl, IDecl)) { 5770b57cec5SDimitry Andric Diag(SuperLoc, diag::err_recursive_superclass) 5780b57cec5SDimitry Andric << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); 5790b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(ClassLoc); 5800b57cec5SDimitry Andric } else { 5810b57cec5SDimitry Andric ObjCInterfaceDecl *SuperClassDecl = 5820b57cec5SDimitry Andric dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 5830b57cec5SDimitry Andric QualType SuperClassType; 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric // Diagnose classes that inherit from deprecated classes. 5860b57cec5SDimitry Andric if (SuperClassDecl) { 587*0fca6ea1SDimitry Andric (void)SemaRef.DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); 5880b57cec5SDimitry Andric SuperClassType = Context.getObjCInterfaceType(SuperClassDecl); 5890b57cec5SDimitry Andric } 5900b57cec5SDimitry Andric 5910b57cec5SDimitry Andric if (PrevDecl && !SuperClassDecl) { 5920b57cec5SDimitry Andric // The previous declaration was not a class decl. Check if we have a 5930b57cec5SDimitry Andric // typedef. If we do, get the underlying class type. 5940b57cec5SDimitry Andric if (const TypedefNameDecl *TDecl = 5950b57cec5SDimitry Andric dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) { 5960b57cec5SDimitry Andric QualType T = TDecl->getUnderlyingType(); 5970b57cec5SDimitry Andric if (T->isObjCObjectType()) { 598a7dea167SDimitry Andric if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) { 5990b57cec5SDimitry Andric SuperClassDecl = dyn_cast<ObjCInterfaceDecl>(IDecl); 6000b57cec5SDimitry Andric SuperClassType = Context.getTypeDeclType(TDecl); 6010b57cec5SDimitry Andric 6020b57cec5SDimitry Andric // This handles the following case: 6030b57cec5SDimitry Andric // @interface NewI @end 6040b57cec5SDimitry Andric // typedef NewI DeprI __attribute__((deprecated("blah"))) 6050b57cec5SDimitry Andric // @interface SI : DeprI /* warn here */ @end 606*0fca6ea1SDimitry Andric (void)SemaRef.DiagnoseUseOfDecl( 607*0fca6ea1SDimitry Andric const_cast<TypedefNameDecl *>(TDecl), SuperLoc); 6080b57cec5SDimitry Andric } 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric // This handles the following case: 6130b57cec5SDimitry Andric // 6140b57cec5SDimitry Andric // typedef int SuperClass; 6150b57cec5SDimitry Andric // @interface MyClass : SuperClass {} @end 6160b57cec5SDimitry Andric // 6170b57cec5SDimitry Andric if (!SuperClassDecl) { 6180b57cec5SDimitry Andric Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName; 6190b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 6200b57cec5SDimitry Andric } 6210b57cec5SDimitry Andric } 6220b57cec5SDimitry Andric 623349cc55cSDimitry Andric if (!isa_and_nonnull<TypedefNameDecl>(PrevDecl)) { 6240b57cec5SDimitry Andric if (!SuperClassDecl) 6250b57cec5SDimitry Andric Diag(SuperLoc, diag::err_undef_superclass) 6260b57cec5SDimitry Andric << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); 627*0fca6ea1SDimitry Andric else if (SemaRef.RequireCompleteType( 628*0fca6ea1SDimitry Andric SuperLoc, SuperClassType, diag::err_forward_superclass, 629*0fca6ea1SDimitry Andric SuperClassDecl->getDeclName(), ClassName, 6300b57cec5SDimitry Andric SourceRange(AtInterfaceLoc, ClassLoc))) { 6310b57cec5SDimitry Andric SuperClassDecl = nullptr; 6320b57cec5SDimitry Andric SuperClassType = QualType(); 6330b57cec5SDimitry Andric } 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric if (SuperClassType.isNull()) { 6370b57cec5SDimitry Andric assert(!SuperClassDecl && "Failed to set SuperClassType?"); 6380b57cec5SDimitry Andric return; 6390b57cec5SDimitry Andric } 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric // Handle type arguments on the superclass. 6420b57cec5SDimitry Andric TypeSourceInfo *SuperClassTInfo = nullptr; 6430b57cec5SDimitry Andric if (!SuperTypeArgs.empty()) { 6440b57cec5SDimitry Andric TypeResult fullSuperClassType = actOnObjCTypeArgsAndProtocolQualifiers( 645*0fca6ea1SDimitry Andric S, SuperLoc, SemaRef.CreateParsedType(SuperClassType, nullptr), 646*0fca6ea1SDimitry Andric SuperTypeArgsRange.getBegin(), SuperTypeArgs, 647*0fca6ea1SDimitry Andric SuperTypeArgsRange.getEnd(), SourceLocation(), {}, {}, 6480b57cec5SDimitry Andric SourceLocation()); 6490b57cec5SDimitry Andric if (!fullSuperClassType.isUsable()) 6500b57cec5SDimitry Andric return; 6510b57cec5SDimitry Andric 652*0fca6ea1SDimitry Andric SuperClassType = 653*0fca6ea1SDimitry Andric SemaRef.GetTypeFromParser(fullSuperClassType.get(), &SuperClassTInfo); 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric if (!SuperClassTInfo) { 6570b57cec5SDimitry Andric SuperClassTInfo = Context.getTrivialTypeSourceInfo(SuperClassType, 6580b57cec5SDimitry Andric SuperLoc); 6590b57cec5SDimitry Andric } 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric IDecl->setSuperClass(SuperClassTInfo); 6620b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(SuperClassTInfo->getTypeLoc().getEndLoc()); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric } 6650b57cec5SDimitry Andric 666*0fca6ea1SDimitry Andric DeclResult SemaObjC::actOnObjCTypeParam( 667*0fca6ea1SDimitry Andric Scope *S, ObjCTypeParamVariance variance, SourceLocation varianceLoc, 668*0fca6ea1SDimitry Andric unsigned index, IdentifierInfo *paramName, SourceLocation paramLoc, 669*0fca6ea1SDimitry Andric SourceLocation colonLoc, ParsedType parsedTypeBound) { 670*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 6710b57cec5SDimitry Andric // If there was an explicitly-provided type bound, check it. 6720b57cec5SDimitry Andric TypeSourceInfo *typeBoundInfo = nullptr; 6730b57cec5SDimitry Andric if (parsedTypeBound) { 6740b57cec5SDimitry Andric // The type bound can be any Objective-C pointer type. 675*0fca6ea1SDimitry Andric QualType typeBound = 676*0fca6ea1SDimitry Andric SemaRef.GetTypeFromParser(parsedTypeBound, &typeBoundInfo); 6770b57cec5SDimitry Andric if (typeBound->isObjCObjectPointerType()) { 6780b57cec5SDimitry Andric // okay 6790b57cec5SDimitry Andric } else if (typeBound->isObjCObjectType()) { 6800b57cec5SDimitry Andric // The user forgot the * on an Objective-C pointer type, e.g., 6810b57cec5SDimitry Andric // "T : NSView". 682*0fca6ea1SDimitry Andric SourceLocation starLoc = 683*0fca6ea1SDimitry Andric SemaRef.getLocForEndOfToken(typeBoundInfo->getTypeLoc().getEndLoc()); 6840b57cec5SDimitry Andric Diag(typeBoundInfo->getTypeLoc().getBeginLoc(), 6850b57cec5SDimitry Andric diag::err_objc_type_param_bound_missing_pointer) 6860b57cec5SDimitry Andric << typeBound << paramName 6870b57cec5SDimitry Andric << FixItHint::CreateInsertion(starLoc, " *"); 6880b57cec5SDimitry Andric 6890b57cec5SDimitry Andric // Create a new type location builder so we can update the type 6900b57cec5SDimitry Andric // location information we have. 6910b57cec5SDimitry Andric TypeLocBuilder builder; 6920b57cec5SDimitry Andric builder.pushFullCopy(typeBoundInfo->getTypeLoc()); 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric // Create the Objective-C pointer type. 6950b57cec5SDimitry Andric typeBound = Context.getObjCObjectPointerType(typeBound); 6960b57cec5SDimitry Andric ObjCObjectPointerTypeLoc newT 6970b57cec5SDimitry Andric = builder.push<ObjCObjectPointerTypeLoc>(typeBound); 6980b57cec5SDimitry Andric newT.setStarLoc(starLoc); 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric // Form the new type source information. 7010b57cec5SDimitry Andric typeBoundInfo = builder.getTypeSourceInfo(Context, typeBound); 7020b57cec5SDimitry Andric } else { 7030b57cec5SDimitry Andric // Not a valid type bound. 7040b57cec5SDimitry Andric Diag(typeBoundInfo->getTypeLoc().getBeginLoc(), 7050b57cec5SDimitry Andric diag::err_objc_type_param_bound_nonobject) 7060b57cec5SDimitry Andric << typeBound << paramName; 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric // Forget the bound; we'll default to id later. 7090b57cec5SDimitry Andric typeBoundInfo = nullptr; 7100b57cec5SDimitry Andric } 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric // Type bounds cannot have qualifiers (even indirectly) or explicit 7130b57cec5SDimitry Andric // nullability. 7140b57cec5SDimitry Andric if (typeBoundInfo) { 7150b57cec5SDimitry Andric QualType typeBound = typeBoundInfo->getType(); 7160b57cec5SDimitry Andric TypeLoc qual = typeBoundInfo->getTypeLoc().findExplicitQualifierLoc(); 7170b57cec5SDimitry Andric if (qual || typeBound.hasQualifiers()) { 7180b57cec5SDimitry Andric bool diagnosed = false; 7190b57cec5SDimitry Andric SourceRange rangeToRemove; 7200b57cec5SDimitry Andric if (qual) { 7210b57cec5SDimitry Andric if (auto attr = qual.getAs<AttributedTypeLoc>()) { 7220b57cec5SDimitry Andric rangeToRemove = attr.getLocalSourceRange(); 7230b57cec5SDimitry Andric if (attr.getTypePtr()->getImmediateNullability()) { 7240b57cec5SDimitry Andric Diag(attr.getBeginLoc(), 7250b57cec5SDimitry Andric diag::err_objc_type_param_bound_explicit_nullability) 7260b57cec5SDimitry Andric << paramName << typeBound 7270b57cec5SDimitry Andric << FixItHint::CreateRemoval(rangeToRemove); 7280b57cec5SDimitry Andric diagnosed = true; 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric if (!diagnosed) { 7340b57cec5SDimitry Andric Diag(qual ? qual.getBeginLoc() 7350b57cec5SDimitry Andric : typeBoundInfo->getTypeLoc().getBeginLoc(), 7360b57cec5SDimitry Andric diag::err_objc_type_param_bound_qualified) 7370b57cec5SDimitry Andric << paramName << typeBound 7380b57cec5SDimitry Andric << typeBound.getQualifiers().getAsString() 7390b57cec5SDimitry Andric << FixItHint::CreateRemoval(rangeToRemove); 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric // If the type bound has qualifiers other than CVR, we need to strip 7430b57cec5SDimitry Andric // them or we'll probably assert later when trying to apply new 7440b57cec5SDimitry Andric // qualifiers. 7450b57cec5SDimitry Andric Qualifiers quals = typeBound.getQualifiers(); 7460b57cec5SDimitry Andric quals.removeCVRQualifiers(); 7470b57cec5SDimitry Andric if (!quals.empty()) { 7480b57cec5SDimitry Andric typeBoundInfo = 7490b57cec5SDimitry Andric Context.getTrivialTypeSourceInfo(typeBound.getUnqualifiedType()); 7500b57cec5SDimitry Andric } 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric // If there was no explicit type bound (or we removed it due to an error), 7560b57cec5SDimitry Andric // use 'id' instead. 7570b57cec5SDimitry Andric if (!typeBoundInfo) { 7580b57cec5SDimitry Andric colonLoc = SourceLocation(); 7590b57cec5SDimitry Andric typeBoundInfo = Context.getTrivialTypeSourceInfo(Context.getObjCIdType()); 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric // Create the type parameter. 763*0fca6ea1SDimitry Andric return ObjCTypeParamDecl::Create(Context, SemaRef.CurContext, variance, 764*0fca6ea1SDimitry Andric varianceLoc, index, paramLoc, paramName, 765*0fca6ea1SDimitry Andric colonLoc, typeBoundInfo); 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 768*0fca6ea1SDimitry Andric ObjCTypeParamList * 769*0fca6ea1SDimitry Andric SemaObjC::actOnObjCTypeParamList(Scope *S, SourceLocation lAngleLoc, 7700b57cec5SDimitry Andric ArrayRef<Decl *> typeParamsIn, 7710b57cec5SDimitry Andric SourceLocation rAngleLoc) { 772*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 7730b57cec5SDimitry Andric // We know that the array only contains Objective-C type parameters. 7740b57cec5SDimitry Andric ArrayRef<ObjCTypeParamDecl *> 7750b57cec5SDimitry Andric typeParams( 7760b57cec5SDimitry Andric reinterpret_cast<ObjCTypeParamDecl * const *>(typeParamsIn.data()), 7770b57cec5SDimitry Andric typeParamsIn.size()); 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric // Diagnose redeclarations of type parameters. 7800b57cec5SDimitry Andric // We do this now because Objective-C type parameters aren't pushed into 7810b57cec5SDimitry Andric // scope until later (after the instance variable block), but we want the 7820b57cec5SDimitry Andric // diagnostics to occur right after we parse the type parameter list. 7830b57cec5SDimitry Andric llvm::SmallDenseMap<IdentifierInfo *, ObjCTypeParamDecl *> knownParams; 784bdd1243dSDimitry Andric for (auto *typeParam : typeParams) { 7850b57cec5SDimitry Andric auto known = knownParams.find(typeParam->getIdentifier()); 7860b57cec5SDimitry Andric if (known != knownParams.end()) { 7870b57cec5SDimitry Andric Diag(typeParam->getLocation(), diag::err_objc_type_param_redecl) 7880b57cec5SDimitry Andric << typeParam->getIdentifier() 7890b57cec5SDimitry Andric << SourceRange(known->second->getLocation()); 7900b57cec5SDimitry Andric 7910b57cec5SDimitry Andric typeParam->setInvalidDecl(); 7920b57cec5SDimitry Andric } else { 7930b57cec5SDimitry Andric knownParams.insert(std::make_pair(typeParam->getIdentifier(), typeParam)); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric // Push the type parameter into scope. 796*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(typeParam, S, /*AddToContext=*/false); 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric 8000b57cec5SDimitry Andric // Create the parameter list. 8010b57cec5SDimitry Andric return ObjCTypeParamList::create(Context, lAngleLoc, typeParams, rAngleLoc); 8020b57cec5SDimitry Andric } 8030b57cec5SDimitry Andric 804*0fca6ea1SDimitry Andric void SemaObjC::popObjCTypeParamList(Scope *S, 805*0fca6ea1SDimitry Andric ObjCTypeParamList *typeParamList) { 806bdd1243dSDimitry Andric for (auto *typeParam : *typeParamList) { 8070b57cec5SDimitry Andric if (!typeParam->isInvalidDecl()) { 8080b57cec5SDimitry Andric S->RemoveDecl(typeParam); 809*0fca6ea1SDimitry Andric SemaRef.IdResolver.RemoveDecl(typeParam); 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric } 8130b57cec5SDimitry Andric 8140b57cec5SDimitry Andric namespace { 8150b57cec5SDimitry Andric /// The context in which an Objective-C type parameter list occurs, for use 8160b57cec5SDimitry Andric /// in diagnostics. 8170b57cec5SDimitry Andric enum class TypeParamListContext { 8180b57cec5SDimitry Andric ForwardDeclaration, 8190b57cec5SDimitry Andric Definition, 8200b57cec5SDimitry Andric Category, 8210b57cec5SDimitry Andric Extension 8220b57cec5SDimitry Andric }; 8230b57cec5SDimitry Andric } // end anonymous namespace 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric /// Check consistency between two Objective-C type parameter lists, e.g., 8260b57cec5SDimitry Andric /// between a category/extension and an \@interface or between an \@class and an 8270b57cec5SDimitry Andric /// \@interface. 8280b57cec5SDimitry Andric static bool checkTypeParamListConsistency(Sema &S, 8290b57cec5SDimitry Andric ObjCTypeParamList *prevTypeParams, 8300b57cec5SDimitry Andric ObjCTypeParamList *newTypeParams, 8310b57cec5SDimitry Andric TypeParamListContext newContext) { 8320b57cec5SDimitry Andric // If the sizes don't match, complain about that. 8330b57cec5SDimitry Andric if (prevTypeParams->size() != newTypeParams->size()) { 8340b57cec5SDimitry Andric SourceLocation diagLoc; 8350b57cec5SDimitry Andric if (newTypeParams->size() > prevTypeParams->size()) { 8360b57cec5SDimitry Andric diagLoc = newTypeParams->begin()[prevTypeParams->size()]->getLocation(); 8370b57cec5SDimitry Andric } else { 8380b57cec5SDimitry Andric diagLoc = S.getLocForEndOfToken(newTypeParams->back()->getEndLoc()); 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric S.Diag(diagLoc, diag::err_objc_type_param_arity_mismatch) 8420b57cec5SDimitry Andric << static_cast<unsigned>(newContext) 8430b57cec5SDimitry Andric << (newTypeParams->size() > prevTypeParams->size()) 8440b57cec5SDimitry Andric << prevTypeParams->size() 8450b57cec5SDimitry Andric << newTypeParams->size(); 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric return true; 8480b57cec5SDimitry Andric } 8490b57cec5SDimitry Andric 8500b57cec5SDimitry Andric // Match up the type parameters. 8510b57cec5SDimitry Andric for (unsigned i = 0, n = prevTypeParams->size(); i != n; ++i) { 8520b57cec5SDimitry Andric ObjCTypeParamDecl *prevTypeParam = prevTypeParams->begin()[i]; 8530b57cec5SDimitry Andric ObjCTypeParamDecl *newTypeParam = newTypeParams->begin()[i]; 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric // Check for consistency of the variance. 8560b57cec5SDimitry Andric if (newTypeParam->getVariance() != prevTypeParam->getVariance()) { 8570b57cec5SDimitry Andric if (newTypeParam->getVariance() == ObjCTypeParamVariance::Invariant && 8580b57cec5SDimitry Andric newContext != TypeParamListContext::Definition) { 8590b57cec5SDimitry Andric // When the new type parameter is invariant and is not part 8600b57cec5SDimitry Andric // of the definition, just propagate the variance. 8610b57cec5SDimitry Andric newTypeParam->setVariance(prevTypeParam->getVariance()); 8620b57cec5SDimitry Andric } else if (prevTypeParam->getVariance() 8630b57cec5SDimitry Andric == ObjCTypeParamVariance::Invariant && 8640b57cec5SDimitry Andric !(isa<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) && 8650b57cec5SDimitry Andric cast<ObjCInterfaceDecl>(prevTypeParam->getDeclContext()) 8660b57cec5SDimitry Andric ->getDefinition() == prevTypeParam->getDeclContext())) { 8670b57cec5SDimitry Andric // When the old parameter is invariant and was not part of the 8680b57cec5SDimitry Andric // definition, just ignore the difference because it doesn't 8690b57cec5SDimitry Andric // matter. 8700b57cec5SDimitry Andric } else { 8710b57cec5SDimitry Andric { 8720b57cec5SDimitry Andric // Diagnose the conflict and update the second declaration. 8730b57cec5SDimitry Andric SourceLocation diagLoc = newTypeParam->getVarianceLoc(); 8740b57cec5SDimitry Andric if (diagLoc.isInvalid()) 8750b57cec5SDimitry Andric diagLoc = newTypeParam->getBeginLoc(); 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric auto diag = S.Diag(diagLoc, 8780b57cec5SDimitry Andric diag::err_objc_type_param_variance_conflict) 8790b57cec5SDimitry Andric << static_cast<unsigned>(newTypeParam->getVariance()) 8800b57cec5SDimitry Andric << newTypeParam->getDeclName() 8810b57cec5SDimitry Andric << static_cast<unsigned>(prevTypeParam->getVariance()) 8820b57cec5SDimitry Andric << prevTypeParam->getDeclName(); 8830b57cec5SDimitry Andric switch (prevTypeParam->getVariance()) { 8840b57cec5SDimitry Andric case ObjCTypeParamVariance::Invariant: 8850b57cec5SDimitry Andric diag << FixItHint::CreateRemoval(newTypeParam->getVarianceLoc()); 8860b57cec5SDimitry Andric break; 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric case ObjCTypeParamVariance::Covariant: 8890b57cec5SDimitry Andric case ObjCTypeParamVariance::Contravariant: { 8900b57cec5SDimitry Andric StringRef newVarianceStr 8910b57cec5SDimitry Andric = prevTypeParam->getVariance() == ObjCTypeParamVariance::Covariant 8920b57cec5SDimitry Andric ? "__covariant" 8930b57cec5SDimitry Andric : "__contravariant"; 8940b57cec5SDimitry Andric if (newTypeParam->getVariance() 8950b57cec5SDimitry Andric == ObjCTypeParamVariance::Invariant) { 8960b57cec5SDimitry Andric diag << FixItHint::CreateInsertion(newTypeParam->getBeginLoc(), 8970b57cec5SDimitry Andric (newVarianceStr + " ").str()); 8980b57cec5SDimitry Andric } else { 8990b57cec5SDimitry Andric diag << FixItHint::CreateReplacement(newTypeParam->getVarianceLoc(), 9000b57cec5SDimitry Andric newVarianceStr); 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric } 9050b57cec5SDimitry Andric 9060b57cec5SDimitry Andric S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here) 9070b57cec5SDimitry Andric << prevTypeParam->getDeclName(); 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric // Override the variance. 9100b57cec5SDimitry Andric newTypeParam->setVariance(prevTypeParam->getVariance()); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric } 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric // If the bound types match, there's nothing to do. 9150b57cec5SDimitry Andric if (S.Context.hasSameType(prevTypeParam->getUnderlyingType(), 9160b57cec5SDimitry Andric newTypeParam->getUnderlyingType())) 9170b57cec5SDimitry Andric continue; 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric // If the new type parameter's bound was explicit, complain about it being 9200b57cec5SDimitry Andric // different from the original. 9210b57cec5SDimitry Andric if (newTypeParam->hasExplicitBound()) { 9220b57cec5SDimitry Andric SourceRange newBoundRange = newTypeParam->getTypeSourceInfo() 9230b57cec5SDimitry Andric ->getTypeLoc().getSourceRange(); 9240b57cec5SDimitry Andric S.Diag(newBoundRange.getBegin(), diag::err_objc_type_param_bound_conflict) 9250b57cec5SDimitry Andric << newTypeParam->getUnderlyingType() 9260b57cec5SDimitry Andric << newTypeParam->getDeclName() 9270b57cec5SDimitry Andric << prevTypeParam->hasExplicitBound() 9280b57cec5SDimitry Andric << prevTypeParam->getUnderlyingType() 9290b57cec5SDimitry Andric << (newTypeParam->getDeclName() == prevTypeParam->getDeclName()) 9300b57cec5SDimitry Andric << prevTypeParam->getDeclName() 9310b57cec5SDimitry Andric << FixItHint::CreateReplacement( 9320b57cec5SDimitry Andric newBoundRange, 9330b57cec5SDimitry Andric prevTypeParam->getUnderlyingType().getAsString( 9340b57cec5SDimitry Andric S.Context.getPrintingPolicy())); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here) 9370b57cec5SDimitry Andric << prevTypeParam->getDeclName(); 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric // Override the new type parameter's bound type with the previous type, 9400b57cec5SDimitry Andric // so that it's consistent. 9415ffd83dbSDimitry Andric S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam); 9420b57cec5SDimitry Andric continue; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric // The new type parameter got the implicit bound of 'id'. That's okay for 9460b57cec5SDimitry Andric // categories and extensions (overwrite it later), but not for forward 9470b57cec5SDimitry Andric // declarations and @interfaces, because those must be standalone. 9480b57cec5SDimitry Andric if (newContext == TypeParamListContext::ForwardDeclaration || 9490b57cec5SDimitry Andric newContext == TypeParamListContext::Definition) { 9500b57cec5SDimitry Andric // Diagnose this problem for forward declarations and definitions. 9510b57cec5SDimitry Andric SourceLocation insertionLoc 9520b57cec5SDimitry Andric = S.getLocForEndOfToken(newTypeParam->getLocation()); 9530b57cec5SDimitry Andric std::string newCode 9540b57cec5SDimitry Andric = " : " + prevTypeParam->getUnderlyingType().getAsString( 9550b57cec5SDimitry Andric S.Context.getPrintingPolicy()); 9560b57cec5SDimitry Andric S.Diag(newTypeParam->getLocation(), 9570b57cec5SDimitry Andric diag::err_objc_type_param_bound_missing) 9580b57cec5SDimitry Andric << prevTypeParam->getUnderlyingType() 9590b57cec5SDimitry Andric << newTypeParam->getDeclName() 9600b57cec5SDimitry Andric << (newContext == TypeParamListContext::ForwardDeclaration) 9610b57cec5SDimitry Andric << FixItHint::CreateInsertion(insertionLoc, newCode); 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric S.Diag(prevTypeParam->getLocation(), diag::note_objc_type_param_here) 9640b57cec5SDimitry Andric << prevTypeParam->getDeclName(); 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric 9670b57cec5SDimitry Andric // Update the new type parameter's bound to match the previous one. 9685ffd83dbSDimitry Andric S.Context.adjustObjCTypeParamBoundType(prevTypeParam, newTypeParam); 9690b57cec5SDimitry Andric } 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric return false; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 974*0fca6ea1SDimitry Andric ObjCInterfaceDecl *SemaObjC::ActOnStartClassInterface( 9750b57cec5SDimitry Andric Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, 9760b57cec5SDimitry Andric SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, 9770b57cec5SDimitry Andric IdentifierInfo *SuperName, SourceLocation SuperLoc, 9780b57cec5SDimitry Andric ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange, 9790b57cec5SDimitry Andric Decl *const *ProtoRefs, unsigned NumProtoRefs, 9800b57cec5SDimitry Andric const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, 981bdd1243dSDimitry Andric const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) { 9820b57cec5SDimitry Andric assert(ClassName && "Missing class identifier"); 9830b57cec5SDimitry Andric 984*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 9850b57cec5SDimitry Andric // Check for another declaration kind with the same name. 986*0fca6ea1SDimitry Andric NamedDecl *PrevDecl = SemaRef.LookupSingleName( 987*0fca6ea1SDimitry Andric SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName, 988*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { 9910b57cec5SDimitry Andric Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; 9920b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 9930b57cec5SDimitry Andric } 9940b57cec5SDimitry Andric 9950b57cec5SDimitry Andric // Create a declaration to describe this @interface. 9960b57cec5SDimitry Andric ObjCInterfaceDecl* PrevIDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { 9990b57cec5SDimitry Andric // A previous decl with a different name is because of 10000b57cec5SDimitry Andric // @compatibility_alias, for example: 10010b57cec5SDimitry Andric // \code 10020b57cec5SDimitry Andric // @class NewImage; 10030b57cec5SDimitry Andric // @compatibility_alias OldImage NewImage; 10040b57cec5SDimitry Andric // \endcode 10050b57cec5SDimitry Andric // A lookup for 'OldImage' will return the 'NewImage' decl. 10060b57cec5SDimitry Andric // 10070b57cec5SDimitry Andric // In such a case use the real declaration name, instead of the alias one, 10080b57cec5SDimitry Andric // otherwise we will break IdentifierResolver and redecls-chain invariants. 10090b57cec5SDimitry Andric // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl 10100b57cec5SDimitry Andric // has been aliased. 10110b57cec5SDimitry Andric ClassName = PrevIDecl->getIdentifier(); 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric // If there was a forward declaration with type parameters, check 10150b57cec5SDimitry Andric // for consistency. 10160b57cec5SDimitry Andric if (PrevIDecl) { 10170b57cec5SDimitry Andric if (ObjCTypeParamList *prevTypeParamList = PrevIDecl->getTypeParamList()) { 10180b57cec5SDimitry Andric if (typeParamList) { 10190b57cec5SDimitry Andric // Both have type parameter lists; check for consistency. 1020*0fca6ea1SDimitry Andric if (checkTypeParamListConsistency(SemaRef, prevTypeParamList, 10210b57cec5SDimitry Andric typeParamList, 10220b57cec5SDimitry Andric TypeParamListContext::Definition)) { 10230b57cec5SDimitry Andric typeParamList = nullptr; 10240b57cec5SDimitry Andric } 10250b57cec5SDimitry Andric } else { 10260b57cec5SDimitry Andric Diag(ClassLoc, diag::err_objc_parameterized_forward_class_first) 10270b57cec5SDimitry Andric << ClassName; 10280b57cec5SDimitry Andric Diag(prevTypeParamList->getLAngleLoc(), diag::note_previous_decl) 10290b57cec5SDimitry Andric << ClassName; 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric // Clone the type parameter list. 10320b57cec5SDimitry Andric SmallVector<ObjCTypeParamDecl *, 4> clonedTypeParams; 1033bdd1243dSDimitry Andric for (auto *typeParam : *prevTypeParamList) { 1034*0fca6ea1SDimitry Andric clonedTypeParams.push_back(ObjCTypeParamDecl::Create( 1035*0fca6ea1SDimitry Andric Context, SemaRef.CurContext, typeParam->getVariance(), 1036*0fca6ea1SDimitry Andric SourceLocation(), typeParam->getIndex(), SourceLocation(), 1037*0fca6ea1SDimitry Andric typeParam->getIdentifier(), SourceLocation(), 1038*0fca6ea1SDimitry Andric Context.getTrivialTypeSourceInfo( 1039*0fca6ea1SDimitry Andric typeParam->getUnderlyingType()))); 10400b57cec5SDimitry Andric } 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric typeParamList = ObjCTypeParamList::create(Context, 10430b57cec5SDimitry Andric SourceLocation(), 10440b57cec5SDimitry Andric clonedTypeParams, 10450b57cec5SDimitry Andric SourceLocation()); 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric 1050*0fca6ea1SDimitry Andric ObjCInterfaceDecl *IDecl = 1051*0fca6ea1SDimitry Andric ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc, 1052*0fca6ea1SDimitry Andric ClassName, typeParamList, PrevIDecl, ClassLoc); 10530b57cec5SDimitry Andric if (PrevIDecl) { 10540b57cec5SDimitry Andric // Class already seen. Was it a definition? 10550b57cec5SDimitry Andric if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { 1056*0fca6ea1SDimitry Andric if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) { 1057bdd1243dSDimitry Andric SkipBody->CheckSameAsPrevious = true; 1058bdd1243dSDimitry Andric SkipBody->New = IDecl; 1059bdd1243dSDimitry Andric SkipBody->Previous = Def; 1060bdd1243dSDimitry Andric } else { 10610b57cec5SDimitry Andric Diag(AtInterfaceLoc, diag::err_duplicate_class_def) 10620b57cec5SDimitry Andric << PrevIDecl->getDeclName(); 10630b57cec5SDimitry Andric Diag(Def->getLocation(), diag::note_previous_definition); 10640b57cec5SDimitry Andric IDecl->setInvalidDecl(); 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric } 1067bdd1243dSDimitry Andric } 10680b57cec5SDimitry Andric 1069*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IDecl, AttrList); 1070*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl); 1071*0fca6ea1SDimitry Andric SemaRef.ProcessAPINotes(IDecl); 1072e8d8bef9SDimitry Andric 1073e8d8bef9SDimitry Andric // Merge attributes from previous declarations. 1074e8d8bef9SDimitry Andric if (PrevIDecl) 1075*0fca6ea1SDimitry Andric SemaRef.mergeDeclAttributes(IDecl, PrevIDecl); 1076e8d8bef9SDimitry Andric 1077*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); 10780b57cec5SDimitry Andric 10790b57cec5SDimitry Andric // Start the definition of this class. If we're in a redefinition case, there 10800b57cec5SDimitry Andric // may already be a definition, so we'll end up adding to it. 1081bdd1243dSDimitry Andric if (SkipBody && SkipBody->CheckSameAsPrevious) 1082bdd1243dSDimitry Andric IDecl->startDuplicateDefinitionForComparison(); 1083bdd1243dSDimitry Andric else if (!IDecl->hasDefinition()) 10840b57cec5SDimitry Andric IDecl->startDefinition(); 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric if (SuperName) { 10870b57cec5SDimitry Andric // Diagnose availability in the context of the @interface. 1088*0fca6ea1SDimitry Andric Sema::ContextRAII SavedContext(SemaRef, IDecl); 10890b57cec5SDimitry Andric 10900b57cec5SDimitry Andric ActOnSuperClassOfClassInterface(S, AtInterfaceLoc, IDecl, 10910b57cec5SDimitry Andric ClassName, ClassLoc, 10920b57cec5SDimitry Andric SuperName, SuperLoc, SuperTypeArgs, 10930b57cec5SDimitry Andric SuperTypeArgsRange); 10940b57cec5SDimitry Andric } else { // we have a root class. 10950b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(ClassLoc); 10960b57cec5SDimitry Andric } 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric // Check then save referenced protocols. 10990b57cec5SDimitry Andric if (NumProtoRefs) { 1100*0fca6ea1SDimitry Andric diagnoseUseOfProtocols(SemaRef, IDecl, (ObjCProtocolDecl *const *)ProtoRefs, 11010b57cec5SDimitry Andric NumProtoRefs, ProtoLocs); 11020b57cec5SDimitry Andric IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, 11030b57cec5SDimitry Andric ProtoLocs, Context); 11040b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(EndProtoLoc); 11050b57cec5SDimitry Andric } 11060b57cec5SDimitry Andric 11070b57cec5SDimitry Andric CheckObjCDeclScope(IDecl); 110881ad6265SDimitry Andric ActOnObjCContainerStartDefinition(IDecl); 110981ad6265SDimitry Andric return IDecl; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric /// ActOnTypedefedProtocols - this action finds protocol list as part of the 11130b57cec5SDimitry Andric /// typedef'ed use for a qualified super class and adds them to the list 11140b57cec5SDimitry Andric /// of the protocols. 1115*0fca6ea1SDimitry Andric void SemaObjC::ActOnTypedefedProtocols( 1116*0fca6ea1SDimitry Andric SmallVectorImpl<Decl *> &ProtocolRefs, 1117*0fca6ea1SDimitry Andric SmallVectorImpl<SourceLocation> &ProtocolLocs, IdentifierInfo *SuperName, 11180b57cec5SDimitry Andric SourceLocation SuperLoc) { 11190b57cec5SDimitry Andric if (!SuperName) 11200b57cec5SDimitry Andric return; 1121*0fca6ea1SDimitry Andric NamedDecl *IDecl = SemaRef.LookupSingleName( 1122*0fca6ea1SDimitry Andric SemaRef.TUScope, SuperName, SuperLoc, Sema::LookupOrdinaryName); 11230b57cec5SDimitry Andric if (!IDecl) 11240b57cec5SDimitry Andric return; 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric if (const TypedefNameDecl *TDecl = dyn_cast_or_null<TypedefNameDecl>(IDecl)) { 11270b57cec5SDimitry Andric QualType T = TDecl->getUnderlyingType(); 11280b57cec5SDimitry Andric if (T->isObjCObjectType()) 11290b57cec5SDimitry Andric if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) { 11300b57cec5SDimitry Andric ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end()); 11310b57cec5SDimitry Andric // FIXME: Consider whether this should be an invalid loc since the loc 11320b57cec5SDimitry Andric // is not actually pointing to a protocol name reference but to the 11330b57cec5SDimitry Andric // typedef reference. Note that the base class name loc is also pointing 11340b57cec5SDimitry Andric // at the typedef. 11350b57cec5SDimitry Andric ProtocolLocs.append(OPT->getNumProtocols(), SuperLoc); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric } 11390b57cec5SDimitry Andric 11400b57cec5SDimitry Andric /// ActOnCompatibilityAlias - this action is called after complete parsing of 11410b57cec5SDimitry Andric /// a \@compatibility_alias declaration. It sets up the alias relationships. 1142*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnCompatibilityAlias(SourceLocation AtLoc, 11430b57cec5SDimitry Andric IdentifierInfo *AliasName, 11440b57cec5SDimitry Andric SourceLocation AliasLocation, 11450b57cec5SDimitry Andric IdentifierInfo *ClassName, 11460b57cec5SDimitry Andric SourceLocation ClassLocation) { 1147*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 11480b57cec5SDimitry Andric // Look for previous declaration of alias name 1149*0fca6ea1SDimitry Andric NamedDecl *ADecl = SemaRef.LookupSingleName( 1150*0fca6ea1SDimitry Andric SemaRef.TUScope, AliasName, AliasLocation, Sema::LookupOrdinaryName, 1151*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 11520b57cec5SDimitry Andric if (ADecl) { 11530b57cec5SDimitry Andric Diag(AliasLocation, diag::err_conflicting_aliasing_type) << AliasName; 11540b57cec5SDimitry Andric Diag(ADecl->getLocation(), diag::note_previous_declaration); 11550b57cec5SDimitry Andric return nullptr; 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric // Check for class declaration 1158*0fca6ea1SDimitry Andric NamedDecl *CDeclU = SemaRef.LookupSingleName( 1159*0fca6ea1SDimitry Andric SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName, 1160*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 11610b57cec5SDimitry Andric if (const TypedefNameDecl *TDecl = 11620b57cec5SDimitry Andric dyn_cast_or_null<TypedefNameDecl>(CDeclU)) { 11630b57cec5SDimitry Andric QualType T = TDecl->getUnderlyingType(); 11640b57cec5SDimitry Andric if (T->isObjCObjectType()) { 1165a7dea167SDimitry Andric if (NamedDecl *IDecl = T->castAs<ObjCObjectType>()->getInterface()) { 11660b57cec5SDimitry Andric ClassName = IDecl->getIdentifier(); 1167*0fca6ea1SDimitry Andric CDeclU = SemaRef.LookupSingleName( 1168*0fca6ea1SDimitry Andric SemaRef.TUScope, ClassName, ClassLocation, Sema::LookupOrdinaryName, 1169*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 11700b57cec5SDimitry Andric } 11710b57cec5SDimitry Andric } 11720b57cec5SDimitry Andric } 11730b57cec5SDimitry Andric ObjCInterfaceDecl *CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(CDeclU); 11740b57cec5SDimitry Andric if (!CDecl) { 11750b57cec5SDimitry Andric Diag(ClassLocation, diag::warn_undef_interface) << ClassName; 11760b57cec5SDimitry Andric if (CDeclU) 11770b57cec5SDimitry Andric Diag(CDeclU->getLocation(), diag::note_previous_declaration); 11780b57cec5SDimitry Andric return nullptr; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric // Everything checked out, instantiate a new alias declaration AST. 1182*0fca6ea1SDimitry Andric ObjCCompatibleAliasDecl *AliasDecl = ObjCCompatibleAliasDecl::Create( 1183*0fca6ea1SDimitry Andric Context, SemaRef.CurContext, AtLoc, AliasName, CDecl); 11840b57cec5SDimitry Andric 11850b57cec5SDimitry Andric if (!CheckObjCDeclScope(AliasDecl)) 1186*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(AliasDecl, SemaRef.TUScope); 11870b57cec5SDimitry Andric 11880b57cec5SDimitry Andric return AliasDecl; 11890b57cec5SDimitry Andric } 11900b57cec5SDimitry Andric 1191*0fca6ea1SDimitry Andric bool SemaObjC::CheckForwardProtocolDeclarationForCircularDependency( 1192*0fca6ea1SDimitry Andric IdentifierInfo *PName, SourceLocation &Ploc, SourceLocation PrevLoc, 11930b57cec5SDimitry Andric const ObjCList<ObjCProtocolDecl> &PList) { 11940b57cec5SDimitry Andric 11950b57cec5SDimitry Andric bool res = false; 11960b57cec5SDimitry Andric for (ObjCList<ObjCProtocolDecl>::iterator I = PList.begin(), 11970b57cec5SDimitry Andric E = PList.end(); I != E; ++I) { 1198*0fca6ea1SDimitry Andric if (ObjCProtocolDecl *PDecl = LookupProtocol((*I)->getIdentifier(), Ploc)) { 11990b57cec5SDimitry Andric if (PDecl->getIdentifier() == PName) { 12000b57cec5SDimitry Andric Diag(Ploc, diag::err_protocol_has_circular_dependency); 12010b57cec5SDimitry Andric Diag(PrevLoc, diag::note_previous_definition); 12020b57cec5SDimitry Andric res = true; 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric if (!PDecl->hasDefinition()) 12060b57cec5SDimitry Andric continue; 12070b57cec5SDimitry Andric 12080b57cec5SDimitry Andric if (CheckForwardProtocolDeclarationForCircularDependency(PName, Ploc, 12090b57cec5SDimitry Andric PDecl->getLocation(), PDecl->getReferencedProtocols())) 12100b57cec5SDimitry Andric res = true; 12110b57cec5SDimitry Andric } 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric return res; 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric 1216*0fca6ea1SDimitry Andric ObjCProtocolDecl *SemaObjC::ActOnStartProtocolInterface( 12170b57cec5SDimitry Andric SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, 12180b57cec5SDimitry Andric SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, 12190b57cec5SDimitry Andric const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, 1220bdd1243dSDimitry Andric const ParsedAttributesView &AttrList, SkipBodyInfo *SkipBody) { 1221*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 12220b57cec5SDimitry Andric bool err = false; 12230b57cec5SDimitry Andric // FIXME: Deal with AttrList. 12240b57cec5SDimitry Andric assert(ProtocolName && "Missing protocol identifier"); 1225*0fca6ea1SDimitry Andric ObjCProtocolDecl *PrevDecl = LookupProtocol( 1226*0fca6ea1SDimitry Andric ProtocolName, ProtocolLoc, SemaRef.forRedeclarationInCurContext()); 12270b57cec5SDimitry Andric ObjCProtocolDecl *PDecl = nullptr; 12280b57cec5SDimitry Andric if (ObjCProtocolDecl *Def = PrevDecl? PrevDecl->getDefinition() : nullptr) { 12290b57cec5SDimitry Andric // Create a new protocol that is completely distinct from previous 12300b57cec5SDimitry Andric // declarations, and do not make this protocol available for name lookup. 12310b57cec5SDimitry Andric // That way, we'll end up completely ignoring the duplicate. 12320b57cec5SDimitry Andric // FIXME: Can we turn this into an error? 1233*0fca6ea1SDimitry Andric PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName, 12340b57cec5SDimitry Andric ProtocolLoc, AtProtoInterfaceLoc, 1235bdd1243dSDimitry Andric /*PrevDecl=*/Def); 1236bdd1243dSDimitry Andric 1237*0fca6ea1SDimitry Andric if (SkipBody && !SemaRef.hasVisibleDefinition(Def)) { 1238bdd1243dSDimitry Andric SkipBody->CheckSameAsPrevious = true; 1239bdd1243dSDimitry Andric SkipBody->New = PDecl; 1240bdd1243dSDimitry Andric SkipBody->Previous = Def; 1241bdd1243dSDimitry Andric } else { 1242bdd1243dSDimitry Andric // If we already have a definition, complain. 1243bdd1243dSDimitry Andric Diag(ProtocolLoc, diag::warn_duplicate_protocol_def) << ProtocolName; 1244bdd1243dSDimitry Andric Diag(Def->getLocation(), diag::note_previous_definition); 1245bdd1243dSDimitry Andric } 12460b57cec5SDimitry Andric 12470b57cec5SDimitry Andric // If we are using modules, add the decl to the context in order to 12480b57cec5SDimitry Andric // serialize something meaningful. 12490b57cec5SDimitry Andric if (getLangOpts().Modules) 1250*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); 1251bdd1243dSDimitry Andric PDecl->startDuplicateDefinitionForComparison(); 12520b57cec5SDimitry Andric } else { 12530b57cec5SDimitry Andric if (PrevDecl) { 12540b57cec5SDimitry Andric // Check for circular dependencies among protocol declarations. This can 12550b57cec5SDimitry Andric // only happen if this protocol was forward-declared. 12560b57cec5SDimitry Andric ObjCList<ObjCProtocolDecl> PList; 12570b57cec5SDimitry Andric PList.set((ObjCProtocolDecl *const*)ProtoRefs, NumProtoRefs, Context); 12580b57cec5SDimitry Andric err = CheckForwardProtocolDeclarationForCircularDependency( 12590b57cec5SDimitry Andric ProtocolName, ProtocolLoc, PrevDecl->getLocation(), PList); 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric 12620b57cec5SDimitry Andric // Create the new declaration. 1263*0fca6ea1SDimitry Andric PDecl = ObjCProtocolDecl::Create(Context, SemaRef.CurContext, ProtocolName, 12640b57cec5SDimitry Andric ProtocolLoc, AtProtoInterfaceLoc, 12650b57cec5SDimitry Andric /*PrevDecl=*/PrevDecl); 12660b57cec5SDimitry Andric 1267*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); 12680b57cec5SDimitry Andric PDecl->startDefinition(); 12690b57cec5SDimitry Andric } 12700b57cec5SDimitry Andric 1271*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, AttrList); 1272*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl); 1273*0fca6ea1SDimitry Andric SemaRef.ProcessAPINotes(PDecl); 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric // Merge attributes from previous declarations. 12760b57cec5SDimitry Andric if (PrevDecl) 1277*0fca6ea1SDimitry Andric SemaRef.mergeDeclAttributes(PDecl, PrevDecl); 12780b57cec5SDimitry Andric 12790b57cec5SDimitry Andric if (!err && NumProtoRefs ) { 12800b57cec5SDimitry Andric /// Check then save referenced protocols. 1281*0fca6ea1SDimitry Andric diagnoseUseOfProtocols(SemaRef, PDecl, (ObjCProtocolDecl *const *)ProtoRefs, 12820b57cec5SDimitry Andric NumProtoRefs, ProtoLocs); 12830b57cec5SDimitry Andric PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, 12840b57cec5SDimitry Andric ProtoLocs, Context); 12850b57cec5SDimitry Andric } 12860b57cec5SDimitry Andric 12870b57cec5SDimitry Andric CheckObjCDeclScope(PDecl); 128881ad6265SDimitry Andric ActOnObjCContainerStartDefinition(PDecl); 128981ad6265SDimitry Andric return PDecl; 12900b57cec5SDimitry Andric } 12910b57cec5SDimitry Andric 12920b57cec5SDimitry Andric static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl, 12930b57cec5SDimitry Andric ObjCProtocolDecl *&UndefinedProtocol) { 12945ffd83dbSDimitry Andric if (!PDecl->hasDefinition() || 12955ffd83dbSDimitry Andric !PDecl->getDefinition()->isUnconditionallyVisible()) { 12960b57cec5SDimitry Andric UndefinedProtocol = PDecl; 12970b57cec5SDimitry Andric return true; 12980b57cec5SDimitry Andric } 12990b57cec5SDimitry Andric 13000b57cec5SDimitry Andric for (auto *PI : PDecl->protocols()) 13010b57cec5SDimitry Andric if (NestedProtocolHasNoDefinition(PI, UndefinedProtocol)) { 13020b57cec5SDimitry Andric UndefinedProtocol = PI; 13030b57cec5SDimitry Andric return true; 13040b57cec5SDimitry Andric } 13050b57cec5SDimitry Andric return false; 13060b57cec5SDimitry Andric } 13070b57cec5SDimitry Andric 13080b57cec5SDimitry Andric /// FindProtocolDeclaration - This routine looks up protocols and 13090b57cec5SDimitry Andric /// issues an error if they are not declared. It returns list of 13100b57cec5SDimitry Andric /// protocol declarations in its 'Protocols' argument. 1311*0fca6ea1SDimitry Andric void SemaObjC::FindProtocolDeclaration(bool WarnOnDeclarations, 1312*0fca6ea1SDimitry Andric bool ForObjCContainer, 13130b57cec5SDimitry Andric ArrayRef<IdentifierLocPair> ProtocolId, 13140b57cec5SDimitry Andric SmallVectorImpl<Decl *> &Protocols) { 13150b57cec5SDimitry Andric for (const IdentifierLocPair &Pair : ProtocolId) { 13160b57cec5SDimitry Andric ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second); 13170b57cec5SDimitry Andric if (!PDecl) { 13180b57cec5SDimitry Andric DeclFilterCCC<ObjCProtocolDecl> CCC{}; 1319*0fca6ea1SDimitry Andric TypoCorrection Corrected = 1320*0fca6ea1SDimitry Andric SemaRef.CorrectTypo(DeclarationNameInfo(Pair.first, Pair.second), 1321*0fca6ea1SDimitry Andric Sema::LookupObjCProtocolName, SemaRef.TUScope, 1322*0fca6ea1SDimitry Andric nullptr, CCC, Sema::CTK_ErrorRecovery); 13230b57cec5SDimitry Andric if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) 1324*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(Corrected, 1325*0fca6ea1SDimitry Andric PDiag(diag::err_undeclared_protocol_suggest) 13260b57cec5SDimitry Andric << Pair.first); 13270b57cec5SDimitry Andric } 13280b57cec5SDimitry Andric 13290b57cec5SDimitry Andric if (!PDecl) { 13300b57cec5SDimitry Andric Diag(Pair.second, diag::err_undeclared_protocol) << Pair.first; 13310b57cec5SDimitry Andric continue; 13320b57cec5SDimitry Andric } 13330b57cec5SDimitry Andric // If this is a forward protocol declaration, get its definition. 13340b57cec5SDimitry Andric if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition()) 13350b57cec5SDimitry Andric PDecl = PDecl->getDefinition(); 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric // For an objc container, delay protocol reference checking until after we 13380b57cec5SDimitry Andric // can set the objc decl as the availability context, otherwise check now. 13390b57cec5SDimitry Andric if (!ForObjCContainer) { 1340*0fca6ea1SDimitry Andric (void)SemaRef.DiagnoseUseOfDecl(PDecl, Pair.second); 13410b57cec5SDimitry Andric } 13420b57cec5SDimitry Andric 13430b57cec5SDimitry Andric // If this is a forward declaration and we are supposed to warn in this 13440b57cec5SDimitry Andric // case, do it. 13450b57cec5SDimitry Andric // FIXME: Recover nicely in the hidden case. 13460b57cec5SDimitry Andric ObjCProtocolDecl *UndefinedProtocol; 13470b57cec5SDimitry Andric 13480b57cec5SDimitry Andric if (WarnOnDeclarations && 13490b57cec5SDimitry Andric NestedProtocolHasNoDefinition(PDecl, UndefinedProtocol)) { 13500b57cec5SDimitry Andric Diag(Pair.second, diag::warn_undef_protocolref) << Pair.first; 13510b57cec5SDimitry Andric Diag(UndefinedProtocol->getLocation(), diag::note_protocol_decl_undefined) 13520b57cec5SDimitry Andric << UndefinedProtocol; 13530b57cec5SDimitry Andric } 13540b57cec5SDimitry Andric Protocols.push_back(PDecl); 13550b57cec5SDimitry Andric } 13560b57cec5SDimitry Andric } 13570b57cec5SDimitry Andric 13580b57cec5SDimitry Andric namespace { 13590b57cec5SDimitry Andric // Callback to only accept typo corrections that are either 13600b57cec5SDimitry Andric // Objective-C protocols or valid Objective-C type arguments. 13610b57cec5SDimitry Andric class ObjCTypeArgOrProtocolValidatorCCC final 13620b57cec5SDimitry Andric : public CorrectionCandidateCallback { 13630b57cec5SDimitry Andric ASTContext &Context; 13640b57cec5SDimitry Andric Sema::LookupNameKind LookupKind; 13650b57cec5SDimitry Andric public: 13660b57cec5SDimitry Andric ObjCTypeArgOrProtocolValidatorCCC(ASTContext &context, 13670b57cec5SDimitry Andric Sema::LookupNameKind lookupKind) 13680b57cec5SDimitry Andric : Context(context), LookupKind(lookupKind) { } 13690b57cec5SDimitry Andric 13700b57cec5SDimitry Andric bool ValidateCandidate(const TypoCorrection &candidate) override { 13710b57cec5SDimitry Andric // If we're allowed to find protocols and we have a protocol, accept it. 13720b57cec5SDimitry Andric if (LookupKind != Sema::LookupOrdinaryName) { 13730b57cec5SDimitry Andric if (candidate.getCorrectionDeclAs<ObjCProtocolDecl>()) 13740b57cec5SDimitry Andric return true; 13750b57cec5SDimitry Andric } 13760b57cec5SDimitry Andric 13770b57cec5SDimitry Andric // If we're allowed to find type names and we have one, accept it. 13780b57cec5SDimitry Andric if (LookupKind != Sema::LookupObjCProtocolName) { 13790b57cec5SDimitry Andric // If we have a type declaration, we might accept this result. 13800b57cec5SDimitry Andric if (auto typeDecl = candidate.getCorrectionDeclAs<TypeDecl>()) { 13810b57cec5SDimitry Andric // If we found a tag declaration outside of C++, skip it. This 13820b57cec5SDimitry Andric // can happy because we look for any name when there is no 13830b57cec5SDimitry Andric // bias to protocol or type names. 13840b57cec5SDimitry Andric if (isa<RecordDecl>(typeDecl) && !Context.getLangOpts().CPlusPlus) 13850b57cec5SDimitry Andric return false; 13860b57cec5SDimitry Andric 13870b57cec5SDimitry Andric // Make sure the type is something we would accept as a type 13880b57cec5SDimitry Andric // argument. 13890b57cec5SDimitry Andric auto type = Context.getTypeDeclType(typeDecl); 13900b57cec5SDimitry Andric if (type->isObjCObjectPointerType() || 13910b57cec5SDimitry Andric type->isBlockPointerType() || 13920b57cec5SDimitry Andric type->isDependentType() || 13930b57cec5SDimitry Andric type->isObjCObjectType()) 13940b57cec5SDimitry Andric return true; 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric return false; 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric 13990b57cec5SDimitry Andric // If we have an Objective-C class type, accept it; there will 14000b57cec5SDimitry Andric // be another fix to add the '*'. 14010b57cec5SDimitry Andric if (candidate.getCorrectionDeclAs<ObjCInterfaceDecl>()) 14020b57cec5SDimitry Andric return true; 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric return false; 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric 14070b57cec5SDimitry Andric return false; 14080b57cec5SDimitry Andric } 14090b57cec5SDimitry Andric 14100b57cec5SDimitry Andric std::unique_ptr<CorrectionCandidateCallback> clone() override { 1411a7dea167SDimitry Andric return std::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this); 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric }; 14140b57cec5SDimitry Andric } // end anonymous namespace 14150b57cec5SDimitry Andric 1416*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseTypeArgsAndProtocols(IdentifierInfo *ProtocolId, 14170b57cec5SDimitry Andric SourceLocation ProtocolLoc, 14180b57cec5SDimitry Andric IdentifierInfo *TypeArgId, 14190b57cec5SDimitry Andric SourceLocation TypeArgLoc, 14200b57cec5SDimitry Andric bool SelectProtocolFirst) { 14210b57cec5SDimitry Andric Diag(TypeArgLoc, diag::err_objc_type_args_and_protocols) 14220b57cec5SDimitry Andric << SelectProtocolFirst << TypeArgId << ProtocolId 14230b57cec5SDimitry Andric << SourceRange(ProtocolLoc); 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 1426*0fca6ea1SDimitry Andric void SemaObjC::actOnObjCTypeArgsOrProtocolQualifiers( 1427*0fca6ea1SDimitry Andric Scope *S, ParsedType baseType, SourceLocation lAngleLoc, 14280b57cec5SDimitry Andric ArrayRef<IdentifierInfo *> identifiers, 1429*0fca6ea1SDimitry Andric ArrayRef<SourceLocation> identifierLocs, SourceLocation rAngleLoc, 1430*0fca6ea1SDimitry Andric SourceLocation &typeArgsLAngleLoc, SmallVectorImpl<ParsedType> &typeArgs, 1431*0fca6ea1SDimitry Andric SourceLocation &typeArgsRAngleLoc, SourceLocation &protocolLAngleLoc, 1432*0fca6ea1SDimitry Andric SmallVectorImpl<Decl *> &protocols, SourceLocation &protocolRAngleLoc, 14330b57cec5SDimitry Andric bool warnOnIncompleteProtocols) { 1434*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 14350b57cec5SDimitry Andric // Local function that updates the declaration specifiers with 14360b57cec5SDimitry Andric // protocol information. 14370b57cec5SDimitry Andric unsigned numProtocolsResolved = 0; 14380b57cec5SDimitry Andric auto resolvedAsProtocols = [&] { 14390b57cec5SDimitry Andric assert(numProtocolsResolved == identifiers.size() && "Unresolved protocols"); 14400b57cec5SDimitry Andric 14410b57cec5SDimitry Andric // Determine whether the base type is a parameterized class, in 14420b57cec5SDimitry Andric // which case we want to warn about typos such as 14430b57cec5SDimitry Andric // "NSArray<NSObject>" (that should be NSArray<NSObject *>). 14440b57cec5SDimitry Andric ObjCInterfaceDecl *baseClass = nullptr; 1445*0fca6ea1SDimitry Andric QualType base = SemaRef.GetTypeFromParser(baseType, nullptr); 14460b57cec5SDimitry Andric bool allAreTypeNames = false; 14470b57cec5SDimitry Andric SourceLocation firstClassNameLoc; 14480b57cec5SDimitry Andric if (!base.isNull()) { 14490b57cec5SDimitry Andric if (const auto *objcObjectType = base->getAs<ObjCObjectType>()) { 14500b57cec5SDimitry Andric baseClass = objcObjectType->getInterface(); 14510b57cec5SDimitry Andric if (baseClass) { 14520b57cec5SDimitry Andric if (auto typeParams = baseClass->getTypeParamList()) { 14530b57cec5SDimitry Andric if (typeParams->size() == numProtocolsResolved) { 14540b57cec5SDimitry Andric // Note that we should be looking for type names, too. 14550b57cec5SDimitry Andric allAreTypeNames = true; 14560b57cec5SDimitry Andric } 14570b57cec5SDimitry Andric } 14580b57cec5SDimitry Andric } 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric } 14610b57cec5SDimitry Andric 14620b57cec5SDimitry Andric for (unsigned i = 0, n = protocols.size(); i != n; ++i) { 14630b57cec5SDimitry Andric ObjCProtocolDecl *&proto 14640b57cec5SDimitry Andric = reinterpret_cast<ObjCProtocolDecl *&>(protocols[i]); 14650b57cec5SDimitry Andric // For an objc container, delay protocol reference checking until after we 14660b57cec5SDimitry Andric // can set the objc decl as the availability context, otherwise check now. 14670b57cec5SDimitry Andric if (!warnOnIncompleteProtocols) { 1468*0fca6ea1SDimitry Andric (void)SemaRef.DiagnoseUseOfDecl(proto, identifierLocs[i]); 14690b57cec5SDimitry Andric } 14700b57cec5SDimitry Andric 14710b57cec5SDimitry Andric // If this is a forward protocol declaration, get its definition. 14720b57cec5SDimitry Andric if (!proto->isThisDeclarationADefinition() && proto->getDefinition()) 14730b57cec5SDimitry Andric proto = proto->getDefinition(); 14740b57cec5SDimitry Andric 14750b57cec5SDimitry Andric // If this is a forward declaration and we are supposed to warn in this 14760b57cec5SDimitry Andric // case, do it. 14770b57cec5SDimitry Andric // FIXME: Recover nicely in the hidden case. 14780b57cec5SDimitry Andric ObjCProtocolDecl *forwardDecl = nullptr; 14790b57cec5SDimitry Andric if (warnOnIncompleteProtocols && 14800b57cec5SDimitry Andric NestedProtocolHasNoDefinition(proto, forwardDecl)) { 14810b57cec5SDimitry Andric Diag(identifierLocs[i], diag::warn_undef_protocolref) 14820b57cec5SDimitry Andric << proto->getDeclName(); 14830b57cec5SDimitry Andric Diag(forwardDecl->getLocation(), diag::note_protocol_decl_undefined) 14840b57cec5SDimitry Andric << forwardDecl; 14850b57cec5SDimitry Andric } 14860b57cec5SDimitry Andric 14870b57cec5SDimitry Andric // If everything this far has been a type name (and we care 14880b57cec5SDimitry Andric // about such things), check whether this name refers to a type 14890b57cec5SDimitry Andric // as well. 14900b57cec5SDimitry Andric if (allAreTypeNames) { 1491*0fca6ea1SDimitry Andric if (auto *decl = 1492*0fca6ea1SDimitry Andric SemaRef.LookupSingleName(S, identifiers[i], identifierLocs[i], 1493*0fca6ea1SDimitry Andric Sema::LookupOrdinaryName)) { 14940b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(decl)) { 14950b57cec5SDimitry Andric if (firstClassNameLoc.isInvalid()) 14960b57cec5SDimitry Andric firstClassNameLoc = identifierLocs[i]; 14970b57cec5SDimitry Andric } else if (!isa<TypeDecl>(decl)) { 14980b57cec5SDimitry Andric // Not a type. 14990b57cec5SDimitry Andric allAreTypeNames = false; 15000b57cec5SDimitry Andric } 15010b57cec5SDimitry Andric } else { 15020b57cec5SDimitry Andric allAreTypeNames = false; 15030b57cec5SDimitry Andric } 15040b57cec5SDimitry Andric } 15050b57cec5SDimitry Andric } 15060b57cec5SDimitry Andric 15070b57cec5SDimitry Andric // All of the protocols listed also have type names, and at least 15080b57cec5SDimitry Andric // one is an Objective-C class name. Check whether all of the 15090b57cec5SDimitry Andric // protocol conformances are declared by the base class itself, in 15100b57cec5SDimitry Andric // which case we warn. 15110b57cec5SDimitry Andric if (allAreTypeNames && firstClassNameLoc.isValid()) { 15120b57cec5SDimitry Andric llvm::SmallPtrSet<ObjCProtocolDecl*, 8> knownProtocols; 15130b57cec5SDimitry Andric Context.CollectInheritedProtocols(baseClass, knownProtocols); 15140b57cec5SDimitry Andric bool allProtocolsDeclared = true; 1515bdd1243dSDimitry Andric for (auto *proto : protocols) { 15160b57cec5SDimitry Andric if (knownProtocols.count(static_cast<ObjCProtocolDecl *>(proto)) == 0) { 15170b57cec5SDimitry Andric allProtocolsDeclared = false; 15180b57cec5SDimitry Andric break; 15190b57cec5SDimitry Andric } 15200b57cec5SDimitry Andric } 15210b57cec5SDimitry Andric 15220b57cec5SDimitry Andric if (allProtocolsDeclared) { 15230b57cec5SDimitry Andric Diag(firstClassNameLoc, diag::warn_objc_redundant_qualified_class_type) 15240b57cec5SDimitry Andric << baseClass->getDeclName() << SourceRange(lAngleLoc, rAngleLoc) 1525*0fca6ea1SDimitry Andric << FixItHint::CreateInsertion( 1526*0fca6ea1SDimitry Andric SemaRef.getLocForEndOfToken(firstClassNameLoc), " *"); 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric 15300b57cec5SDimitry Andric protocolLAngleLoc = lAngleLoc; 15310b57cec5SDimitry Andric protocolRAngleLoc = rAngleLoc; 15320b57cec5SDimitry Andric assert(protocols.size() == identifierLocs.size()); 15330b57cec5SDimitry Andric }; 15340b57cec5SDimitry Andric 15350b57cec5SDimitry Andric // Attempt to resolve all of the identifiers as protocols. 15360b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 15370b57cec5SDimitry Andric ObjCProtocolDecl *proto = LookupProtocol(identifiers[i], identifierLocs[i]); 15380b57cec5SDimitry Andric protocols.push_back(proto); 15390b57cec5SDimitry Andric if (proto) 15400b57cec5SDimitry Andric ++numProtocolsResolved; 15410b57cec5SDimitry Andric } 15420b57cec5SDimitry Andric 15430b57cec5SDimitry Andric // If all of the names were protocols, these were protocol qualifiers. 15440b57cec5SDimitry Andric if (numProtocolsResolved == identifiers.size()) 15450b57cec5SDimitry Andric return resolvedAsProtocols(); 15460b57cec5SDimitry Andric 15470b57cec5SDimitry Andric // Attempt to resolve all of the identifiers as type names or 15480b57cec5SDimitry Andric // Objective-C class names. The latter is technically ill-formed, 15490b57cec5SDimitry Andric // but is probably something like \c NSArray<NSView *> missing the 15500b57cec5SDimitry Andric // \c*. 15510b57cec5SDimitry Andric typedef llvm::PointerUnion<TypeDecl *, ObjCInterfaceDecl *> TypeOrClassDecl; 15520b57cec5SDimitry Andric SmallVector<TypeOrClassDecl, 4> typeDecls; 15530b57cec5SDimitry Andric unsigned numTypeDeclsResolved = 0; 15540b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 1555*0fca6ea1SDimitry Andric NamedDecl *decl = SemaRef.LookupSingleName( 1556*0fca6ea1SDimitry Andric S, identifiers[i], identifierLocs[i], Sema::LookupOrdinaryName); 15570b57cec5SDimitry Andric if (!decl) { 15580b57cec5SDimitry Andric typeDecls.push_back(TypeOrClassDecl()); 15590b57cec5SDimitry Andric continue; 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric 15620b57cec5SDimitry Andric if (auto typeDecl = dyn_cast<TypeDecl>(decl)) { 15630b57cec5SDimitry Andric typeDecls.push_back(typeDecl); 15640b57cec5SDimitry Andric ++numTypeDeclsResolved; 15650b57cec5SDimitry Andric continue; 15660b57cec5SDimitry Andric } 15670b57cec5SDimitry Andric 15680b57cec5SDimitry Andric if (auto objcClass = dyn_cast<ObjCInterfaceDecl>(decl)) { 15690b57cec5SDimitry Andric typeDecls.push_back(objcClass); 15700b57cec5SDimitry Andric ++numTypeDeclsResolved; 15710b57cec5SDimitry Andric continue; 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric typeDecls.push_back(TypeOrClassDecl()); 15750b57cec5SDimitry Andric } 15760b57cec5SDimitry Andric 15770b57cec5SDimitry Andric AttributeFactory attrFactory; 15780b57cec5SDimitry Andric 15790b57cec5SDimitry Andric // Local function that forms a reference to the given type or 15800b57cec5SDimitry Andric // Objective-C class declaration. 15810b57cec5SDimitry Andric auto resolveTypeReference = [&](TypeOrClassDecl typeDecl, SourceLocation loc) 15820b57cec5SDimitry Andric -> TypeResult { 15830b57cec5SDimitry Andric // Form declaration specifiers. They simply refer to the type. 15840b57cec5SDimitry Andric DeclSpec DS(attrFactory); 15850b57cec5SDimitry Andric const char* prevSpec; // unused 15860b57cec5SDimitry Andric unsigned diagID; // unused 15870b57cec5SDimitry Andric QualType type; 15880b57cec5SDimitry Andric if (auto *actualTypeDecl = typeDecl.dyn_cast<TypeDecl *>()) 15890b57cec5SDimitry Andric type = Context.getTypeDeclType(actualTypeDecl); 15900b57cec5SDimitry Andric else 15910b57cec5SDimitry Andric type = Context.getObjCInterfaceType(typeDecl.get<ObjCInterfaceDecl *>()); 15920b57cec5SDimitry Andric TypeSourceInfo *parsedTSInfo = Context.getTrivialTypeSourceInfo(type, loc); 1593*0fca6ea1SDimitry Andric ParsedType parsedType = SemaRef.CreateParsedType(type, parsedTSInfo); 15940b57cec5SDimitry Andric DS.SetTypeSpecType(DeclSpec::TST_typename, loc, prevSpec, diagID, 15950b57cec5SDimitry Andric parsedType, Context.getPrintingPolicy()); 15960b57cec5SDimitry Andric // Use the identifier location for the type source range. 15970b57cec5SDimitry Andric DS.SetRangeStart(loc); 15980b57cec5SDimitry Andric DS.SetRangeEnd(loc); 15990b57cec5SDimitry Andric 16000b57cec5SDimitry Andric // Form the declarator. 160181ad6265SDimitry Andric Declarator D(DS, ParsedAttributesView::none(), DeclaratorContext::TypeName); 16020b57cec5SDimitry Andric 16030b57cec5SDimitry Andric // If we have a typedef of an Objective-C class type that is missing a '*', 16040b57cec5SDimitry Andric // add the '*'. 16050b57cec5SDimitry Andric if (type->getAs<ObjCInterfaceType>()) { 1606*0fca6ea1SDimitry Andric SourceLocation starLoc = SemaRef.getLocForEndOfToken(loc); 16070b57cec5SDimitry Andric D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc, 16080b57cec5SDimitry Andric SourceLocation(), 16090b57cec5SDimitry Andric SourceLocation(), 16100b57cec5SDimitry Andric SourceLocation(), 16110b57cec5SDimitry Andric SourceLocation(), 16120b57cec5SDimitry Andric SourceLocation()), 16130b57cec5SDimitry Andric starLoc); 16140b57cec5SDimitry Andric 16150b57cec5SDimitry Andric // Diagnose the missing '*'. 16160b57cec5SDimitry Andric Diag(loc, diag::err_objc_type_arg_missing_star) 16170b57cec5SDimitry Andric << type 16180b57cec5SDimitry Andric << FixItHint::CreateInsertion(starLoc, " *"); 16190b57cec5SDimitry Andric } 16200b57cec5SDimitry Andric 16210b57cec5SDimitry Andric // Convert this to a type. 1622*0fca6ea1SDimitry Andric return SemaRef.ActOnTypeName(D); 16230b57cec5SDimitry Andric }; 16240b57cec5SDimitry Andric 16250b57cec5SDimitry Andric // Local function that updates the declaration specifiers with 16260b57cec5SDimitry Andric // type argument information. 16270b57cec5SDimitry Andric auto resolvedAsTypeDecls = [&] { 16280b57cec5SDimitry Andric // We did not resolve these as protocols. 16290b57cec5SDimitry Andric protocols.clear(); 16300b57cec5SDimitry Andric 16310b57cec5SDimitry Andric assert(numTypeDeclsResolved == identifiers.size() && "Unresolved type decl"); 16320b57cec5SDimitry Andric // Map type declarations to type arguments. 16330b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 16340b57cec5SDimitry Andric // Map type reference to a type. 16350b57cec5SDimitry Andric TypeResult type = resolveTypeReference(typeDecls[i], identifierLocs[i]); 16360b57cec5SDimitry Andric if (!type.isUsable()) { 16370b57cec5SDimitry Andric typeArgs.clear(); 16380b57cec5SDimitry Andric return; 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 16410b57cec5SDimitry Andric typeArgs.push_back(type.get()); 16420b57cec5SDimitry Andric } 16430b57cec5SDimitry Andric 16440b57cec5SDimitry Andric typeArgsLAngleLoc = lAngleLoc; 16450b57cec5SDimitry Andric typeArgsRAngleLoc = rAngleLoc; 16460b57cec5SDimitry Andric }; 16470b57cec5SDimitry Andric 16480b57cec5SDimitry Andric // If all of the identifiers can be resolved as type names or 16490b57cec5SDimitry Andric // Objective-C class names, we have type arguments. 16500b57cec5SDimitry Andric if (numTypeDeclsResolved == identifiers.size()) 16510b57cec5SDimitry Andric return resolvedAsTypeDecls(); 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric // Error recovery: some names weren't found, or we have a mix of 16540b57cec5SDimitry Andric // type and protocol names. Go resolve all of the unresolved names 16550b57cec5SDimitry Andric // and complain if we can't find a consistent answer. 1656*0fca6ea1SDimitry Andric Sema::LookupNameKind lookupKind = Sema::LookupAnyName; 16570b57cec5SDimitry Andric for (unsigned i = 0, n = identifiers.size(); i != n; ++i) { 16580b57cec5SDimitry Andric // If we already have a protocol or type. Check whether it is the 16590b57cec5SDimitry Andric // right thing. 16600b57cec5SDimitry Andric if (protocols[i] || typeDecls[i]) { 16610b57cec5SDimitry Andric // If we haven't figured out whether we want types or protocols 16620b57cec5SDimitry Andric // yet, try to figure it out from this name. 1663*0fca6ea1SDimitry Andric if (lookupKind == Sema::LookupAnyName) { 16640b57cec5SDimitry Andric // If this name refers to both a protocol and a type (e.g., \c 16650b57cec5SDimitry Andric // NSObject), don't conclude anything yet. 16660b57cec5SDimitry Andric if (protocols[i] && typeDecls[i]) 16670b57cec5SDimitry Andric continue; 16680b57cec5SDimitry Andric 16690b57cec5SDimitry Andric // Otherwise, let this name decide whether we'll be correcting 16700b57cec5SDimitry Andric // toward types or protocols. 1671*0fca6ea1SDimitry Andric lookupKind = protocols[i] ? Sema::LookupObjCProtocolName 1672*0fca6ea1SDimitry Andric : Sema::LookupOrdinaryName; 16730b57cec5SDimitry Andric continue; 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric 16760b57cec5SDimitry Andric // If we want protocols and we have a protocol, there's nothing 16770b57cec5SDimitry Andric // more to do. 1678*0fca6ea1SDimitry Andric if (lookupKind == Sema::LookupObjCProtocolName && protocols[i]) 16790b57cec5SDimitry Andric continue; 16800b57cec5SDimitry Andric 16810b57cec5SDimitry Andric // If we want types and we have a type declaration, there's 16820b57cec5SDimitry Andric // nothing more to do. 1683*0fca6ea1SDimitry Andric if (lookupKind == Sema::LookupOrdinaryName && typeDecls[i]) 16840b57cec5SDimitry Andric continue; 16850b57cec5SDimitry Andric 16860b57cec5SDimitry Andric // We have a conflict: some names refer to protocols and others 16870b57cec5SDimitry Andric // refer to types. 16880b57cec5SDimitry Andric DiagnoseTypeArgsAndProtocols(identifiers[0], identifierLocs[0], 16890b57cec5SDimitry Andric identifiers[i], identifierLocs[i], 16900b57cec5SDimitry Andric protocols[i] != nullptr); 16910b57cec5SDimitry Andric 16920b57cec5SDimitry Andric protocols.clear(); 16930b57cec5SDimitry Andric typeArgs.clear(); 16940b57cec5SDimitry Andric return; 16950b57cec5SDimitry Andric } 16960b57cec5SDimitry Andric 16970b57cec5SDimitry Andric // Perform typo correction on the name. 16980b57cec5SDimitry Andric ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind); 1699*0fca6ea1SDimitry Andric TypoCorrection corrected = SemaRef.CorrectTypo( 1700*0fca6ea1SDimitry Andric DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S, 1701*0fca6ea1SDimitry Andric nullptr, CCC, Sema::CTK_ErrorRecovery); 17020b57cec5SDimitry Andric if (corrected) { 17030b57cec5SDimitry Andric // Did we find a protocol? 17040b57cec5SDimitry Andric if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) { 1705*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(corrected, 17060b57cec5SDimitry Andric PDiag(diag::err_undeclared_protocol_suggest) 17070b57cec5SDimitry Andric << identifiers[i]); 1708*0fca6ea1SDimitry Andric lookupKind = Sema::LookupObjCProtocolName; 17090b57cec5SDimitry Andric protocols[i] = proto; 17100b57cec5SDimitry Andric ++numProtocolsResolved; 17110b57cec5SDimitry Andric continue; 17120b57cec5SDimitry Andric } 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric // Did we find a type? 17150b57cec5SDimitry Andric if (auto typeDecl = corrected.getCorrectionDeclAs<TypeDecl>()) { 1716*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(corrected, 17170b57cec5SDimitry Andric PDiag(diag::err_unknown_typename_suggest) 17180b57cec5SDimitry Andric << identifiers[i]); 1719*0fca6ea1SDimitry Andric lookupKind = Sema::LookupOrdinaryName; 17200b57cec5SDimitry Andric typeDecls[i] = typeDecl; 17210b57cec5SDimitry Andric ++numTypeDeclsResolved; 17220b57cec5SDimitry Andric continue; 17230b57cec5SDimitry Andric } 17240b57cec5SDimitry Andric 17250b57cec5SDimitry Andric // Did we find an Objective-C class? 17260b57cec5SDimitry Andric if (auto objcClass = corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { 1727*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(corrected, 17280b57cec5SDimitry Andric PDiag(diag::err_unknown_type_or_class_name_suggest) 17290b57cec5SDimitry Andric << identifiers[i] << true); 1730*0fca6ea1SDimitry Andric lookupKind = Sema::LookupOrdinaryName; 17310b57cec5SDimitry Andric typeDecls[i] = objcClass; 17320b57cec5SDimitry Andric ++numTypeDeclsResolved; 17330b57cec5SDimitry Andric continue; 17340b57cec5SDimitry Andric } 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric 17370b57cec5SDimitry Andric // We couldn't find anything. 17380b57cec5SDimitry Andric Diag(identifierLocs[i], 1739*0fca6ea1SDimitry Andric (lookupKind == Sema::LookupAnyName ? diag::err_objc_type_arg_missing 1740*0fca6ea1SDimitry Andric : lookupKind == Sema::LookupObjCProtocolName 1741*0fca6ea1SDimitry Andric ? diag::err_undeclared_protocol 17420b57cec5SDimitry Andric : diag::err_unknown_typename)) 17430b57cec5SDimitry Andric << identifiers[i]; 17440b57cec5SDimitry Andric protocols.clear(); 17450b57cec5SDimitry Andric typeArgs.clear(); 17460b57cec5SDimitry Andric return; 17470b57cec5SDimitry Andric } 17480b57cec5SDimitry Andric 17490b57cec5SDimitry Andric // If all of the names were (corrected to) protocols, these were 17500b57cec5SDimitry Andric // protocol qualifiers. 17510b57cec5SDimitry Andric if (numProtocolsResolved == identifiers.size()) 17520b57cec5SDimitry Andric return resolvedAsProtocols(); 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric // Otherwise, all of the names were (corrected to) types. 17550b57cec5SDimitry Andric assert(numTypeDeclsResolved == identifiers.size() && "Not all types?"); 17560b57cec5SDimitry Andric return resolvedAsTypeDecls(); 17570b57cec5SDimitry Andric } 17580b57cec5SDimitry Andric 17590b57cec5SDimitry Andric /// DiagnoseClassExtensionDupMethods - Check for duplicate declaration of 17600b57cec5SDimitry Andric /// a class method in its extension. 17610b57cec5SDimitry Andric /// 1762*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, 17630b57cec5SDimitry Andric ObjCInterfaceDecl *ID) { 17640b57cec5SDimitry Andric if (!ID) 17650b57cec5SDimitry Andric return; // Possibly due to previous error 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap; 17680b57cec5SDimitry Andric for (auto *MD : ID->methods()) 17690b57cec5SDimitry Andric MethodMap[MD->getSelector()] = MD; 17700b57cec5SDimitry Andric 17710b57cec5SDimitry Andric if (MethodMap.empty()) 17720b57cec5SDimitry Andric return; 17730b57cec5SDimitry Andric for (const auto *Method : CAT->methods()) { 17740b57cec5SDimitry Andric const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; 17750b57cec5SDimitry Andric if (PrevMethod && 17760b57cec5SDimitry Andric (PrevMethod->isInstanceMethod() == Method->isInstanceMethod()) && 17770b57cec5SDimitry Andric !MatchTwoMethodDeclarations(Method, PrevMethod)) { 17780b57cec5SDimitry Andric Diag(Method->getLocation(), diag::err_duplicate_method_decl) 17790b57cec5SDimitry Andric << Method->getDeclName(); 17800b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 17810b57cec5SDimitry Andric } 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric } 17840b57cec5SDimitry Andric 17850b57cec5SDimitry Andric /// ActOnForwardProtocolDeclaration - Handle \@protocol foo; 1786*0fca6ea1SDimitry Andric SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardProtocolDeclaration( 1787*0fca6ea1SDimitry Andric SourceLocation AtProtocolLoc, ArrayRef<IdentifierLocPair> IdentList, 17880b57cec5SDimitry Andric const ParsedAttributesView &attrList) { 1789*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 17900b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup; 17910b57cec5SDimitry Andric for (const IdentifierLocPair &IdentPair : IdentList) { 17920b57cec5SDimitry Andric IdentifierInfo *Ident = IdentPair.first; 1793*0fca6ea1SDimitry Andric ObjCProtocolDecl *PrevDecl = LookupProtocol( 1794*0fca6ea1SDimitry Andric Ident, IdentPair.second, SemaRef.forRedeclarationInCurContext()); 1795*0fca6ea1SDimitry Andric ObjCProtocolDecl *PDecl = 1796*0fca6ea1SDimitry Andric ObjCProtocolDecl::Create(Context, SemaRef.CurContext, Ident, 1797*0fca6ea1SDimitry Andric IdentPair.second, AtProtocolLoc, PrevDecl); 17980b57cec5SDimitry Andric 1799*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(PDecl, SemaRef.TUScope); 18000b57cec5SDimitry Andric CheckObjCDeclScope(PDecl); 18010b57cec5SDimitry Andric 1802*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, PDecl, attrList); 1803*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, PDecl); 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric if (PrevDecl) 1806*0fca6ea1SDimitry Andric SemaRef.mergeDeclAttributes(PDecl, PrevDecl); 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric DeclsInGroup.push_back(PDecl); 18090b57cec5SDimitry Andric } 18100b57cec5SDimitry Andric 1811*0fca6ea1SDimitry Andric return SemaRef.BuildDeclaratorGroup(DeclsInGroup); 18120b57cec5SDimitry Andric } 18130b57cec5SDimitry Andric 1814*0fca6ea1SDimitry Andric ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface( 1815*0fca6ea1SDimitry Andric SourceLocation AtInterfaceLoc, const IdentifierInfo *ClassName, 18160b57cec5SDimitry Andric SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, 1817*0fca6ea1SDimitry Andric const IdentifierInfo *CategoryName, SourceLocation CategoryLoc, 18180b57cec5SDimitry Andric Decl *const *ProtoRefs, unsigned NumProtoRefs, 18190b57cec5SDimitry Andric const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, 18200b57cec5SDimitry Andric const ParsedAttributesView &AttrList) { 1821*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 18220b57cec5SDimitry Andric ObjCCategoryDecl *CDecl; 18230b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); 18240b57cec5SDimitry Andric 18250b57cec5SDimitry Andric /// Check that class of this category is already completely declared. 18260b57cec5SDimitry Andric 1827*0fca6ea1SDimitry Andric if (!IDecl || 1828*0fca6ea1SDimitry Andric SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), 18290b57cec5SDimitry Andric diag::err_category_forward_interface, 18300b57cec5SDimitry Andric CategoryName == nullptr)) { 18310b57cec5SDimitry Andric // Create an invalid ObjCCategoryDecl to serve as context for 18320b57cec5SDimitry Andric // the enclosing method declarations. We mark the decl invalid 18330b57cec5SDimitry Andric // to make it clear that this isn't a valid AST. 1834*0fca6ea1SDimitry Andric CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, 1835*0fca6ea1SDimitry Andric AtInterfaceLoc, ClassLoc, CategoryLoc, 1836*0fca6ea1SDimitry Andric CategoryName, IDecl, typeParamList); 18370b57cec5SDimitry Andric CDecl->setInvalidDecl(); 1838*0fca6ea1SDimitry Andric SemaRef.CurContext->addDecl(CDecl); 18390b57cec5SDimitry Andric 18400b57cec5SDimitry Andric if (!IDecl) 18410b57cec5SDimitry Andric Diag(ClassLoc, diag::err_undef_interface) << ClassName; 184281ad6265SDimitry Andric ActOnObjCContainerStartDefinition(CDecl); 184381ad6265SDimitry Andric return CDecl; 18440b57cec5SDimitry Andric } 18450b57cec5SDimitry Andric 18460b57cec5SDimitry Andric if (!CategoryName && IDecl->getImplementation()) { 18470b57cec5SDimitry Andric Diag(ClassLoc, diag::err_class_extension_after_impl) << ClassName; 18480b57cec5SDimitry Andric Diag(IDecl->getImplementation()->getLocation(), 18490b57cec5SDimitry Andric diag::note_implementation_declared); 18500b57cec5SDimitry Andric } 18510b57cec5SDimitry Andric 18520b57cec5SDimitry Andric if (CategoryName) { 18530b57cec5SDimitry Andric /// Check for duplicate interface declaration for this category 18540b57cec5SDimitry Andric if (ObjCCategoryDecl *Previous 18550b57cec5SDimitry Andric = IDecl->FindCategoryDeclaration(CategoryName)) { 18560b57cec5SDimitry Andric // Class extensions can be declared multiple times, categories cannot. 18570b57cec5SDimitry Andric Diag(CategoryLoc, diag::warn_dup_category_def) 18580b57cec5SDimitry Andric << ClassName << CategoryName; 18590b57cec5SDimitry Andric Diag(Previous->getLocation(), diag::note_previous_definition); 18600b57cec5SDimitry Andric } 18610b57cec5SDimitry Andric } 18620b57cec5SDimitry Andric 18630b57cec5SDimitry Andric // If we have a type parameter list, check it. 18640b57cec5SDimitry Andric if (typeParamList) { 18650b57cec5SDimitry Andric if (auto prevTypeParamList = IDecl->getTypeParamList()) { 1866*0fca6ea1SDimitry Andric if (checkTypeParamListConsistency( 1867*0fca6ea1SDimitry Andric SemaRef, prevTypeParamList, typeParamList, 1868*0fca6ea1SDimitry Andric CategoryName ? TypeParamListContext::Category 18690b57cec5SDimitry Andric : TypeParamListContext::Extension)) 18700b57cec5SDimitry Andric typeParamList = nullptr; 18710b57cec5SDimitry Andric } else { 18720b57cec5SDimitry Andric Diag(typeParamList->getLAngleLoc(), 18730b57cec5SDimitry Andric diag::err_objc_parameterized_category_nonclass) 18740b57cec5SDimitry Andric << (CategoryName != nullptr) 18750b57cec5SDimitry Andric << ClassName 18760b57cec5SDimitry Andric << typeParamList->getSourceRange(); 18770b57cec5SDimitry Andric 18780b57cec5SDimitry Andric typeParamList = nullptr; 18790b57cec5SDimitry Andric } 18800b57cec5SDimitry Andric } 18810b57cec5SDimitry Andric 1882*0fca6ea1SDimitry Andric CDecl = ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtInterfaceLoc, 18830b57cec5SDimitry Andric ClassLoc, CategoryLoc, CategoryName, IDecl, 18840b57cec5SDimitry Andric typeParamList); 18850b57cec5SDimitry Andric // FIXME: PushOnScopeChains? 1886*0fca6ea1SDimitry Andric SemaRef.CurContext->addDecl(CDecl); 18870b57cec5SDimitry Andric 18880b57cec5SDimitry Andric // Process the attributes before looking at protocols to ensure that the 18890b57cec5SDimitry Andric // availability attribute is attached to the category to provide availability 18900b57cec5SDimitry Andric // checking for protocol uses. 1891*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList); 1892*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric if (NumProtoRefs) { 1895*0fca6ea1SDimitry Andric diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs, 18960b57cec5SDimitry Andric NumProtoRefs, ProtoLocs); 18970b57cec5SDimitry Andric CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, 18980b57cec5SDimitry Andric ProtoLocs, Context); 18990b57cec5SDimitry Andric // Protocols in the class extension belong to the class. 19000b57cec5SDimitry Andric if (CDecl->IsClassExtension()) 19010b57cec5SDimitry Andric IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl*const*)ProtoRefs, 19020b57cec5SDimitry Andric NumProtoRefs, Context); 19030b57cec5SDimitry Andric } 19040b57cec5SDimitry Andric 19050b57cec5SDimitry Andric CheckObjCDeclScope(CDecl); 190681ad6265SDimitry Andric ActOnObjCContainerStartDefinition(CDecl); 190781ad6265SDimitry Andric return CDecl; 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric /// ActOnStartCategoryImplementation - Perform semantic checks on the 19110b57cec5SDimitry Andric /// category implementation declaration and build an ObjCCategoryImplDecl 19120b57cec5SDimitry Andric /// object. 1913*0fca6ea1SDimitry Andric ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation( 1914*0fca6ea1SDimitry Andric SourceLocation AtCatImplLoc, const IdentifierInfo *ClassName, 1915*0fca6ea1SDimitry Andric SourceLocation ClassLoc, const IdentifierInfo *CatName, 1916*0fca6ea1SDimitry Andric SourceLocation CatLoc, const ParsedAttributesView &Attrs) { 1917*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 19180b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); 19190b57cec5SDimitry Andric ObjCCategoryDecl *CatIDecl = nullptr; 19200b57cec5SDimitry Andric if (IDecl && IDecl->hasDefinition()) { 19210b57cec5SDimitry Andric CatIDecl = IDecl->FindCategoryDeclaration(CatName); 19220b57cec5SDimitry Andric if (!CatIDecl) { 19230b57cec5SDimitry Andric // Category @implementation with no corresponding @interface. 19240b57cec5SDimitry Andric // Create and install one. 1925*0fca6ea1SDimitry Andric CatIDecl = 1926*0fca6ea1SDimitry Andric ObjCCategoryDecl::Create(Context, SemaRef.CurContext, AtCatImplLoc, 1927*0fca6ea1SDimitry Andric ClassLoc, CatLoc, CatName, IDecl, 19280b57cec5SDimitry Andric /*typeParamList=*/nullptr); 19290b57cec5SDimitry Andric CatIDecl->setImplicit(); 19300b57cec5SDimitry Andric } 19310b57cec5SDimitry Andric } 19320b57cec5SDimitry Andric 19330b57cec5SDimitry Andric ObjCCategoryImplDecl *CDecl = 1934*0fca6ea1SDimitry Andric ObjCCategoryImplDecl::Create(Context, SemaRef.CurContext, CatName, IDecl, 19350b57cec5SDimitry Andric ClassLoc, AtCatImplLoc, CatLoc); 19360b57cec5SDimitry Andric /// Check that class of this category is already completely declared. 19370b57cec5SDimitry Andric if (!IDecl) { 19380b57cec5SDimitry Andric Diag(ClassLoc, diag::err_undef_interface) << ClassName; 19390b57cec5SDimitry Andric CDecl->setInvalidDecl(); 1940*0fca6ea1SDimitry Andric } else if (SemaRef.RequireCompleteType(ClassLoc, 1941*0fca6ea1SDimitry Andric Context.getObjCInterfaceType(IDecl), 19420b57cec5SDimitry Andric diag::err_undef_interface)) { 19430b57cec5SDimitry Andric CDecl->setInvalidDecl(); 19440b57cec5SDimitry Andric } 19450b57cec5SDimitry Andric 1946*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs); 1947*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); 19480b57cec5SDimitry Andric 19490b57cec5SDimitry Andric // FIXME: PushOnScopeChains? 1950*0fca6ea1SDimitry Andric SemaRef.CurContext->addDecl(CDecl); 19510b57cec5SDimitry Andric 19520b57cec5SDimitry Andric // If the interface has the objc_runtime_visible attribute, we 19530b57cec5SDimitry Andric // cannot implement a category for it. 19540b57cec5SDimitry Andric if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) { 19550b57cec5SDimitry Andric Diag(ClassLoc, diag::err_objc_runtime_visible_category) 19560b57cec5SDimitry Andric << IDecl->getDeclName(); 19570b57cec5SDimitry Andric } 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric /// Check that CatName, category name, is not used in another implementation. 19600b57cec5SDimitry Andric if (CatIDecl) { 19610b57cec5SDimitry Andric if (CatIDecl->getImplementation()) { 19620b57cec5SDimitry Andric Diag(ClassLoc, diag::err_dup_implementation_category) << ClassName 19630b57cec5SDimitry Andric << CatName; 19640b57cec5SDimitry Andric Diag(CatIDecl->getImplementation()->getLocation(), 19650b57cec5SDimitry Andric diag::note_previous_definition); 19660b57cec5SDimitry Andric CDecl->setInvalidDecl(); 19670b57cec5SDimitry Andric } else { 19680b57cec5SDimitry Andric CatIDecl->setImplementation(CDecl); 19690b57cec5SDimitry Andric // Warn on implementating category of deprecated class under 19700b57cec5SDimitry Andric // -Wdeprecated-implementations flag. 1971*0fca6ea1SDimitry Andric DiagnoseObjCImplementedDeprecations(SemaRef, CatIDecl, 19720b57cec5SDimitry Andric CDecl->getLocation()); 19730b57cec5SDimitry Andric } 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric 19760b57cec5SDimitry Andric CheckObjCDeclScope(CDecl); 197781ad6265SDimitry Andric ActOnObjCContainerStartDefinition(CDecl); 197881ad6265SDimitry Andric return CDecl; 19790b57cec5SDimitry Andric } 19800b57cec5SDimitry Andric 1981*0fca6ea1SDimitry Andric ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation( 1982*0fca6ea1SDimitry Andric SourceLocation AtClassImplLoc, const IdentifierInfo *ClassName, 1983*0fca6ea1SDimitry Andric SourceLocation ClassLoc, const IdentifierInfo *SuperClassname, 198481ad6265SDimitry Andric SourceLocation SuperClassLoc, const ParsedAttributesView &Attrs) { 1985*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 19860b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = nullptr; 19870b57cec5SDimitry Andric // Check for another declaration kind with the same name. 1988*0fca6ea1SDimitry Andric NamedDecl *PrevDecl = SemaRef.LookupSingleName( 1989*0fca6ea1SDimitry Andric SemaRef.TUScope, ClassName, ClassLoc, Sema::LookupOrdinaryName, 1990*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 19910b57cec5SDimitry Andric if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { 19920b57cec5SDimitry Andric Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName; 19930b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 19940b57cec5SDimitry Andric } else if ((IDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl))) { 19950b57cec5SDimitry Andric // FIXME: This will produce an error if the definition of the interface has 19960b57cec5SDimitry Andric // been imported from a module but is not visible. 1997*0fca6ea1SDimitry Andric SemaRef.RequireCompleteType(ClassLoc, Context.getObjCInterfaceType(IDecl), 19980b57cec5SDimitry Andric diag::warn_undef_interface); 19990b57cec5SDimitry Andric } else { 20000b57cec5SDimitry Andric // We did not find anything with the name ClassName; try to correct for 20010b57cec5SDimitry Andric // typos in the class name. 20020b57cec5SDimitry Andric ObjCInterfaceValidatorCCC CCC{}; 2003*0fca6ea1SDimitry Andric TypoCorrection Corrected = SemaRef.CorrectTypo( 2004*0fca6ea1SDimitry Andric DeclarationNameInfo(ClassName, ClassLoc), Sema::LookupOrdinaryName, 2005*0fca6ea1SDimitry Andric SemaRef.TUScope, nullptr, CCC, Sema::CTK_NonError); 20060b57cec5SDimitry Andric if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { 20070b57cec5SDimitry Andric // Suggest the (potentially) correct interface name. Don't provide a 20080b57cec5SDimitry Andric // code-modification hint or use the typo name for recovery, because 20090b57cec5SDimitry Andric // this is just a warning. The program may actually be correct. 2010*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo( 2011*0fca6ea1SDimitry Andric Corrected, PDiag(diag::warn_undef_interface_suggest) << ClassName, 20120b57cec5SDimitry Andric /*ErrorRecovery*/ false); 20130b57cec5SDimitry Andric } else { 20140b57cec5SDimitry Andric Diag(ClassLoc, diag::warn_undef_interface) << ClassName; 20150b57cec5SDimitry Andric } 20160b57cec5SDimitry Andric } 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric // Check that super class name is valid class name 20190b57cec5SDimitry Andric ObjCInterfaceDecl *SDecl = nullptr; 20200b57cec5SDimitry Andric if (SuperClassname) { 20210b57cec5SDimitry Andric // Check if a different kind of symbol declared in this scope. 2022*0fca6ea1SDimitry Andric PrevDecl = 2023*0fca6ea1SDimitry Andric SemaRef.LookupSingleName(SemaRef.TUScope, SuperClassname, SuperClassLoc, 2024*0fca6ea1SDimitry Andric Sema::LookupOrdinaryName); 20250b57cec5SDimitry Andric if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { 20260b57cec5SDimitry Andric Diag(SuperClassLoc, diag::err_redefinition_different_kind) 20270b57cec5SDimitry Andric << SuperClassname; 20280b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 20290b57cec5SDimitry Andric } else { 20300b57cec5SDimitry Andric SDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 20310b57cec5SDimitry Andric if (SDecl && !SDecl->hasDefinition()) 20320b57cec5SDimitry Andric SDecl = nullptr; 20330b57cec5SDimitry Andric if (!SDecl) 20340b57cec5SDimitry Andric Diag(SuperClassLoc, diag::err_undef_superclass) 20350b57cec5SDimitry Andric << SuperClassname << ClassName; 20360b57cec5SDimitry Andric else if (IDecl && !declaresSameEntity(IDecl->getSuperClass(), SDecl)) { 20370b57cec5SDimitry Andric // This implementation and its interface do not have the same 20380b57cec5SDimitry Andric // super class. 20390b57cec5SDimitry Andric Diag(SuperClassLoc, diag::err_conflicting_super_class) 20400b57cec5SDimitry Andric << SDecl->getDeclName(); 20410b57cec5SDimitry Andric Diag(SDecl->getLocation(), diag::note_previous_definition); 20420b57cec5SDimitry Andric } 20430b57cec5SDimitry Andric } 20440b57cec5SDimitry Andric } 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric if (!IDecl) { 20470b57cec5SDimitry Andric // Legacy case of @implementation with no corresponding @interface. 20480b57cec5SDimitry Andric // Build, chain & install the interface decl into the identifier. 20490b57cec5SDimitry Andric 20500b57cec5SDimitry Andric // FIXME: Do we support attributes on the @implementation? If so we should 20510b57cec5SDimitry Andric // copy them over. 2052*0fca6ea1SDimitry Andric IDecl = 2053*0fca6ea1SDimitry Andric ObjCInterfaceDecl::Create(Context, SemaRef.CurContext, AtClassImplLoc, 20540b57cec5SDimitry Andric ClassName, /*typeParamList=*/nullptr, 2055*0fca6ea1SDimitry Andric /*PrevDecl=*/nullptr, ClassLoc, true); 2056*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, IDecl); 20570b57cec5SDimitry Andric IDecl->startDefinition(); 20580b57cec5SDimitry Andric if (SDecl) { 20590b57cec5SDimitry Andric IDecl->setSuperClass(Context.getTrivialTypeSourceInfo( 20600b57cec5SDimitry Andric Context.getObjCInterfaceType(SDecl), 20610b57cec5SDimitry Andric SuperClassLoc)); 20620b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(SuperClassLoc); 20630b57cec5SDimitry Andric } else { 20640b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(ClassLoc); 20650b57cec5SDimitry Andric } 20660b57cec5SDimitry Andric 2067*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); 20680b57cec5SDimitry Andric } else { 20690b57cec5SDimitry Andric // Mark the interface as being completed, even if it was just as 20700b57cec5SDimitry Andric // @class ....; 20710b57cec5SDimitry Andric // declaration; the user cannot reopen it. 20720b57cec5SDimitry Andric if (!IDecl->hasDefinition()) 20730b57cec5SDimitry Andric IDecl->startDefinition(); 20740b57cec5SDimitry Andric } 20750b57cec5SDimitry Andric 20760b57cec5SDimitry Andric ObjCImplementationDecl *IMPDecl = 2077*0fca6ea1SDimitry Andric ObjCImplementationDecl::Create(Context, SemaRef.CurContext, IDecl, SDecl, 20780b57cec5SDimitry Andric ClassLoc, AtClassImplLoc, SuperClassLoc); 20790b57cec5SDimitry Andric 2080*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs); 2081*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl); 20820b57cec5SDimitry Andric 208381ad6265SDimitry Andric if (CheckObjCDeclScope(IMPDecl)) { 208481ad6265SDimitry Andric ActOnObjCContainerStartDefinition(IMPDecl); 208581ad6265SDimitry Andric return IMPDecl; 208681ad6265SDimitry Andric } 20870b57cec5SDimitry Andric 20880b57cec5SDimitry Andric // Check that there is no duplicate implementation of this class. 20890b57cec5SDimitry Andric if (IDecl->getImplementation()) { 20900b57cec5SDimitry Andric // FIXME: Don't leak everything! 20910b57cec5SDimitry Andric Diag(ClassLoc, diag::err_dup_implementation_class) << ClassName; 20920b57cec5SDimitry Andric Diag(IDecl->getImplementation()->getLocation(), 20930b57cec5SDimitry Andric diag::note_previous_definition); 20940b57cec5SDimitry Andric IMPDecl->setInvalidDecl(); 20950b57cec5SDimitry Andric } else { // add it to the list. 20960b57cec5SDimitry Andric IDecl->setImplementation(IMPDecl); 2097*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(IMPDecl, SemaRef.TUScope); 20980b57cec5SDimitry Andric // Warn on implementating deprecated class under 20990b57cec5SDimitry Andric // -Wdeprecated-implementations flag. 2100*0fca6ea1SDimitry Andric DiagnoseObjCImplementedDeprecations(SemaRef, IDecl, IMPDecl->getLocation()); 21010b57cec5SDimitry Andric } 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric // If the superclass has the objc_runtime_visible attribute, we 21040b57cec5SDimitry Andric // cannot implement a subclass of it. 21050b57cec5SDimitry Andric if (IDecl->getSuperClass() && 21060b57cec5SDimitry Andric IDecl->getSuperClass()->hasAttr<ObjCRuntimeVisibleAttr>()) { 21070b57cec5SDimitry Andric Diag(ClassLoc, diag::err_objc_runtime_visible_subclass) 21080b57cec5SDimitry Andric << IDecl->getDeclName() 21090b57cec5SDimitry Andric << IDecl->getSuperClass()->getDeclName(); 21100b57cec5SDimitry Andric } 21110b57cec5SDimitry Andric 211281ad6265SDimitry Andric ActOnObjCContainerStartDefinition(IMPDecl); 211381ad6265SDimitry Andric return IMPDecl; 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric 2116*0fca6ea1SDimitry Andric SemaObjC::DeclGroupPtrTy 2117*0fca6ea1SDimitry Andric SemaObjC::ActOnFinishObjCImplementation(Decl *ObjCImpDecl, 2118*0fca6ea1SDimitry Andric ArrayRef<Decl *> Decls) { 21190b57cec5SDimitry Andric SmallVector<Decl *, 64> DeclsInGroup; 21200b57cec5SDimitry Andric DeclsInGroup.reserve(Decls.size() + 1); 21210b57cec5SDimitry Andric 21220b57cec5SDimitry Andric for (unsigned i = 0, e = Decls.size(); i != e; ++i) { 21230b57cec5SDimitry Andric Decl *Dcl = Decls[i]; 21240b57cec5SDimitry Andric if (!Dcl) 21250b57cec5SDimitry Andric continue; 21260b57cec5SDimitry Andric if (Dcl->getDeclContext()->isFileContext()) 21270b57cec5SDimitry Andric Dcl->setTopLevelDeclInObjCContainer(); 21280b57cec5SDimitry Andric DeclsInGroup.push_back(Dcl); 21290b57cec5SDimitry Andric } 21300b57cec5SDimitry Andric 21310b57cec5SDimitry Andric DeclsInGroup.push_back(ObjCImpDecl); 21320b57cec5SDimitry Andric 2133*0fca6ea1SDimitry Andric return SemaRef.BuildDeclaratorGroup(DeclsInGroup); 21340b57cec5SDimitry Andric } 21350b57cec5SDimitry Andric 2136*0fca6ea1SDimitry Andric void SemaObjC::CheckImplementationIvars(ObjCImplementationDecl *ImpDecl, 21370b57cec5SDimitry Andric ObjCIvarDecl **ivars, unsigned numIvars, 21380b57cec5SDimitry Andric SourceLocation RBrace) { 21390b57cec5SDimitry Andric assert(ImpDecl && "missing implementation decl"); 2140*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 21410b57cec5SDimitry Andric ObjCInterfaceDecl* IDecl = ImpDecl->getClassInterface(); 21420b57cec5SDimitry Andric if (!IDecl) 21430b57cec5SDimitry Andric return; 21440b57cec5SDimitry Andric /// Check case of non-existing \@interface decl. 21450b57cec5SDimitry Andric /// (legacy objective-c \@implementation decl without an \@interface decl). 21460b57cec5SDimitry Andric /// Add implementations's ivar to the synthesize class's ivar list. 21470b57cec5SDimitry Andric if (IDecl->isImplicitInterfaceDecl()) { 21480b57cec5SDimitry Andric IDecl->setEndOfDefinitionLoc(RBrace); 21490b57cec5SDimitry Andric // Add ivar's to class's DeclContext. 21500b57cec5SDimitry Andric for (unsigned i = 0, e = numIvars; i != e; ++i) { 21510b57cec5SDimitry Andric ivars[i]->setLexicalDeclContext(ImpDecl); 2152e8d8bef9SDimitry Andric // In a 'fragile' runtime the ivar was added to the implicit 2153e8d8bef9SDimitry Andric // ObjCInterfaceDecl while in a 'non-fragile' runtime the ivar is 2154e8d8bef9SDimitry Andric // only in the ObjCImplementationDecl. In the non-fragile case the ivar 2155e8d8bef9SDimitry Andric // therefore also needs to be propagated to the ObjCInterfaceDecl. 2156*0fca6ea1SDimitry Andric if (!getLangOpts().ObjCRuntime.isFragile()) 21570b57cec5SDimitry Andric IDecl->makeDeclVisibleInContext(ivars[i]); 21580b57cec5SDimitry Andric ImpDecl->addDecl(ivars[i]); 21590b57cec5SDimitry Andric } 21600b57cec5SDimitry Andric 21610b57cec5SDimitry Andric return; 21620b57cec5SDimitry Andric } 21630b57cec5SDimitry Andric // If implementation has empty ivar list, just return. 21640b57cec5SDimitry Andric if (numIvars == 0) 21650b57cec5SDimitry Andric return; 21660b57cec5SDimitry Andric 21670b57cec5SDimitry Andric assert(ivars && "missing @implementation ivars"); 2168*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isNonFragile()) { 21690b57cec5SDimitry Andric if (ImpDecl->getSuperClass()) 21700b57cec5SDimitry Andric Diag(ImpDecl->getLocation(), diag::warn_on_superclass_use); 21710b57cec5SDimitry Andric for (unsigned i = 0; i < numIvars; i++) { 21720b57cec5SDimitry Andric ObjCIvarDecl* ImplIvar = ivars[i]; 21730b57cec5SDimitry Andric if (const ObjCIvarDecl *ClsIvar = 21740b57cec5SDimitry Andric IDecl->getIvarDecl(ImplIvar->getIdentifier())) { 21750b57cec5SDimitry Andric Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); 21760b57cec5SDimitry Andric Diag(ClsIvar->getLocation(), diag::note_previous_definition); 21770b57cec5SDimitry Andric continue; 21780b57cec5SDimitry Andric } 21790b57cec5SDimitry Andric // Check class extensions (unnamed categories) for duplicate ivars. 21800b57cec5SDimitry Andric for (const auto *CDecl : IDecl->visible_extensions()) { 21810b57cec5SDimitry Andric if (const ObjCIvarDecl *ClsExtIvar = 21820b57cec5SDimitry Andric CDecl->getIvarDecl(ImplIvar->getIdentifier())) { 21830b57cec5SDimitry Andric Diag(ImplIvar->getLocation(), diag::err_duplicate_ivar_declaration); 21840b57cec5SDimitry Andric Diag(ClsExtIvar->getLocation(), diag::note_previous_definition); 21850b57cec5SDimitry Andric continue; 21860b57cec5SDimitry Andric } 21870b57cec5SDimitry Andric } 21880b57cec5SDimitry Andric // Instance ivar to Implementation's DeclContext. 21890b57cec5SDimitry Andric ImplIvar->setLexicalDeclContext(ImpDecl); 21900b57cec5SDimitry Andric IDecl->makeDeclVisibleInContext(ImplIvar); 21910b57cec5SDimitry Andric ImpDecl->addDecl(ImplIvar); 21920b57cec5SDimitry Andric } 21930b57cec5SDimitry Andric return; 21940b57cec5SDimitry Andric } 21950b57cec5SDimitry Andric // Check interface's Ivar list against those in the implementation. 21960b57cec5SDimitry Andric // names and types must match. 21970b57cec5SDimitry Andric // 21980b57cec5SDimitry Andric unsigned j = 0; 21990b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator 22000b57cec5SDimitry Andric IVI = IDecl->ivar_begin(), IVE = IDecl->ivar_end(); 22010b57cec5SDimitry Andric for (; numIvars > 0 && IVI != IVE; ++IVI) { 22020b57cec5SDimitry Andric ObjCIvarDecl* ImplIvar = ivars[j++]; 22030b57cec5SDimitry Andric ObjCIvarDecl* ClsIvar = *IVI; 22040b57cec5SDimitry Andric assert (ImplIvar && "missing implementation ivar"); 22050b57cec5SDimitry Andric assert (ClsIvar && "missing class ivar"); 22060b57cec5SDimitry Andric 22070b57cec5SDimitry Andric // First, make sure the types match. 22080b57cec5SDimitry Andric if (!Context.hasSameType(ImplIvar->getType(), ClsIvar->getType())) { 22090b57cec5SDimitry Andric Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_type) 22100b57cec5SDimitry Andric << ImplIvar->getIdentifier() 22110b57cec5SDimitry Andric << ImplIvar->getType() << ClsIvar->getType(); 22120b57cec5SDimitry Andric Diag(ClsIvar->getLocation(), diag::note_previous_definition); 22130b57cec5SDimitry Andric } else if (ImplIvar->isBitField() && ClsIvar->isBitField() && 22140b57cec5SDimitry Andric ImplIvar->getBitWidthValue(Context) != 22150b57cec5SDimitry Andric ClsIvar->getBitWidthValue(Context)) { 22160b57cec5SDimitry Andric Diag(ImplIvar->getBitWidth()->getBeginLoc(), 22170b57cec5SDimitry Andric diag::err_conflicting_ivar_bitwidth) 22180b57cec5SDimitry Andric << ImplIvar->getIdentifier(); 22190b57cec5SDimitry Andric Diag(ClsIvar->getBitWidth()->getBeginLoc(), 22200b57cec5SDimitry Andric diag::note_previous_definition); 22210b57cec5SDimitry Andric } 22220b57cec5SDimitry Andric // Make sure the names are identical. 22230b57cec5SDimitry Andric if (ImplIvar->getIdentifier() != ClsIvar->getIdentifier()) { 22240b57cec5SDimitry Andric Diag(ImplIvar->getLocation(), diag::err_conflicting_ivar_name) 22250b57cec5SDimitry Andric << ImplIvar->getIdentifier() << ClsIvar->getIdentifier(); 22260b57cec5SDimitry Andric Diag(ClsIvar->getLocation(), diag::note_previous_definition); 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric --numIvars; 22290b57cec5SDimitry Andric } 22300b57cec5SDimitry Andric 22310b57cec5SDimitry Andric if (numIvars > 0) 22320b57cec5SDimitry Andric Diag(ivars[j]->getLocation(), diag::err_inconsistent_ivar_count); 22330b57cec5SDimitry Andric else if (IVI != IVE) 22340b57cec5SDimitry Andric Diag(IVI->getLocation(), diag::err_inconsistent_ivar_count); 22350b57cec5SDimitry Andric } 22360b57cec5SDimitry Andric 2237*0fca6ea1SDimitry Andric static bool shouldWarnUndefinedMethod(const ObjCMethodDecl *M) { 2238*0fca6ea1SDimitry Andric // No point warning no definition of method which is 'unavailable'. 2239*0fca6ea1SDimitry Andric return M->getAvailability() != AR_Unavailable; 2240*0fca6ea1SDimitry Andric } 2241*0fca6ea1SDimitry Andric 224204eeddc0SDimitry Andric static void WarnUndefinedMethod(Sema &S, ObjCImplDecl *Impl, 224304eeddc0SDimitry Andric ObjCMethodDecl *method, bool &IncompleteImpl, 22440b57cec5SDimitry Andric unsigned DiagID, 22450b57cec5SDimitry Andric NamedDecl *NeededFor = nullptr) { 2246*0fca6ea1SDimitry Andric if (!shouldWarnUndefinedMethod(method)) 22470b57cec5SDimitry Andric return; 22480b57cec5SDimitry Andric 22490b57cec5SDimitry Andric // FIXME: For now ignore 'IncompleteImpl'. 22500b57cec5SDimitry Andric // Previously we grouped all unimplemented methods under a single 22510b57cec5SDimitry Andric // warning, but some users strongly voiced that they would prefer 22520b57cec5SDimitry Andric // separate warnings. We will give that approach a try, as that 22530b57cec5SDimitry Andric // matches what we do with protocols. 22540b57cec5SDimitry Andric { 2255*0fca6ea1SDimitry Andric const SemaBase::SemaDiagnosticBuilder &B = 2256*0fca6ea1SDimitry Andric S.Diag(Impl->getLocation(), DiagID); 22570b57cec5SDimitry Andric B << method; 22580b57cec5SDimitry Andric if (NeededFor) 22590b57cec5SDimitry Andric B << NeededFor; 226004eeddc0SDimitry Andric 226104eeddc0SDimitry Andric // Add an empty definition at the end of the @implementation. 226204eeddc0SDimitry Andric std::string FixItStr; 226304eeddc0SDimitry Andric llvm::raw_string_ostream Out(FixItStr); 226404eeddc0SDimitry Andric method->print(Out, Impl->getASTContext().getPrintingPolicy()); 226504eeddc0SDimitry Andric Out << " {\n}\n\n"; 226604eeddc0SDimitry Andric 226704eeddc0SDimitry Andric SourceLocation Loc = Impl->getAtEndRange().getBegin(); 226804eeddc0SDimitry Andric B << FixItHint::CreateInsertion(Loc, FixItStr); 22690b57cec5SDimitry Andric } 22700b57cec5SDimitry Andric 22710b57cec5SDimitry Andric // Issue a note to the original declaration. 22720b57cec5SDimitry Andric SourceLocation MethodLoc = method->getBeginLoc(); 22730b57cec5SDimitry Andric if (MethodLoc.isValid()) 22740b57cec5SDimitry Andric S.Diag(MethodLoc, diag::note_method_declared_at) << method; 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric /// Determines if type B can be substituted for type A. Returns true if we can 22780b57cec5SDimitry Andric /// guarantee that anything that the user will do to an object of type A can 22790b57cec5SDimitry Andric /// also be done to an object of type B. This is trivially true if the two 22800b57cec5SDimitry Andric /// types are the same, or if B is a subclass of A. It becomes more complex 22810b57cec5SDimitry Andric /// in cases where protocols are involved. 22820b57cec5SDimitry Andric /// 22830b57cec5SDimitry Andric /// Object types in Objective-C describe the minimum requirements for an 22840b57cec5SDimitry Andric /// object, rather than providing a complete description of a type. For 22850b57cec5SDimitry Andric /// example, if A is a subclass of B, then B* may refer to an instance of A. 22860b57cec5SDimitry Andric /// The principle of substitutability means that we may use an instance of A 22870b57cec5SDimitry Andric /// anywhere that we may use an instance of B - it will implement all of the 22880b57cec5SDimitry Andric /// ivars of B and all of the methods of B. 22890b57cec5SDimitry Andric /// 22900b57cec5SDimitry Andric /// This substitutability is important when type checking methods, because 22910b57cec5SDimitry Andric /// the implementation may have stricter type definitions than the interface. 22920b57cec5SDimitry Andric /// The interface specifies minimum requirements, but the implementation may 22930b57cec5SDimitry Andric /// have more accurate ones. For example, a method may privately accept 22940b57cec5SDimitry Andric /// instances of B, but only publish that it accepts instances of A. Any 22950b57cec5SDimitry Andric /// object passed to it will be type checked against B, and so will implicitly 22960b57cec5SDimitry Andric /// by a valid A*. Similarly, a method may return a subclass of the class that 22970b57cec5SDimitry Andric /// it is declared as returning. 22980b57cec5SDimitry Andric /// 22990b57cec5SDimitry Andric /// This is most important when considering subclassing. A method in a 23000b57cec5SDimitry Andric /// subclass must accept any object as an argument that its superclass's 23010b57cec5SDimitry Andric /// implementation accepts. It may, however, accept a more general type 23020b57cec5SDimitry Andric /// without breaking substitutability (i.e. you can still use the subclass 23030b57cec5SDimitry Andric /// anywhere that you can use the superclass, but not vice versa). The 23040b57cec5SDimitry Andric /// converse requirement applies to return types: the return type for a 23050b57cec5SDimitry Andric /// subclass method must be a valid object of the kind that the superclass 23060b57cec5SDimitry Andric /// advertises, but it may be specified more accurately. This avoids the need 23070b57cec5SDimitry Andric /// for explicit down-casting by callers. 23080b57cec5SDimitry Andric /// 23090b57cec5SDimitry Andric /// Note: This is a stricter requirement than for assignment. 23100b57cec5SDimitry Andric static bool isObjCTypeSubstitutable(ASTContext &Context, 23110b57cec5SDimitry Andric const ObjCObjectPointerType *A, 23120b57cec5SDimitry Andric const ObjCObjectPointerType *B, 23130b57cec5SDimitry Andric bool rejectId) { 23140b57cec5SDimitry Andric // Reject a protocol-unqualified id. 23150b57cec5SDimitry Andric if (rejectId && B->isObjCIdType()) return false; 23160b57cec5SDimitry Andric 23170b57cec5SDimitry Andric // If B is a qualified id, then A must also be a qualified id and it must 23180b57cec5SDimitry Andric // implement all of the protocols in B. It may not be a qualified class. 23190b57cec5SDimitry Andric // For example, MyClass<A> can be assigned to id<A>, but MyClass<A> is a 23200b57cec5SDimitry Andric // stricter definition so it is not substitutable for id<A>. 23210b57cec5SDimitry Andric if (B->isObjCQualifiedIdType()) { 23220b57cec5SDimitry Andric return A->isObjCQualifiedIdType() && 2323a7dea167SDimitry Andric Context.ObjCQualifiedIdTypesAreCompatible(A, B, false); 23240b57cec5SDimitry Andric } 23250b57cec5SDimitry Andric 23260b57cec5SDimitry Andric /* 23270b57cec5SDimitry Andric // id is a special type that bypasses type checking completely. We want a 23280b57cec5SDimitry Andric // warning when it is used in one place but not another. 23290b57cec5SDimitry Andric if (C.isObjCIdType(A) || C.isObjCIdType(B)) return false; 23300b57cec5SDimitry Andric 23310b57cec5SDimitry Andric 23320b57cec5SDimitry Andric // If B is a qualified id, then A must also be a qualified id (which it isn't 23330b57cec5SDimitry Andric // if we've got this far) 23340b57cec5SDimitry Andric if (B->isObjCQualifiedIdType()) return false; 23350b57cec5SDimitry Andric */ 23360b57cec5SDimitry Andric 23370b57cec5SDimitry Andric // Now we know that A and B are (potentially-qualified) class types. The 23380b57cec5SDimitry Andric // normal rules for assignment apply. 23390b57cec5SDimitry Andric return Context.canAssignObjCInterfaces(A, B); 23400b57cec5SDimitry Andric } 23410b57cec5SDimitry Andric 23420b57cec5SDimitry Andric static SourceRange getTypeRange(TypeSourceInfo *TSI) { 23430b57cec5SDimitry Andric return (TSI ? TSI->getTypeLoc().getSourceRange() : SourceRange()); 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric 23460b57cec5SDimitry Andric /// Determine whether two set of Objective-C declaration qualifiers conflict. 23470b57cec5SDimitry Andric static bool objcModifiersConflict(Decl::ObjCDeclQualifier x, 23480b57cec5SDimitry Andric Decl::ObjCDeclQualifier y) { 23490b57cec5SDimitry Andric return (x & ~Decl::OBJC_TQ_CSNullability) != 23500b57cec5SDimitry Andric (y & ~Decl::OBJC_TQ_CSNullability); 23510b57cec5SDimitry Andric } 23520b57cec5SDimitry Andric 23530b57cec5SDimitry Andric static bool CheckMethodOverrideReturn(Sema &S, 23540b57cec5SDimitry Andric ObjCMethodDecl *MethodImpl, 23550b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl, 23560b57cec5SDimitry Andric bool IsProtocolMethodDecl, 23570b57cec5SDimitry Andric bool IsOverridingMode, 23580b57cec5SDimitry Andric bool Warn) { 23590b57cec5SDimitry Andric if (IsProtocolMethodDecl && 23600b57cec5SDimitry Andric objcModifiersConflict(MethodDecl->getObjCDeclQualifier(), 23610b57cec5SDimitry Andric MethodImpl->getObjCDeclQualifier())) { 23620b57cec5SDimitry Andric if (Warn) { 23630b57cec5SDimitry Andric S.Diag(MethodImpl->getLocation(), 23640b57cec5SDimitry Andric (IsOverridingMode 23650b57cec5SDimitry Andric ? diag::warn_conflicting_overriding_ret_type_modifiers 23660b57cec5SDimitry Andric : diag::warn_conflicting_ret_type_modifiers)) 23670b57cec5SDimitry Andric << MethodImpl->getDeclName() 23680b57cec5SDimitry Andric << MethodImpl->getReturnTypeSourceRange(); 23690b57cec5SDimitry Andric S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration) 23700b57cec5SDimitry Andric << MethodDecl->getReturnTypeSourceRange(); 23710b57cec5SDimitry Andric } 23720b57cec5SDimitry Andric else 23730b57cec5SDimitry Andric return false; 23740b57cec5SDimitry Andric } 23750b57cec5SDimitry Andric if (Warn && IsOverridingMode && 23760b57cec5SDimitry Andric !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) && 23770b57cec5SDimitry Andric !S.Context.hasSameNullabilityTypeQualifier(MethodImpl->getReturnType(), 23780b57cec5SDimitry Andric MethodDecl->getReturnType(), 23790b57cec5SDimitry Andric false)) { 2380bdd1243dSDimitry Andric auto nullabilityMethodImpl = *MethodImpl->getReturnType()->getNullability(); 2381bdd1243dSDimitry Andric auto nullabilityMethodDecl = *MethodDecl->getReturnType()->getNullability(); 23820b57cec5SDimitry Andric S.Diag(MethodImpl->getLocation(), 23830b57cec5SDimitry Andric diag::warn_conflicting_nullability_attr_overriding_ret_types) 2384bdd1243dSDimitry Andric << DiagNullabilityKind(nullabilityMethodImpl, 2385bdd1243dSDimitry Andric ((MethodImpl->getObjCDeclQualifier() & 2386bdd1243dSDimitry Andric Decl::OBJC_TQ_CSNullability) != 0)) 2387bdd1243dSDimitry Andric << DiagNullabilityKind(nullabilityMethodDecl, 2388bdd1243dSDimitry Andric ((MethodDecl->getObjCDeclQualifier() & 2389bdd1243dSDimitry Andric Decl::OBJC_TQ_CSNullability) != 0)); 23900b57cec5SDimitry Andric S.Diag(MethodDecl->getLocation(), diag::note_previous_declaration); 23910b57cec5SDimitry Andric } 23920b57cec5SDimitry Andric 23930b57cec5SDimitry Andric if (S.Context.hasSameUnqualifiedType(MethodImpl->getReturnType(), 23940b57cec5SDimitry Andric MethodDecl->getReturnType())) 23950b57cec5SDimitry Andric return true; 23960b57cec5SDimitry Andric if (!Warn) 23970b57cec5SDimitry Andric return false; 23980b57cec5SDimitry Andric 23990b57cec5SDimitry Andric unsigned DiagID = 24000b57cec5SDimitry Andric IsOverridingMode ? diag::warn_conflicting_overriding_ret_types 24010b57cec5SDimitry Andric : diag::warn_conflicting_ret_types; 24020b57cec5SDimitry Andric 24030b57cec5SDimitry Andric // Mismatches between ObjC pointers go into a different warning 24045ffd83dbSDimitry Andric // category, and sometimes they're even completely explicitly allowed. 24050b57cec5SDimitry Andric if (const ObjCObjectPointerType *ImplPtrTy = 24060b57cec5SDimitry Andric MethodImpl->getReturnType()->getAs<ObjCObjectPointerType>()) { 24070b57cec5SDimitry Andric if (const ObjCObjectPointerType *IfacePtrTy = 24080b57cec5SDimitry Andric MethodDecl->getReturnType()->getAs<ObjCObjectPointerType>()) { 24090b57cec5SDimitry Andric // Allow non-matching return types as long as they don't violate 24100b57cec5SDimitry Andric // the principle of substitutability. Specifically, we permit 24110b57cec5SDimitry Andric // return types that are subclasses of the declared return type, 24120b57cec5SDimitry Andric // or that are more-qualified versions of the declared type. 24130b57cec5SDimitry Andric if (isObjCTypeSubstitutable(S.Context, IfacePtrTy, ImplPtrTy, false)) 24140b57cec5SDimitry Andric return false; 24150b57cec5SDimitry Andric 24160b57cec5SDimitry Andric DiagID = 24170b57cec5SDimitry Andric IsOverridingMode ? diag::warn_non_covariant_overriding_ret_types 24180b57cec5SDimitry Andric : diag::warn_non_covariant_ret_types; 24190b57cec5SDimitry Andric } 24200b57cec5SDimitry Andric } 24210b57cec5SDimitry Andric 24220b57cec5SDimitry Andric S.Diag(MethodImpl->getLocation(), DiagID) 24230b57cec5SDimitry Andric << MethodImpl->getDeclName() << MethodDecl->getReturnType() 24240b57cec5SDimitry Andric << MethodImpl->getReturnType() 24250b57cec5SDimitry Andric << MethodImpl->getReturnTypeSourceRange(); 24260b57cec5SDimitry Andric S.Diag(MethodDecl->getLocation(), IsOverridingMode 24270b57cec5SDimitry Andric ? diag::note_previous_declaration 24280b57cec5SDimitry Andric : diag::note_previous_definition) 24290b57cec5SDimitry Andric << MethodDecl->getReturnTypeSourceRange(); 24300b57cec5SDimitry Andric return false; 24310b57cec5SDimitry Andric } 24320b57cec5SDimitry Andric 24330b57cec5SDimitry Andric static bool CheckMethodOverrideParam(Sema &S, 24340b57cec5SDimitry Andric ObjCMethodDecl *MethodImpl, 24350b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl, 24360b57cec5SDimitry Andric ParmVarDecl *ImplVar, 24370b57cec5SDimitry Andric ParmVarDecl *IfaceVar, 24380b57cec5SDimitry Andric bool IsProtocolMethodDecl, 24390b57cec5SDimitry Andric bool IsOverridingMode, 24400b57cec5SDimitry Andric bool Warn) { 24410b57cec5SDimitry Andric if (IsProtocolMethodDecl && 24420b57cec5SDimitry Andric objcModifiersConflict(ImplVar->getObjCDeclQualifier(), 24430b57cec5SDimitry Andric IfaceVar->getObjCDeclQualifier())) { 24440b57cec5SDimitry Andric if (Warn) { 24450b57cec5SDimitry Andric if (IsOverridingMode) 24460b57cec5SDimitry Andric S.Diag(ImplVar->getLocation(), 24470b57cec5SDimitry Andric diag::warn_conflicting_overriding_param_modifiers) 24480b57cec5SDimitry Andric << getTypeRange(ImplVar->getTypeSourceInfo()) 24490b57cec5SDimitry Andric << MethodImpl->getDeclName(); 24500b57cec5SDimitry Andric else S.Diag(ImplVar->getLocation(), 24510b57cec5SDimitry Andric diag::warn_conflicting_param_modifiers) 24520b57cec5SDimitry Andric << getTypeRange(ImplVar->getTypeSourceInfo()) 24530b57cec5SDimitry Andric << MethodImpl->getDeclName(); 24540b57cec5SDimitry Andric S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration) 24550b57cec5SDimitry Andric << getTypeRange(IfaceVar->getTypeSourceInfo()); 24560b57cec5SDimitry Andric } 24570b57cec5SDimitry Andric else 24580b57cec5SDimitry Andric return false; 24590b57cec5SDimitry Andric } 24600b57cec5SDimitry Andric 24610b57cec5SDimitry Andric QualType ImplTy = ImplVar->getType(); 24620b57cec5SDimitry Andric QualType IfaceTy = IfaceVar->getType(); 24630b57cec5SDimitry Andric if (Warn && IsOverridingMode && 24640b57cec5SDimitry Andric !isa<ObjCImplementationDecl>(MethodImpl->getDeclContext()) && 24650b57cec5SDimitry Andric !S.Context.hasSameNullabilityTypeQualifier(ImplTy, IfaceTy, true)) { 24660b57cec5SDimitry Andric S.Diag(ImplVar->getLocation(), 24670b57cec5SDimitry Andric diag::warn_conflicting_nullability_attr_overriding_param_types) 2468bdd1243dSDimitry Andric << DiagNullabilityKind(*ImplTy->getNullability(), 2469bdd1243dSDimitry Andric ((ImplVar->getObjCDeclQualifier() & 2470bdd1243dSDimitry Andric Decl::OBJC_TQ_CSNullability) != 0)) 2471bdd1243dSDimitry Andric << DiagNullabilityKind(*IfaceTy->getNullability(), 2472bdd1243dSDimitry Andric ((IfaceVar->getObjCDeclQualifier() & 2473bdd1243dSDimitry Andric Decl::OBJC_TQ_CSNullability) != 0)); 24740b57cec5SDimitry Andric S.Diag(IfaceVar->getLocation(), diag::note_previous_declaration); 24750b57cec5SDimitry Andric } 24760b57cec5SDimitry Andric if (S.Context.hasSameUnqualifiedType(ImplTy, IfaceTy)) 24770b57cec5SDimitry Andric return true; 24780b57cec5SDimitry Andric 24790b57cec5SDimitry Andric if (!Warn) 24800b57cec5SDimitry Andric return false; 24810b57cec5SDimitry Andric unsigned DiagID = 24820b57cec5SDimitry Andric IsOverridingMode ? diag::warn_conflicting_overriding_param_types 24830b57cec5SDimitry Andric : diag::warn_conflicting_param_types; 24840b57cec5SDimitry Andric 24850b57cec5SDimitry Andric // Mismatches between ObjC pointers go into a different warning 24865ffd83dbSDimitry Andric // category, and sometimes they're even completely explicitly allowed.. 24870b57cec5SDimitry Andric if (const ObjCObjectPointerType *ImplPtrTy = 24880b57cec5SDimitry Andric ImplTy->getAs<ObjCObjectPointerType>()) { 24890b57cec5SDimitry Andric if (const ObjCObjectPointerType *IfacePtrTy = 24900b57cec5SDimitry Andric IfaceTy->getAs<ObjCObjectPointerType>()) { 24910b57cec5SDimitry Andric // Allow non-matching argument types as long as they don't 24920b57cec5SDimitry Andric // violate the principle of substitutability. Specifically, the 24930b57cec5SDimitry Andric // implementation must accept any objects that the superclass 24940b57cec5SDimitry Andric // accepts, however it may also accept others. 24950b57cec5SDimitry Andric if (isObjCTypeSubstitutable(S.Context, ImplPtrTy, IfacePtrTy, true)) 24960b57cec5SDimitry Andric return false; 24970b57cec5SDimitry Andric 24980b57cec5SDimitry Andric DiagID = 24990b57cec5SDimitry Andric IsOverridingMode ? diag::warn_non_contravariant_overriding_param_types 25000b57cec5SDimitry Andric : diag::warn_non_contravariant_param_types; 25010b57cec5SDimitry Andric } 25020b57cec5SDimitry Andric } 25030b57cec5SDimitry Andric 25040b57cec5SDimitry Andric S.Diag(ImplVar->getLocation(), DiagID) 25050b57cec5SDimitry Andric << getTypeRange(ImplVar->getTypeSourceInfo()) 25060b57cec5SDimitry Andric << MethodImpl->getDeclName() << IfaceTy << ImplTy; 25070b57cec5SDimitry Andric S.Diag(IfaceVar->getLocation(), 25080b57cec5SDimitry Andric (IsOverridingMode ? diag::note_previous_declaration 25090b57cec5SDimitry Andric : diag::note_previous_definition)) 25100b57cec5SDimitry Andric << getTypeRange(IfaceVar->getTypeSourceInfo()); 25110b57cec5SDimitry Andric return false; 25120b57cec5SDimitry Andric } 25130b57cec5SDimitry Andric 25140b57cec5SDimitry Andric /// In ARC, check whether the conventional meanings of the two methods 25150b57cec5SDimitry Andric /// match. If they don't, it's a hard error. 25160b57cec5SDimitry Andric static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, 25170b57cec5SDimitry Andric ObjCMethodDecl *decl) { 25180b57cec5SDimitry Andric ObjCMethodFamily implFamily = impl->getMethodFamily(); 25190b57cec5SDimitry Andric ObjCMethodFamily declFamily = decl->getMethodFamily(); 25200b57cec5SDimitry Andric if (implFamily == declFamily) return false; 25210b57cec5SDimitry Andric 25220b57cec5SDimitry Andric // Since conventions are sorted by selector, the only possibility is 25230b57cec5SDimitry Andric // that the types differ enough to cause one selector or the other 25240b57cec5SDimitry Andric // to fall out of the family. 25250b57cec5SDimitry Andric assert(implFamily == OMF_None || declFamily == OMF_None); 25260b57cec5SDimitry Andric 25270b57cec5SDimitry Andric // No further diagnostics required on invalid declarations. 25280b57cec5SDimitry Andric if (impl->isInvalidDecl() || decl->isInvalidDecl()) return true; 25290b57cec5SDimitry Andric 25300b57cec5SDimitry Andric const ObjCMethodDecl *unmatched = impl; 25310b57cec5SDimitry Andric ObjCMethodFamily family = declFamily; 25320b57cec5SDimitry Andric unsigned errorID = diag::err_arc_lost_method_convention; 25330b57cec5SDimitry Andric unsigned noteID = diag::note_arc_lost_method_convention; 25340b57cec5SDimitry Andric if (declFamily == OMF_None) { 25350b57cec5SDimitry Andric unmatched = decl; 25360b57cec5SDimitry Andric family = implFamily; 25370b57cec5SDimitry Andric errorID = diag::err_arc_gained_method_convention; 25380b57cec5SDimitry Andric noteID = diag::note_arc_gained_method_convention; 25390b57cec5SDimitry Andric } 25400b57cec5SDimitry Andric 25410b57cec5SDimitry Andric // Indexes into a %select clause in the diagnostic. 25420b57cec5SDimitry Andric enum FamilySelector { 25430b57cec5SDimitry Andric F_alloc, F_copy, F_mutableCopy = F_copy, F_init, F_new 25440b57cec5SDimitry Andric }; 25450b57cec5SDimitry Andric FamilySelector familySelector = FamilySelector(); 25460b57cec5SDimitry Andric 25470b57cec5SDimitry Andric switch (family) { 25480b57cec5SDimitry Andric case OMF_None: llvm_unreachable("logic error, no method convention"); 25490b57cec5SDimitry Andric case OMF_retain: 25500b57cec5SDimitry Andric case OMF_release: 25510b57cec5SDimitry Andric case OMF_autorelease: 25520b57cec5SDimitry Andric case OMF_dealloc: 25530b57cec5SDimitry Andric case OMF_finalize: 25540b57cec5SDimitry Andric case OMF_retainCount: 25550b57cec5SDimitry Andric case OMF_self: 25560b57cec5SDimitry Andric case OMF_initialize: 25570b57cec5SDimitry Andric case OMF_performSelector: 25580b57cec5SDimitry Andric // Mismatches for these methods don't change ownership 25590b57cec5SDimitry Andric // conventions, so we don't care. 25600b57cec5SDimitry Andric return false; 25610b57cec5SDimitry Andric 25620b57cec5SDimitry Andric case OMF_init: familySelector = F_init; break; 25630b57cec5SDimitry Andric case OMF_alloc: familySelector = F_alloc; break; 25640b57cec5SDimitry Andric case OMF_copy: familySelector = F_copy; break; 25650b57cec5SDimitry Andric case OMF_mutableCopy: familySelector = F_mutableCopy; break; 25660b57cec5SDimitry Andric case OMF_new: familySelector = F_new; break; 25670b57cec5SDimitry Andric } 25680b57cec5SDimitry Andric 25690b57cec5SDimitry Andric enum ReasonSelector { R_NonObjectReturn, R_UnrelatedReturn }; 25700b57cec5SDimitry Andric ReasonSelector reasonSelector; 25710b57cec5SDimitry Andric 25720b57cec5SDimitry Andric // The only reason these methods don't fall within their families is 25730b57cec5SDimitry Andric // due to unusual result types. 25740b57cec5SDimitry Andric if (unmatched->getReturnType()->isObjCObjectPointerType()) { 25750b57cec5SDimitry Andric reasonSelector = R_UnrelatedReturn; 25760b57cec5SDimitry Andric } else { 25770b57cec5SDimitry Andric reasonSelector = R_NonObjectReturn; 25780b57cec5SDimitry Andric } 25790b57cec5SDimitry Andric 25800b57cec5SDimitry Andric S.Diag(impl->getLocation(), errorID) << int(familySelector) << int(reasonSelector); 25810b57cec5SDimitry Andric S.Diag(decl->getLocation(), noteID) << int(familySelector) << int(reasonSelector); 25820b57cec5SDimitry Andric 25830b57cec5SDimitry Andric return true; 25840b57cec5SDimitry Andric } 25850b57cec5SDimitry Andric 2586*0fca6ea1SDimitry Andric void SemaObjC::WarnConflictingTypedMethods(ObjCMethodDecl *ImpMethodDecl, 25870b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl, 25880b57cec5SDimitry Andric bool IsProtocolMethodDecl) { 25890b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && 2590*0fca6ea1SDimitry Andric checkMethodFamilyMismatch(SemaRef, ImpMethodDecl, MethodDecl)) 25910b57cec5SDimitry Andric return; 25920b57cec5SDimitry Andric 2593*0fca6ea1SDimitry Andric CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl, 2594*0fca6ea1SDimitry Andric IsProtocolMethodDecl, false, true); 25950b57cec5SDimitry Andric 25960b57cec5SDimitry Andric for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), 25970b57cec5SDimitry Andric IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), 25980b57cec5SDimitry Andric EF = MethodDecl->param_end(); 25990b57cec5SDimitry Andric IM != EM && IF != EF; ++IM, ++IF) { 2600*0fca6ea1SDimitry Andric CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, *IF, 26010b57cec5SDimitry Andric IsProtocolMethodDecl, false, true); 26020b57cec5SDimitry Andric } 26030b57cec5SDimitry Andric 26040b57cec5SDimitry Andric if (ImpMethodDecl->isVariadic() != MethodDecl->isVariadic()) { 26050b57cec5SDimitry Andric Diag(ImpMethodDecl->getLocation(), 26060b57cec5SDimitry Andric diag::warn_conflicting_variadic); 26070b57cec5SDimitry Andric Diag(MethodDecl->getLocation(), diag::note_previous_declaration); 26080b57cec5SDimitry Andric } 26090b57cec5SDimitry Andric } 26100b57cec5SDimitry Andric 2611*0fca6ea1SDimitry Andric void SemaObjC::CheckConflictingOverridingMethod(ObjCMethodDecl *Method, 26120b57cec5SDimitry Andric ObjCMethodDecl *Overridden, 26130b57cec5SDimitry Andric bool IsProtocolMethodDecl) { 26140b57cec5SDimitry Andric 2615*0fca6ea1SDimitry Andric CheckMethodOverrideReturn(SemaRef, Method, Overridden, IsProtocolMethodDecl, 2616*0fca6ea1SDimitry Andric true, true); 26170b57cec5SDimitry Andric 26180b57cec5SDimitry Andric for (ObjCMethodDecl::param_iterator IM = Method->param_begin(), 26190b57cec5SDimitry Andric IF = Overridden->param_begin(), EM = Method->param_end(), 26200b57cec5SDimitry Andric EF = Overridden->param_end(); 26210b57cec5SDimitry Andric IM != EM && IF != EF; ++IM, ++IF) { 2622*0fca6ea1SDimitry Andric CheckMethodOverrideParam(SemaRef, Method, Overridden, *IM, *IF, 26230b57cec5SDimitry Andric IsProtocolMethodDecl, true, true); 26240b57cec5SDimitry Andric } 26250b57cec5SDimitry Andric 26260b57cec5SDimitry Andric if (Method->isVariadic() != Overridden->isVariadic()) { 26270b57cec5SDimitry Andric Diag(Method->getLocation(), 26280b57cec5SDimitry Andric diag::warn_conflicting_overriding_variadic); 26290b57cec5SDimitry Andric Diag(Overridden->getLocation(), diag::note_previous_declaration); 26300b57cec5SDimitry Andric } 26310b57cec5SDimitry Andric } 26320b57cec5SDimitry Andric 26330b57cec5SDimitry Andric /// WarnExactTypedMethods - This routine issues a warning if method 26340b57cec5SDimitry Andric /// implementation declaration matches exactly that of its declaration. 2635*0fca6ea1SDimitry Andric void SemaObjC::WarnExactTypedMethods(ObjCMethodDecl *ImpMethodDecl, 26360b57cec5SDimitry Andric ObjCMethodDecl *MethodDecl, 26370b57cec5SDimitry Andric bool IsProtocolMethodDecl) { 2638*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 26390b57cec5SDimitry Andric // don't issue warning when protocol method is optional because primary 26400b57cec5SDimitry Andric // class is not required to implement it and it is safe for protocol 26410b57cec5SDimitry Andric // to implement it. 26425f757f3fSDimitry Andric if (MethodDecl->getImplementationControl() == 26435f757f3fSDimitry Andric ObjCImplementationControl::Optional) 26440b57cec5SDimitry Andric return; 26450b57cec5SDimitry Andric // don't issue warning when primary class's method is 2646349cc55cSDimitry Andric // deprecated/unavailable. 26470b57cec5SDimitry Andric if (MethodDecl->hasAttr<UnavailableAttr>() || 26480b57cec5SDimitry Andric MethodDecl->hasAttr<DeprecatedAttr>()) 26490b57cec5SDimitry Andric return; 26500b57cec5SDimitry Andric 2651*0fca6ea1SDimitry Andric bool match = CheckMethodOverrideReturn(SemaRef, ImpMethodDecl, MethodDecl, 26520b57cec5SDimitry Andric IsProtocolMethodDecl, false, false); 26530b57cec5SDimitry Andric if (match) 26540b57cec5SDimitry Andric for (ObjCMethodDecl::param_iterator IM = ImpMethodDecl->param_begin(), 26550b57cec5SDimitry Andric IF = MethodDecl->param_begin(), EM = ImpMethodDecl->param_end(), 26560b57cec5SDimitry Andric EF = MethodDecl->param_end(); 26570b57cec5SDimitry Andric IM != EM && IF != EF; ++IM, ++IF) { 2658*0fca6ea1SDimitry Andric match = CheckMethodOverrideParam(SemaRef, ImpMethodDecl, MethodDecl, *IM, 2659*0fca6ea1SDimitry Andric *IF, IsProtocolMethodDecl, false, false); 26600b57cec5SDimitry Andric if (!match) 26610b57cec5SDimitry Andric break; 26620b57cec5SDimitry Andric } 26630b57cec5SDimitry Andric if (match) 26640b57cec5SDimitry Andric match = (ImpMethodDecl->isVariadic() == MethodDecl->isVariadic()); 26650b57cec5SDimitry Andric if (match) 26660b57cec5SDimitry Andric match = !(MethodDecl->isClassMethod() && 26670b57cec5SDimitry Andric MethodDecl->getSelector() == GetNullarySelector("load", Context)); 26680b57cec5SDimitry Andric 26690b57cec5SDimitry Andric if (match) { 26700b57cec5SDimitry Andric Diag(ImpMethodDecl->getLocation(), 26710b57cec5SDimitry Andric diag::warn_category_method_impl_match); 26720b57cec5SDimitry Andric Diag(MethodDecl->getLocation(), diag::note_method_declared_at) 26730b57cec5SDimitry Andric << MethodDecl->getDeclName(); 26740b57cec5SDimitry Andric } 26750b57cec5SDimitry Andric } 26760b57cec5SDimitry Andric 26770b57cec5SDimitry Andric /// FIXME: Type hierarchies in Objective-C can be deep. We could most likely 26780b57cec5SDimitry Andric /// improve the efficiency of selector lookups and type checking by associating 26790b57cec5SDimitry Andric /// with each protocol / interface / category the flattened instance tables. If 26800b57cec5SDimitry Andric /// we used an immutable set to keep the table then it wouldn't add significant 26810b57cec5SDimitry Andric /// memory cost and it would be handy for lookups. 26820b57cec5SDimitry Andric 26830b57cec5SDimitry Andric typedef llvm::DenseSet<IdentifierInfo*> ProtocolNameSet; 26840b57cec5SDimitry Andric typedef std::unique_ptr<ProtocolNameSet> LazyProtocolNameSet; 26850b57cec5SDimitry Andric 26860b57cec5SDimitry Andric static void findProtocolsWithExplicitImpls(const ObjCProtocolDecl *PDecl, 26870b57cec5SDimitry Andric ProtocolNameSet &PNS) { 26880b57cec5SDimitry Andric if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) 26890b57cec5SDimitry Andric PNS.insert(PDecl->getIdentifier()); 26900b57cec5SDimitry Andric for (const auto *PI : PDecl->protocols()) 26910b57cec5SDimitry Andric findProtocolsWithExplicitImpls(PI, PNS); 26920b57cec5SDimitry Andric } 26930b57cec5SDimitry Andric 26940b57cec5SDimitry Andric /// Recursively populates a set with all conformed protocols in a class 26950b57cec5SDimitry Andric /// hierarchy that have the 'objc_protocol_requires_explicit_implementation' 26960b57cec5SDimitry Andric /// attribute. 26970b57cec5SDimitry Andric static void findProtocolsWithExplicitImpls(const ObjCInterfaceDecl *Super, 26980b57cec5SDimitry Andric ProtocolNameSet &PNS) { 26990b57cec5SDimitry Andric if (!Super) 27000b57cec5SDimitry Andric return; 27010b57cec5SDimitry Andric 27020b57cec5SDimitry Andric for (const auto *I : Super->all_referenced_protocols()) 27030b57cec5SDimitry Andric findProtocolsWithExplicitImpls(I, PNS); 27040b57cec5SDimitry Andric 27050b57cec5SDimitry Andric findProtocolsWithExplicitImpls(Super->getSuperClass(), PNS); 27060b57cec5SDimitry Andric } 27070b57cec5SDimitry Andric 27080b57cec5SDimitry Andric /// CheckProtocolMethodDefs - This routine checks unimplemented methods 27090b57cec5SDimitry Andric /// Declared in protocol, and those referenced by it. 271004eeddc0SDimitry Andric static void CheckProtocolMethodDefs( 271104eeddc0SDimitry Andric Sema &S, ObjCImplDecl *Impl, ObjCProtocolDecl *PDecl, bool &IncompleteImpl, 2712*0fca6ea1SDimitry Andric const SemaObjC::SelectorSet &InsMap, const SemaObjC::SelectorSet &ClsMap, 271304eeddc0SDimitry Andric ObjCContainerDecl *CDecl, LazyProtocolNameSet &ProtocolsExplictImpl) { 27140b57cec5SDimitry Andric ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl); 27150b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = C ? C->getClassInterface() 27160b57cec5SDimitry Andric : dyn_cast<ObjCInterfaceDecl>(CDecl); 27170b57cec5SDimitry Andric assert (IDecl && "CheckProtocolMethodDefs - IDecl is null"); 27180b57cec5SDimitry Andric 27190b57cec5SDimitry Andric ObjCInterfaceDecl *Super = IDecl->getSuperClass(); 27200b57cec5SDimitry Andric ObjCInterfaceDecl *NSIDecl = nullptr; 27210b57cec5SDimitry Andric 27220b57cec5SDimitry Andric // If this protocol is marked 'objc_protocol_requires_explicit_implementation' 27230b57cec5SDimitry Andric // then we should check if any class in the super class hierarchy also 27240b57cec5SDimitry Andric // conforms to this protocol, either directly or via protocol inheritance. 27250b57cec5SDimitry Andric // If so, we can skip checking this protocol completely because we 27260b57cec5SDimitry Andric // know that a parent class already satisfies this protocol. 27270b57cec5SDimitry Andric // 27280b57cec5SDimitry Andric // Note: we could generalize this logic for all protocols, and merely 27290b57cec5SDimitry Andric // add the limit on looking at the super class chain for just 27300b57cec5SDimitry Andric // specially marked protocols. This may be a good optimization. This 27310b57cec5SDimitry Andric // change is restricted to 'objc_protocol_requires_explicit_implementation' 27320b57cec5SDimitry Andric // protocols for now for controlled evaluation. 27330b57cec5SDimitry Andric if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) { 27340b57cec5SDimitry Andric if (!ProtocolsExplictImpl) { 27350b57cec5SDimitry Andric ProtocolsExplictImpl.reset(new ProtocolNameSet); 27360b57cec5SDimitry Andric findProtocolsWithExplicitImpls(Super, *ProtocolsExplictImpl); 27370b57cec5SDimitry Andric } 2738349cc55cSDimitry Andric if (ProtocolsExplictImpl->contains(PDecl->getIdentifier())) 27390b57cec5SDimitry Andric return; 27400b57cec5SDimitry Andric 27410b57cec5SDimitry Andric // If no super class conforms to the protocol, we should not search 27420b57cec5SDimitry Andric // for methods in the super class to implicitly satisfy the protocol. 27430b57cec5SDimitry Andric Super = nullptr; 27440b57cec5SDimitry Andric } 27450b57cec5SDimitry Andric 27460b57cec5SDimitry Andric if (S.getLangOpts().ObjCRuntime.isNeXTFamily()) { 27470b57cec5SDimitry Andric // check to see if class implements forwardInvocation method and objects 27480b57cec5SDimitry Andric // of this class are derived from 'NSProxy' so that to forward requests 27490b57cec5SDimitry Andric // from one object to another. 27500b57cec5SDimitry Andric // Under such conditions, which means that every method possible is 27510b57cec5SDimitry Andric // implemented in the class, we should not issue "Method definition not 27520b57cec5SDimitry Andric // found" warnings. 27530b57cec5SDimitry Andric // FIXME: Use a general GetUnarySelector method for this. 2754*0fca6ea1SDimitry Andric const IdentifierInfo *II = &S.Context.Idents.get("forwardInvocation"); 27550b57cec5SDimitry Andric Selector fISelector = S.Context.Selectors.getSelector(1, &II); 27560b57cec5SDimitry Andric if (InsMap.count(fISelector)) 27570b57cec5SDimitry Andric // Is IDecl derived from 'NSProxy'? If so, no instance methods 27580b57cec5SDimitry Andric // need be implemented in the implementation. 27590b57cec5SDimitry Andric NSIDecl = IDecl->lookupInheritedClass(&S.Context.Idents.get("NSProxy")); 27600b57cec5SDimitry Andric } 27610b57cec5SDimitry Andric 27620b57cec5SDimitry Andric // If this is a forward protocol declaration, get its definition. 27630b57cec5SDimitry Andric if (!PDecl->isThisDeclarationADefinition() && 27640b57cec5SDimitry Andric PDecl->getDefinition()) 27650b57cec5SDimitry Andric PDecl = PDecl->getDefinition(); 27660b57cec5SDimitry Andric 27670b57cec5SDimitry Andric // If a method lookup fails locally we still need to look and see if 27680b57cec5SDimitry Andric // the method was implemented by a base class or an inherited 27690b57cec5SDimitry Andric // protocol. This lookup is slow, but occurs rarely in correct code 27700b57cec5SDimitry Andric // and otherwise would terminate in a warning. 27710b57cec5SDimitry Andric 27720b57cec5SDimitry Andric // check unimplemented instance methods. 27730b57cec5SDimitry Andric if (!NSIDecl) 27740b57cec5SDimitry Andric for (auto *method : PDecl->instance_methods()) { 27755f757f3fSDimitry Andric if (method->getImplementationControl() != 27765f757f3fSDimitry Andric ObjCImplementationControl::Optional && 27770b57cec5SDimitry Andric !method->isPropertyAccessor() && 27780b57cec5SDimitry Andric !InsMap.count(method->getSelector()) && 27795f757f3fSDimitry Andric (!Super || !Super->lookupMethod( 27805f757f3fSDimitry Andric method->getSelector(), true /* instance */, 27815f757f3fSDimitry Andric false /* shallowCategory */, true /* followsSuper */, 27820b57cec5SDimitry Andric nullptr /* category */))) { 27830b57cec5SDimitry Andric // If a method is not implemented in the category implementation but 27840b57cec5SDimitry Andric // has been declared in its primary class, superclass, 27850b57cec5SDimitry Andric // or in one of their protocols, no need to issue the warning. 27860b57cec5SDimitry Andric // This is because method will be implemented in the primary class 27870b57cec5SDimitry Andric // or one of its super class implementation. 27880b57cec5SDimitry Andric 27890b57cec5SDimitry Andric // Ugly, but necessary. Method declared in protocol might have 27900b57cec5SDimitry Andric // have been synthesized due to a property declared in the class which 27910b57cec5SDimitry Andric // uses the protocol. 27925f757f3fSDimitry Andric if (ObjCMethodDecl *MethodInClass = IDecl->lookupMethod( 27935f757f3fSDimitry Andric method->getSelector(), true /* instance */, 27945f757f3fSDimitry Andric true /* shallowCategoryLookup */, false /* followSuper */)) 27950b57cec5SDimitry Andric if (C || MethodInClass->isPropertyAccessor()) 27960b57cec5SDimitry Andric continue; 27970b57cec5SDimitry Andric unsigned DIAG = diag::warn_unimplemented_protocol_method; 279804eeddc0SDimitry Andric if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) { 279904eeddc0SDimitry Andric WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl); 28000b57cec5SDimitry Andric } 28010b57cec5SDimitry Andric } 28020b57cec5SDimitry Andric } 28030b57cec5SDimitry Andric // check unimplemented class methods 28040b57cec5SDimitry Andric for (auto *method : PDecl->class_methods()) { 28055f757f3fSDimitry Andric if (method->getImplementationControl() != 28065f757f3fSDimitry Andric ObjCImplementationControl::Optional && 28070b57cec5SDimitry Andric !ClsMap.count(method->getSelector()) && 28085f757f3fSDimitry Andric (!Super || !Super->lookupMethod( 28095f757f3fSDimitry Andric method->getSelector(), false /* class method */, 28100b57cec5SDimitry Andric false /* shallowCategoryLookup */, 28115f757f3fSDimitry Andric true /* followSuper */, nullptr /* category */))) { 28120b57cec5SDimitry Andric // See above comment for instance method lookups. 28130b57cec5SDimitry Andric if (C && IDecl->lookupMethod(method->getSelector(), 28140b57cec5SDimitry Andric false /* class */, 28150b57cec5SDimitry Andric true /* shallowCategoryLookup */, 28160b57cec5SDimitry Andric false /* followSuper */)) 28170b57cec5SDimitry Andric continue; 28180b57cec5SDimitry Andric 28190b57cec5SDimitry Andric unsigned DIAG = diag::warn_unimplemented_protocol_method; 282004eeddc0SDimitry Andric if (!S.Diags.isIgnored(DIAG, Impl->getLocation())) { 282104eeddc0SDimitry Andric WarnUndefinedMethod(S, Impl, method, IncompleteImpl, DIAG, PDecl); 28220b57cec5SDimitry Andric } 28230b57cec5SDimitry Andric } 28240b57cec5SDimitry Andric } 28250b57cec5SDimitry Andric // Check on this protocols's referenced protocols, recursively. 28260b57cec5SDimitry Andric for (auto *PI : PDecl->protocols()) 282704eeddc0SDimitry Andric CheckProtocolMethodDefs(S, Impl, PI, IncompleteImpl, InsMap, ClsMap, CDecl, 282804eeddc0SDimitry Andric ProtocolsExplictImpl); 28290b57cec5SDimitry Andric } 28300b57cec5SDimitry Andric 28310b57cec5SDimitry Andric /// MatchAllMethodDeclarations - Check methods declared in interface 28320b57cec5SDimitry Andric /// or protocol against those declared in their implementations. 28330b57cec5SDimitry Andric /// 2834*0fca6ea1SDimitry Andric void SemaObjC::MatchAllMethodDeclarations( 2835*0fca6ea1SDimitry Andric const SelectorSet &InsMap, const SelectorSet &ClsMap, 2836*0fca6ea1SDimitry Andric SelectorSet &InsMapSeen, SelectorSet &ClsMapSeen, ObjCImplDecl *IMPDecl, 2837*0fca6ea1SDimitry Andric ObjCContainerDecl *CDecl, bool &IncompleteImpl, bool ImmediateClass, 28380b57cec5SDimitry Andric bool WarnCategoryMethodImpl) { 28390b57cec5SDimitry Andric // Check and see if instance methods in class interface have been 28400b57cec5SDimitry Andric // implemented in the implementation class. If so, their types match. 28410b57cec5SDimitry Andric for (auto *I : CDecl->instance_methods()) { 28420b57cec5SDimitry Andric if (!InsMapSeen.insert(I->getSelector()).second) 28430b57cec5SDimitry Andric continue; 28440b57cec5SDimitry Andric if (!I->isPropertyAccessor() && 28450b57cec5SDimitry Andric !InsMap.count(I->getSelector())) { 28460b57cec5SDimitry Andric if (ImmediateClass) 2847*0fca6ea1SDimitry Andric WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl, 28480b57cec5SDimitry Andric diag::warn_undef_method_impl); 28490b57cec5SDimitry Andric continue; 28500b57cec5SDimitry Andric } else { 28510b57cec5SDimitry Andric ObjCMethodDecl *ImpMethodDecl = 28520b57cec5SDimitry Andric IMPDecl->getInstanceMethod(I->getSelector()); 28530b57cec5SDimitry Andric assert(CDecl->getInstanceMethod(I->getSelector(), true/*AllowHidden*/) && 28540b57cec5SDimitry Andric "Expected to find the method through lookup as well"); 28550b57cec5SDimitry Andric // ImpMethodDecl may be null as in a @dynamic property. 28560b57cec5SDimitry Andric if (ImpMethodDecl) { 2857480093f4SDimitry Andric // Skip property accessor function stubs. 2858480093f4SDimitry Andric if (ImpMethodDecl->isSynthesizedAccessorStub()) 2859480093f4SDimitry Andric continue; 28600b57cec5SDimitry Andric if (!WarnCategoryMethodImpl) 28610b57cec5SDimitry Andric WarnConflictingTypedMethods(ImpMethodDecl, I, 28620b57cec5SDimitry Andric isa<ObjCProtocolDecl>(CDecl)); 28630b57cec5SDimitry Andric else if (!I->isPropertyAccessor()) 28640b57cec5SDimitry Andric WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl)); 28650b57cec5SDimitry Andric } 28660b57cec5SDimitry Andric } 28670b57cec5SDimitry Andric } 28680b57cec5SDimitry Andric 28690b57cec5SDimitry Andric // Check and see if class methods in class interface have been 28700b57cec5SDimitry Andric // implemented in the implementation class. If so, their types match. 28710b57cec5SDimitry Andric for (auto *I : CDecl->class_methods()) { 28720b57cec5SDimitry Andric if (!ClsMapSeen.insert(I->getSelector()).second) 28730b57cec5SDimitry Andric continue; 28740b57cec5SDimitry Andric if (!I->isPropertyAccessor() && 28750b57cec5SDimitry Andric !ClsMap.count(I->getSelector())) { 28760b57cec5SDimitry Andric if (ImmediateClass) 2877*0fca6ea1SDimitry Andric WarnUndefinedMethod(SemaRef, IMPDecl, I, IncompleteImpl, 28780b57cec5SDimitry Andric diag::warn_undef_method_impl); 28790b57cec5SDimitry Andric } else { 28800b57cec5SDimitry Andric ObjCMethodDecl *ImpMethodDecl = 28810b57cec5SDimitry Andric IMPDecl->getClassMethod(I->getSelector()); 28820b57cec5SDimitry Andric assert(CDecl->getClassMethod(I->getSelector(), true/*AllowHidden*/) && 28830b57cec5SDimitry Andric "Expected to find the method through lookup as well"); 28840b57cec5SDimitry Andric // ImpMethodDecl may be null as in a @dynamic property. 28850b57cec5SDimitry Andric if (ImpMethodDecl) { 2886480093f4SDimitry Andric // Skip property accessor function stubs. 2887480093f4SDimitry Andric if (ImpMethodDecl->isSynthesizedAccessorStub()) 2888480093f4SDimitry Andric continue; 28890b57cec5SDimitry Andric if (!WarnCategoryMethodImpl) 28900b57cec5SDimitry Andric WarnConflictingTypedMethods(ImpMethodDecl, I, 28910b57cec5SDimitry Andric isa<ObjCProtocolDecl>(CDecl)); 28920b57cec5SDimitry Andric else if (!I->isPropertyAccessor()) 28930b57cec5SDimitry Andric WarnExactTypedMethods(ImpMethodDecl, I, isa<ObjCProtocolDecl>(CDecl)); 28940b57cec5SDimitry Andric } 28950b57cec5SDimitry Andric } 28960b57cec5SDimitry Andric } 28970b57cec5SDimitry Andric 28980b57cec5SDimitry Andric if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl> (CDecl)) { 28990b57cec5SDimitry Andric // Also, check for methods declared in protocols inherited by 29000b57cec5SDimitry Andric // this protocol. 29010b57cec5SDimitry Andric for (auto *PI : PD->protocols()) 29020b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29030b57cec5SDimitry Andric IMPDecl, PI, IncompleteImpl, false, 29040b57cec5SDimitry Andric WarnCategoryMethodImpl); 29050b57cec5SDimitry Andric } 29060b57cec5SDimitry Andric 29070b57cec5SDimitry Andric if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { 29080b57cec5SDimitry Andric // when checking that methods in implementation match their declaration, 29090b57cec5SDimitry Andric // i.e. when WarnCategoryMethodImpl is false, check declarations in class 29100b57cec5SDimitry Andric // extension; as well as those in categories. 29110b57cec5SDimitry Andric if (!WarnCategoryMethodImpl) { 29120b57cec5SDimitry Andric for (auto *Cat : I->visible_categories()) 29130b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29140b57cec5SDimitry Andric IMPDecl, Cat, IncompleteImpl, 29150b57cec5SDimitry Andric ImmediateClass && Cat->IsClassExtension(), 29160b57cec5SDimitry Andric WarnCategoryMethodImpl); 29170b57cec5SDimitry Andric } else { 29180b57cec5SDimitry Andric // Also methods in class extensions need be looked at next. 29190b57cec5SDimitry Andric for (auto *Ext : I->visible_extensions()) 29200b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29210b57cec5SDimitry Andric IMPDecl, Ext, IncompleteImpl, false, 29220b57cec5SDimitry Andric WarnCategoryMethodImpl); 29230b57cec5SDimitry Andric } 29240b57cec5SDimitry Andric 29250b57cec5SDimitry Andric // Check for any implementation of a methods declared in protocol. 29260b57cec5SDimitry Andric for (auto *PI : I->all_referenced_protocols()) 29270b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29280b57cec5SDimitry Andric IMPDecl, PI, IncompleteImpl, false, 29290b57cec5SDimitry Andric WarnCategoryMethodImpl); 29300b57cec5SDimitry Andric 29310b57cec5SDimitry Andric // FIXME. For now, we are not checking for exact match of methods 29320b57cec5SDimitry Andric // in category implementation and its primary class's super class. 29330b57cec5SDimitry Andric if (!WarnCategoryMethodImpl && I->getSuperClass()) 29340b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29350b57cec5SDimitry Andric IMPDecl, 29360b57cec5SDimitry Andric I->getSuperClass(), IncompleteImpl, false); 29370b57cec5SDimitry Andric } 29380b57cec5SDimitry Andric } 29390b57cec5SDimitry Andric 29400b57cec5SDimitry Andric /// CheckCategoryVsClassMethodMatches - Checks that methods implemented in 29410b57cec5SDimitry Andric /// category matches with those implemented in its primary class and 29420b57cec5SDimitry Andric /// warns each time an exact match is found. 2943*0fca6ea1SDimitry Andric void SemaObjC::CheckCategoryVsClassMethodMatches( 29440b57cec5SDimitry Andric ObjCCategoryImplDecl *CatIMPDecl) { 29450b57cec5SDimitry Andric // Get category's primary class. 29460b57cec5SDimitry Andric ObjCCategoryDecl *CatDecl = CatIMPDecl->getCategoryDecl(); 29470b57cec5SDimitry Andric if (!CatDecl) 29480b57cec5SDimitry Andric return; 29490b57cec5SDimitry Andric ObjCInterfaceDecl *IDecl = CatDecl->getClassInterface(); 29500b57cec5SDimitry Andric if (!IDecl) 29510b57cec5SDimitry Andric return; 29520b57cec5SDimitry Andric ObjCInterfaceDecl *SuperIDecl = IDecl->getSuperClass(); 29530b57cec5SDimitry Andric SelectorSet InsMap, ClsMap; 29540b57cec5SDimitry Andric 29550b57cec5SDimitry Andric for (const auto *I : CatIMPDecl->instance_methods()) { 29560b57cec5SDimitry Andric Selector Sel = I->getSelector(); 29570b57cec5SDimitry Andric // When checking for methods implemented in the category, skip over 29580b57cec5SDimitry Andric // those declared in category class's super class. This is because 29590b57cec5SDimitry Andric // the super class must implement the method. 29600b57cec5SDimitry Andric if (SuperIDecl && SuperIDecl->lookupMethod(Sel, true)) 29610b57cec5SDimitry Andric continue; 29620b57cec5SDimitry Andric InsMap.insert(Sel); 29630b57cec5SDimitry Andric } 29640b57cec5SDimitry Andric 29650b57cec5SDimitry Andric for (const auto *I : CatIMPDecl->class_methods()) { 29660b57cec5SDimitry Andric Selector Sel = I->getSelector(); 29670b57cec5SDimitry Andric if (SuperIDecl && SuperIDecl->lookupMethod(Sel, false)) 29680b57cec5SDimitry Andric continue; 29690b57cec5SDimitry Andric ClsMap.insert(Sel); 29700b57cec5SDimitry Andric } 29710b57cec5SDimitry Andric if (InsMap.empty() && ClsMap.empty()) 29720b57cec5SDimitry Andric return; 29730b57cec5SDimitry Andric 29740b57cec5SDimitry Andric SelectorSet InsMapSeen, ClsMapSeen; 29750b57cec5SDimitry Andric bool IncompleteImpl = false; 29760b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 29770b57cec5SDimitry Andric CatIMPDecl, IDecl, 29780b57cec5SDimitry Andric IncompleteImpl, false, 29790b57cec5SDimitry Andric true /*WarnCategoryMethodImpl*/); 29800b57cec5SDimitry Andric } 29810b57cec5SDimitry Andric 2982*0fca6ea1SDimitry Andric void SemaObjC::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl *IMPDecl, 29830b57cec5SDimitry Andric ObjCContainerDecl *CDecl, 29840b57cec5SDimitry Andric bool IncompleteImpl) { 29850b57cec5SDimitry Andric SelectorSet InsMap; 29860b57cec5SDimitry Andric // Check and see if instance methods in class interface have been 29870b57cec5SDimitry Andric // implemented in the implementation class. 29880b57cec5SDimitry Andric for (const auto *I : IMPDecl->instance_methods()) 29890b57cec5SDimitry Andric InsMap.insert(I->getSelector()); 29900b57cec5SDimitry Andric 29910b57cec5SDimitry Andric // Add the selectors for getters/setters of @dynamic properties. 29920b57cec5SDimitry Andric for (const auto *PImpl : IMPDecl->property_impls()) { 29930b57cec5SDimitry Andric // We only care about @dynamic implementations. 29940b57cec5SDimitry Andric if (PImpl->getPropertyImplementation() != ObjCPropertyImplDecl::Dynamic) 29950b57cec5SDimitry Andric continue; 29960b57cec5SDimitry Andric 29970b57cec5SDimitry Andric const auto *P = PImpl->getPropertyDecl(); 29980b57cec5SDimitry Andric if (!P) continue; 29990b57cec5SDimitry Andric 30000b57cec5SDimitry Andric InsMap.insert(P->getGetterName()); 30010b57cec5SDimitry Andric if (!P->getSetterName().isNull()) 30020b57cec5SDimitry Andric InsMap.insert(P->getSetterName()); 30030b57cec5SDimitry Andric } 30040b57cec5SDimitry Andric 30050b57cec5SDimitry Andric // Check and see if properties declared in the interface have either 1) 30060b57cec5SDimitry Andric // an implementation or 2) there is a @synthesize/@dynamic implementation 30070b57cec5SDimitry Andric // of the property in the @implementation. 30080b57cec5SDimitry Andric if (const ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { 3009*0fca6ea1SDimitry Andric bool SynthesizeProperties = getLangOpts().ObjCDefaultSynthProperties && 3010*0fca6ea1SDimitry Andric getLangOpts().ObjCRuntime.isNonFragile() && 30110b57cec5SDimitry Andric !IDecl->isObjCRequiresPropertyDefs(); 30120b57cec5SDimitry Andric DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, SynthesizeProperties); 30130b57cec5SDimitry Andric } 30140b57cec5SDimitry Andric 30150b57cec5SDimitry Andric // Diagnose null-resettable synthesized setters. 30160b57cec5SDimitry Andric diagnoseNullResettableSynthesizedSetters(IMPDecl); 30170b57cec5SDimitry Andric 30180b57cec5SDimitry Andric SelectorSet ClsMap; 30190b57cec5SDimitry Andric for (const auto *I : IMPDecl->class_methods()) 30200b57cec5SDimitry Andric ClsMap.insert(I->getSelector()); 30210b57cec5SDimitry Andric 30220b57cec5SDimitry Andric // Check for type conflict of methods declared in a class/protocol and 30230b57cec5SDimitry Andric // its implementation; if any. 30240b57cec5SDimitry Andric SelectorSet InsMapSeen, ClsMapSeen; 30250b57cec5SDimitry Andric MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen, 30260b57cec5SDimitry Andric IMPDecl, CDecl, 30270b57cec5SDimitry Andric IncompleteImpl, true); 30280b57cec5SDimitry Andric 30290b57cec5SDimitry Andric // check all methods implemented in category against those declared 30300b57cec5SDimitry Andric // in its primary class. 30310b57cec5SDimitry Andric if (ObjCCategoryImplDecl *CatDecl = 30320b57cec5SDimitry Andric dyn_cast<ObjCCategoryImplDecl>(IMPDecl)) 30330b57cec5SDimitry Andric CheckCategoryVsClassMethodMatches(CatDecl); 30340b57cec5SDimitry Andric 30350b57cec5SDimitry Andric // Check the protocol list for unimplemented methods in the @implementation 30360b57cec5SDimitry Andric // class. 30370b57cec5SDimitry Andric // Check and see if class methods in class interface have been 30380b57cec5SDimitry Andric // implemented in the implementation class. 30390b57cec5SDimitry Andric 30400b57cec5SDimitry Andric LazyProtocolNameSet ExplicitImplProtocols; 30410b57cec5SDimitry Andric 30420b57cec5SDimitry Andric if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) { 30430b57cec5SDimitry Andric for (auto *PI : I->all_referenced_protocols()) 3044*0fca6ea1SDimitry Andric CheckProtocolMethodDefs(SemaRef, IMPDecl, PI, IncompleteImpl, InsMap, 304504eeddc0SDimitry Andric ClsMap, I, ExplicitImplProtocols); 30460b57cec5SDimitry Andric } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(CDecl)) { 30470b57cec5SDimitry Andric // For extended class, unimplemented methods in its protocols will 30480b57cec5SDimitry Andric // be reported in the primary class. 30490b57cec5SDimitry Andric if (!C->IsClassExtension()) { 30500b57cec5SDimitry Andric for (auto *P : C->protocols()) 3051*0fca6ea1SDimitry Andric CheckProtocolMethodDefs(SemaRef, IMPDecl, P, IncompleteImpl, InsMap, 305204eeddc0SDimitry Andric ClsMap, CDecl, ExplicitImplProtocols); 30530b57cec5SDimitry Andric DiagnoseUnimplementedProperties(S, IMPDecl, CDecl, 30540b57cec5SDimitry Andric /*SynthesizeProperties=*/false); 30550b57cec5SDimitry Andric } 30560b57cec5SDimitry Andric } else 30570b57cec5SDimitry Andric llvm_unreachable("invalid ObjCContainerDecl type."); 30580b57cec5SDimitry Andric } 30590b57cec5SDimitry Andric 3060*0fca6ea1SDimitry Andric SemaObjC::DeclGroupPtrTy SemaObjC::ActOnForwardClassDeclaration( 3061*0fca6ea1SDimitry Andric SourceLocation AtClassLoc, IdentifierInfo **IdentList, 3062*0fca6ea1SDimitry Andric SourceLocation *IdentLocs, ArrayRef<ObjCTypeParamList *> TypeParamLists, 30630b57cec5SDimitry Andric unsigned NumElts) { 3064*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 30650b57cec5SDimitry Andric SmallVector<Decl *, 8> DeclsInGroup; 30660b57cec5SDimitry Andric for (unsigned i = 0; i != NumElts; ++i) { 30670b57cec5SDimitry Andric // Check for another declaration kind with the same name. 3068*0fca6ea1SDimitry Andric NamedDecl *PrevDecl = SemaRef.LookupSingleName( 3069*0fca6ea1SDimitry Andric SemaRef.TUScope, IdentList[i], IdentLocs[i], Sema::LookupOrdinaryName, 3070*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 30710b57cec5SDimitry Andric if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) { 30720b57cec5SDimitry Andric // GCC apparently allows the following idiom: 30730b57cec5SDimitry Andric // 30740b57cec5SDimitry Andric // typedef NSObject < XCElementTogglerP > XCElementToggler; 30750b57cec5SDimitry Andric // @class XCElementToggler; 30760b57cec5SDimitry Andric // 30770b57cec5SDimitry Andric // Here we have chosen to ignore the forward class declaration 30780b57cec5SDimitry Andric // with a warning. Since this is the implied behavior. 30790b57cec5SDimitry Andric TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl); 30800b57cec5SDimitry Andric if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { 30810b57cec5SDimitry Andric Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; 30820b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 30830b57cec5SDimitry Andric } else { 30840b57cec5SDimitry Andric // a forward class declaration matching a typedef name of a class refers 30850b57cec5SDimitry Andric // to the underlying class. Just ignore the forward class with a warning 30860b57cec5SDimitry Andric // as this will force the intended behavior which is to lookup the 30870b57cec5SDimitry Andric // typedef name. 30880b57cec5SDimitry Andric if (isa<ObjCObjectType>(TDD->getUnderlyingType())) { 30890b57cec5SDimitry Andric Diag(AtClassLoc, diag::warn_forward_class_redefinition) 30900b57cec5SDimitry Andric << IdentList[i]; 30910b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_definition); 30920b57cec5SDimitry Andric continue; 30930b57cec5SDimitry Andric } 30940b57cec5SDimitry Andric } 30950b57cec5SDimitry Andric } 30960b57cec5SDimitry Andric 30970b57cec5SDimitry Andric // Create a declaration to describe this forward declaration. 30980b57cec5SDimitry Andric ObjCInterfaceDecl *PrevIDecl 30990b57cec5SDimitry Andric = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); 31000b57cec5SDimitry Andric 31010b57cec5SDimitry Andric IdentifierInfo *ClassName = IdentList[i]; 31020b57cec5SDimitry Andric if (PrevIDecl && PrevIDecl->getIdentifier() != ClassName) { 31030b57cec5SDimitry Andric // A previous decl with a different name is because of 31040b57cec5SDimitry Andric // @compatibility_alias, for example: 31050b57cec5SDimitry Andric // \code 31060b57cec5SDimitry Andric // @class NewImage; 31070b57cec5SDimitry Andric // @compatibility_alias OldImage NewImage; 31080b57cec5SDimitry Andric // \endcode 31090b57cec5SDimitry Andric // A lookup for 'OldImage' will return the 'NewImage' decl. 31100b57cec5SDimitry Andric // 31110b57cec5SDimitry Andric // In such a case use the real declaration name, instead of the alias one, 31120b57cec5SDimitry Andric // otherwise we will break IdentifierResolver and redecls-chain invariants. 31130b57cec5SDimitry Andric // FIXME: If necessary, add a bit to indicate that this ObjCInterfaceDecl 31140b57cec5SDimitry Andric // has been aliased. 31150b57cec5SDimitry Andric ClassName = PrevIDecl->getIdentifier(); 31160b57cec5SDimitry Andric } 31170b57cec5SDimitry Andric 31180b57cec5SDimitry Andric // If this forward declaration has type parameters, compare them with the 31190b57cec5SDimitry Andric // type parameters of the previous declaration. 31200b57cec5SDimitry Andric ObjCTypeParamList *TypeParams = TypeParamLists[i]; 31210b57cec5SDimitry Andric if (PrevIDecl && TypeParams) { 31220b57cec5SDimitry Andric if (ObjCTypeParamList *PrevTypeParams = PrevIDecl->getTypeParamList()) { 31230b57cec5SDimitry Andric // Check for consistency with the previous declaration. 31240b57cec5SDimitry Andric if (checkTypeParamListConsistency( 3125*0fca6ea1SDimitry Andric SemaRef, PrevTypeParams, TypeParams, 31260b57cec5SDimitry Andric TypeParamListContext::ForwardDeclaration)) { 31270b57cec5SDimitry Andric TypeParams = nullptr; 31280b57cec5SDimitry Andric } 31290b57cec5SDimitry Andric } else if (ObjCInterfaceDecl *Def = PrevIDecl->getDefinition()) { 31300b57cec5SDimitry Andric // The @interface does not have type parameters. Complain. 31310b57cec5SDimitry Andric Diag(IdentLocs[i], diag::err_objc_parameterized_forward_class) 31320b57cec5SDimitry Andric << ClassName 31330b57cec5SDimitry Andric << TypeParams->getSourceRange(); 31340b57cec5SDimitry Andric Diag(Def->getLocation(), diag::note_defined_here) 31350b57cec5SDimitry Andric << ClassName; 31360b57cec5SDimitry Andric 31370b57cec5SDimitry Andric TypeParams = nullptr; 31380b57cec5SDimitry Andric } 31390b57cec5SDimitry Andric } 31400b57cec5SDimitry Andric 3141*0fca6ea1SDimitry Andric ObjCInterfaceDecl *IDecl = ObjCInterfaceDecl::Create( 3142*0fca6ea1SDimitry Andric Context, SemaRef.CurContext, AtClassLoc, ClassName, TypeParams, 3143*0fca6ea1SDimitry Andric PrevIDecl, IdentLocs[i]); 31440b57cec5SDimitry Andric IDecl->setAtEndRange(IdentLocs[i]); 31450b57cec5SDimitry Andric 3146e8d8bef9SDimitry Andric if (PrevIDecl) 3147*0fca6ea1SDimitry Andric SemaRef.mergeDeclAttributes(IDecl, PrevIDecl); 3148e8d8bef9SDimitry Andric 3149*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(IDecl, SemaRef.TUScope); 31500b57cec5SDimitry Andric CheckObjCDeclScope(IDecl); 31510b57cec5SDimitry Andric DeclsInGroup.push_back(IDecl); 31520b57cec5SDimitry Andric } 31530b57cec5SDimitry Andric 3154*0fca6ea1SDimitry Andric return SemaRef.BuildDeclaratorGroup(DeclsInGroup); 31550b57cec5SDimitry Andric } 31560b57cec5SDimitry Andric 31570b57cec5SDimitry Andric static bool tryMatchRecordTypes(ASTContext &Context, 3158*0fca6ea1SDimitry Andric SemaObjC::MethodMatchStrategy strategy, 31590b57cec5SDimitry Andric const Type *left, const Type *right); 31600b57cec5SDimitry Andric 3161*0fca6ea1SDimitry Andric static bool matchTypes(ASTContext &Context, 3162*0fca6ea1SDimitry Andric SemaObjC::MethodMatchStrategy strategy, QualType leftQT, 3163*0fca6ea1SDimitry Andric QualType rightQT) { 31640b57cec5SDimitry Andric const Type *left = 31650b57cec5SDimitry Andric Context.getCanonicalType(leftQT).getUnqualifiedType().getTypePtr(); 31660b57cec5SDimitry Andric const Type *right = 31670b57cec5SDimitry Andric Context.getCanonicalType(rightQT).getUnqualifiedType().getTypePtr(); 31680b57cec5SDimitry Andric 31690b57cec5SDimitry Andric if (left == right) return true; 31700b57cec5SDimitry Andric 31710b57cec5SDimitry Andric // If we're doing a strict match, the types have to match exactly. 3172*0fca6ea1SDimitry Andric if (strategy == SemaObjC::MMS_strict) 3173*0fca6ea1SDimitry Andric return false; 31740b57cec5SDimitry Andric 31750b57cec5SDimitry Andric if (left->isIncompleteType() || right->isIncompleteType()) return false; 31760b57cec5SDimitry Andric 31770b57cec5SDimitry Andric // Otherwise, use this absurdly complicated algorithm to try to 31780b57cec5SDimitry Andric // validate the basic, low-level compatibility of the two types. 31790b57cec5SDimitry Andric 31800b57cec5SDimitry Andric // As a minimum, require the sizes and alignments to match. 31810b57cec5SDimitry Andric TypeInfo LeftTI = Context.getTypeInfo(left); 31820b57cec5SDimitry Andric TypeInfo RightTI = Context.getTypeInfo(right); 31830b57cec5SDimitry Andric if (LeftTI.Width != RightTI.Width) 31840b57cec5SDimitry Andric return false; 31850b57cec5SDimitry Andric 31860b57cec5SDimitry Andric if (LeftTI.Align != RightTI.Align) 31870b57cec5SDimitry Andric return false; 31880b57cec5SDimitry Andric 31890b57cec5SDimitry Andric // Consider all the kinds of non-dependent canonical types: 31900b57cec5SDimitry Andric // - functions and arrays aren't possible as return and parameter types 31910b57cec5SDimitry Andric 31920b57cec5SDimitry Andric // - vector types of equal size can be arbitrarily mixed 31930b57cec5SDimitry Andric if (isa<VectorType>(left)) return isa<VectorType>(right); 31940b57cec5SDimitry Andric if (isa<VectorType>(right)) return false; 31950b57cec5SDimitry Andric 31960b57cec5SDimitry Andric // - references should only match references of identical type 31970b57cec5SDimitry Andric // - structs, unions, and Objective-C objects must match more-or-less 31980b57cec5SDimitry Andric // exactly 31990b57cec5SDimitry Andric // - everything else should be a scalar 32000b57cec5SDimitry Andric if (!left->isScalarType() || !right->isScalarType()) 32010b57cec5SDimitry Andric return tryMatchRecordTypes(Context, strategy, left, right); 32020b57cec5SDimitry Andric 32030b57cec5SDimitry Andric // Make scalars agree in kind, except count bools as chars, and group 32040b57cec5SDimitry Andric // all non-member pointers together. 32050b57cec5SDimitry Andric Type::ScalarTypeKind leftSK = left->getScalarTypeKind(); 32060b57cec5SDimitry Andric Type::ScalarTypeKind rightSK = right->getScalarTypeKind(); 32070b57cec5SDimitry Andric if (leftSK == Type::STK_Bool) leftSK = Type::STK_Integral; 32080b57cec5SDimitry Andric if (rightSK == Type::STK_Bool) rightSK = Type::STK_Integral; 32090b57cec5SDimitry Andric if (leftSK == Type::STK_CPointer || leftSK == Type::STK_BlockPointer) 32100b57cec5SDimitry Andric leftSK = Type::STK_ObjCObjectPointer; 32110b57cec5SDimitry Andric if (rightSK == Type::STK_CPointer || rightSK == Type::STK_BlockPointer) 32120b57cec5SDimitry Andric rightSK = Type::STK_ObjCObjectPointer; 32130b57cec5SDimitry Andric 32140b57cec5SDimitry Andric // Note that data member pointers and function member pointers don't 32150b57cec5SDimitry Andric // intermix because of the size differences. 32160b57cec5SDimitry Andric 32170b57cec5SDimitry Andric return (leftSK == rightSK); 32180b57cec5SDimitry Andric } 32190b57cec5SDimitry Andric 32200b57cec5SDimitry Andric static bool tryMatchRecordTypes(ASTContext &Context, 3221*0fca6ea1SDimitry Andric SemaObjC::MethodMatchStrategy strategy, 32220b57cec5SDimitry Andric const Type *lt, const Type *rt) { 32230b57cec5SDimitry Andric assert(lt && rt && lt != rt); 32240b57cec5SDimitry Andric 32250b57cec5SDimitry Andric if (!isa<RecordType>(lt) || !isa<RecordType>(rt)) return false; 32260b57cec5SDimitry Andric RecordDecl *left = cast<RecordType>(lt)->getDecl(); 32270b57cec5SDimitry Andric RecordDecl *right = cast<RecordType>(rt)->getDecl(); 32280b57cec5SDimitry Andric 32290b57cec5SDimitry Andric // Require union-hood to match. 32300b57cec5SDimitry Andric if (left->isUnion() != right->isUnion()) return false; 32310b57cec5SDimitry Andric 32320b57cec5SDimitry Andric // Require an exact match if either is non-POD. 32330b57cec5SDimitry Andric if ((isa<CXXRecordDecl>(left) && !cast<CXXRecordDecl>(left)->isPOD()) || 32340b57cec5SDimitry Andric (isa<CXXRecordDecl>(right) && !cast<CXXRecordDecl>(right)->isPOD())) 32350b57cec5SDimitry Andric return false; 32360b57cec5SDimitry Andric 32370b57cec5SDimitry Andric // Require size and alignment to match. 32380b57cec5SDimitry Andric TypeInfo LeftTI = Context.getTypeInfo(lt); 32390b57cec5SDimitry Andric TypeInfo RightTI = Context.getTypeInfo(rt); 32400b57cec5SDimitry Andric if (LeftTI.Width != RightTI.Width) 32410b57cec5SDimitry Andric return false; 32420b57cec5SDimitry Andric 32430b57cec5SDimitry Andric if (LeftTI.Align != RightTI.Align) 32440b57cec5SDimitry Andric return false; 32450b57cec5SDimitry Andric 32460b57cec5SDimitry Andric // Require fields to match. 32470b57cec5SDimitry Andric RecordDecl::field_iterator li = left->field_begin(), le = left->field_end(); 32480b57cec5SDimitry Andric RecordDecl::field_iterator ri = right->field_begin(), re = right->field_end(); 32490b57cec5SDimitry Andric for (; li != le && ri != re; ++li, ++ri) { 32500b57cec5SDimitry Andric if (!matchTypes(Context, strategy, li->getType(), ri->getType())) 32510b57cec5SDimitry Andric return false; 32520b57cec5SDimitry Andric } 32530b57cec5SDimitry Andric return (li == le && ri == re); 32540b57cec5SDimitry Andric } 32550b57cec5SDimitry Andric 32560b57cec5SDimitry Andric /// MatchTwoMethodDeclarations - Checks that two methods have matching type and 32570b57cec5SDimitry Andric /// returns true, or false, accordingly. 32580b57cec5SDimitry Andric /// TODO: Handle protocol list; such as id<p1,p2> in type comparisons 3259*0fca6ea1SDimitry Andric bool SemaObjC::MatchTwoMethodDeclarations(const ObjCMethodDecl *left, 32600b57cec5SDimitry Andric const ObjCMethodDecl *right, 32610b57cec5SDimitry Andric MethodMatchStrategy strategy) { 3262*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 32630b57cec5SDimitry Andric if (!matchTypes(Context, strategy, left->getReturnType(), 32640b57cec5SDimitry Andric right->getReturnType())) 32650b57cec5SDimitry Andric return false; 32660b57cec5SDimitry Andric 32670b57cec5SDimitry Andric // If either is hidden, it is not considered to match. 32685ffd83dbSDimitry Andric if (!left->isUnconditionallyVisible() || !right->isUnconditionallyVisible()) 32690b57cec5SDimitry Andric return false; 32700b57cec5SDimitry Andric 3271480093f4SDimitry Andric if (left->isDirectMethod() != right->isDirectMethod()) 3272480093f4SDimitry Andric return false; 3273480093f4SDimitry Andric 32740b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && 32750b57cec5SDimitry Andric (left->hasAttr<NSReturnsRetainedAttr>() 32760b57cec5SDimitry Andric != right->hasAttr<NSReturnsRetainedAttr>() || 32770b57cec5SDimitry Andric left->hasAttr<NSConsumesSelfAttr>() 32780b57cec5SDimitry Andric != right->hasAttr<NSConsumesSelfAttr>())) 32790b57cec5SDimitry Andric return false; 32800b57cec5SDimitry Andric 32810b57cec5SDimitry Andric ObjCMethodDecl::param_const_iterator 32820b57cec5SDimitry Andric li = left->param_begin(), le = left->param_end(), ri = right->param_begin(), 32830b57cec5SDimitry Andric re = right->param_end(); 32840b57cec5SDimitry Andric 32850b57cec5SDimitry Andric for (; li != le && ri != re; ++li, ++ri) { 32860b57cec5SDimitry Andric assert(ri != right->param_end() && "Param mismatch"); 32870b57cec5SDimitry Andric const ParmVarDecl *lparm = *li, *rparm = *ri; 32880b57cec5SDimitry Andric 32890b57cec5SDimitry Andric if (!matchTypes(Context, strategy, lparm->getType(), rparm->getType())) 32900b57cec5SDimitry Andric return false; 32910b57cec5SDimitry Andric 32920b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && 32930b57cec5SDimitry Andric lparm->hasAttr<NSConsumedAttr>() != rparm->hasAttr<NSConsumedAttr>()) 32940b57cec5SDimitry Andric return false; 32950b57cec5SDimitry Andric } 32960b57cec5SDimitry Andric return true; 32970b57cec5SDimitry Andric } 32980b57cec5SDimitry Andric 32990b57cec5SDimitry Andric static bool isMethodContextSameForKindofLookup(ObjCMethodDecl *Method, 33000b57cec5SDimitry Andric ObjCMethodDecl *MethodInList) { 33010b57cec5SDimitry Andric auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext()); 33020b57cec5SDimitry Andric auto *MethodInListProtocol = 33030b57cec5SDimitry Andric dyn_cast<ObjCProtocolDecl>(MethodInList->getDeclContext()); 33040b57cec5SDimitry Andric // If this method belongs to a protocol but the method in list does not, or 33050b57cec5SDimitry Andric // vice versa, we say the context is not the same. 33060b57cec5SDimitry Andric if ((MethodProtocol && !MethodInListProtocol) || 33070b57cec5SDimitry Andric (!MethodProtocol && MethodInListProtocol)) 33080b57cec5SDimitry Andric return false; 33090b57cec5SDimitry Andric 33100b57cec5SDimitry Andric if (MethodProtocol && MethodInListProtocol) 33110b57cec5SDimitry Andric return true; 33120b57cec5SDimitry Andric 33130b57cec5SDimitry Andric ObjCInterfaceDecl *MethodInterface = Method->getClassInterface(); 33140b57cec5SDimitry Andric ObjCInterfaceDecl *MethodInListInterface = 33150b57cec5SDimitry Andric MethodInList->getClassInterface(); 33160b57cec5SDimitry Andric return MethodInterface == MethodInListInterface; 33170b57cec5SDimitry Andric } 33180b57cec5SDimitry Andric 3319*0fca6ea1SDimitry Andric void SemaObjC::addMethodToGlobalList(ObjCMethodList *List, 33200b57cec5SDimitry Andric ObjCMethodDecl *Method) { 33210b57cec5SDimitry Andric // Record at the head of the list whether there were 0, 1, or >= 2 methods 33220b57cec5SDimitry Andric // inside categories. 33230b57cec5SDimitry Andric if (ObjCCategoryDecl *CD = 33240b57cec5SDimitry Andric dyn_cast<ObjCCategoryDecl>(Method->getDeclContext())) 33250b57cec5SDimitry Andric if (!CD->IsClassExtension() && List->getBits() < 2) 33260b57cec5SDimitry Andric List->setBits(List->getBits() + 1); 33270b57cec5SDimitry Andric 33280b57cec5SDimitry Andric // If the list is empty, make it a singleton list. 33290b57cec5SDimitry Andric if (List->getMethod() == nullptr) { 33300b57cec5SDimitry Andric List->setMethod(Method); 33310b57cec5SDimitry Andric List->setNext(nullptr); 33320b57cec5SDimitry Andric return; 33330b57cec5SDimitry Andric } 33340b57cec5SDimitry Andric 33350b57cec5SDimitry Andric // We've seen a method with this name, see if we have already seen this type 33360b57cec5SDimitry Andric // signature. 33370b57cec5SDimitry Andric ObjCMethodList *Previous = List; 33380b57cec5SDimitry Andric ObjCMethodList *ListWithSameDeclaration = nullptr; 33390b57cec5SDimitry Andric for (; List; Previous = List, List = List->getNext()) { 33400b57cec5SDimitry Andric // If we are building a module, keep all of the methods. 33410b57cec5SDimitry Andric if (getLangOpts().isCompilingModule()) 33420b57cec5SDimitry Andric continue; 33430b57cec5SDimitry Andric 33440b57cec5SDimitry Andric bool SameDeclaration = MatchTwoMethodDeclarations(Method, 33450b57cec5SDimitry Andric List->getMethod()); 33460b57cec5SDimitry Andric // Looking for method with a type bound requires the correct context exists. 33470b57cec5SDimitry Andric // We need to insert a method into the list if the context is different. 33480b57cec5SDimitry Andric // If the method's declaration matches the list 33490b57cec5SDimitry Andric // a> the method belongs to a different context: we need to insert it, in 33500b57cec5SDimitry Andric // order to emit the availability message, we need to prioritize over 33510b57cec5SDimitry Andric // availability among the methods with the same declaration. 33520b57cec5SDimitry Andric // b> the method belongs to the same context: there is no need to insert a 33530b57cec5SDimitry Andric // new entry. 33540b57cec5SDimitry Andric // If the method's declaration does not match the list, we insert it to the 33550b57cec5SDimitry Andric // end. 33560b57cec5SDimitry Andric if (!SameDeclaration || 33570b57cec5SDimitry Andric !isMethodContextSameForKindofLookup(Method, List->getMethod())) { 33580b57cec5SDimitry Andric // Even if two method types do not match, we would like to say 33590b57cec5SDimitry Andric // there is more than one declaration so unavailability/deprecated 33600b57cec5SDimitry Andric // warning is not too noisy. 33610b57cec5SDimitry Andric if (!Method->isDefined()) 33620b57cec5SDimitry Andric List->setHasMoreThanOneDecl(true); 33630b57cec5SDimitry Andric 33640b57cec5SDimitry Andric // For methods with the same declaration, the one that is deprecated 33650b57cec5SDimitry Andric // should be put in the front for better diagnostics. 33660b57cec5SDimitry Andric if (Method->isDeprecated() && SameDeclaration && 33670b57cec5SDimitry Andric !ListWithSameDeclaration && !List->getMethod()->isDeprecated()) 33680b57cec5SDimitry Andric ListWithSameDeclaration = List; 33690b57cec5SDimitry Andric 33700b57cec5SDimitry Andric if (Method->isUnavailable() && SameDeclaration && 33710b57cec5SDimitry Andric !ListWithSameDeclaration && 33720b57cec5SDimitry Andric List->getMethod()->getAvailability() < AR_Deprecated) 33730b57cec5SDimitry Andric ListWithSameDeclaration = List; 33740b57cec5SDimitry Andric continue; 33750b57cec5SDimitry Andric } 33760b57cec5SDimitry Andric 33770b57cec5SDimitry Andric ObjCMethodDecl *PrevObjCMethod = List->getMethod(); 33780b57cec5SDimitry Andric 33790b57cec5SDimitry Andric // Propagate the 'defined' bit. 33800b57cec5SDimitry Andric if (Method->isDefined()) 33810b57cec5SDimitry Andric PrevObjCMethod->setDefined(true); 33820b57cec5SDimitry Andric else { 33830b57cec5SDimitry Andric // Objective-C doesn't allow an @interface for a class after its 33840b57cec5SDimitry Andric // @implementation. So if Method is not defined and there already is 33850b57cec5SDimitry Andric // an entry for this type signature, Method has to be for a different 33860b57cec5SDimitry Andric // class than PrevObjCMethod. 33870b57cec5SDimitry Andric List->setHasMoreThanOneDecl(true); 33880b57cec5SDimitry Andric } 33890b57cec5SDimitry Andric 33900b57cec5SDimitry Andric // If a method is deprecated, push it in the global pool. 33910b57cec5SDimitry Andric // This is used for better diagnostics. 33920b57cec5SDimitry Andric if (Method->isDeprecated()) { 33930b57cec5SDimitry Andric if (!PrevObjCMethod->isDeprecated()) 33940b57cec5SDimitry Andric List->setMethod(Method); 33950b57cec5SDimitry Andric } 33960b57cec5SDimitry Andric // If the new method is unavailable, push it into global pool 33970b57cec5SDimitry Andric // unless previous one is deprecated. 33980b57cec5SDimitry Andric if (Method->isUnavailable()) { 33990b57cec5SDimitry Andric if (PrevObjCMethod->getAvailability() < AR_Deprecated) 34000b57cec5SDimitry Andric List->setMethod(Method); 34010b57cec5SDimitry Andric } 34020b57cec5SDimitry Andric 34030b57cec5SDimitry Andric return; 34040b57cec5SDimitry Andric } 34050b57cec5SDimitry Andric 34060b57cec5SDimitry Andric // We have a new signature for an existing method - add it. 34070b57cec5SDimitry Andric // This is extremely rare. Only 1% of Cocoa selectors are "overloaded". 3408*0fca6ea1SDimitry Andric ObjCMethodList *Mem = SemaRef.BumpAlloc.Allocate<ObjCMethodList>(); 34090b57cec5SDimitry Andric 34100b57cec5SDimitry Andric // We insert it right before ListWithSameDeclaration. 34110b57cec5SDimitry Andric if (ListWithSameDeclaration) { 34120b57cec5SDimitry Andric auto *List = new (Mem) ObjCMethodList(*ListWithSameDeclaration); 34130b57cec5SDimitry Andric // FIXME: should we clear the other bits in ListWithSameDeclaration? 34140b57cec5SDimitry Andric ListWithSameDeclaration->setMethod(Method); 34150b57cec5SDimitry Andric ListWithSameDeclaration->setNext(List); 34160b57cec5SDimitry Andric return; 34170b57cec5SDimitry Andric } 34180b57cec5SDimitry Andric 34190b57cec5SDimitry Andric Previous->setNext(new (Mem) ObjCMethodList(Method)); 34200b57cec5SDimitry Andric } 34210b57cec5SDimitry Andric 34220b57cec5SDimitry Andric /// Read the contents of the method pool for a given selector from 34230b57cec5SDimitry Andric /// external storage. 3424*0fca6ea1SDimitry Andric void SemaObjC::ReadMethodPool(Selector Sel) { 3425*0fca6ea1SDimitry Andric assert(SemaRef.ExternalSource && "We need an external AST source"); 3426*0fca6ea1SDimitry Andric SemaRef.ExternalSource->ReadMethodPool(Sel); 34270b57cec5SDimitry Andric } 34280b57cec5SDimitry Andric 3429*0fca6ea1SDimitry Andric void SemaObjC::updateOutOfDateSelector(Selector Sel) { 3430*0fca6ea1SDimitry Andric if (!SemaRef.ExternalSource) 34310b57cec5SDimitry Andric return; 3432*0fca6ea1SDimitry Andric SemaRef.ExternalSource->updateOutOfDateSelector(Sel); 34330b57cec5SDimitry Andric } 34340b57cec5SDimitry Andric 3435*0fca6ea1SDimitry Andric void SemaObjC::AddMethodToGlobalPool(ObjCMethodDecl *Method, bool impl, 34360b57cec5SDimitry Andric bool instance) { 34370b57cec5SDimitry Andric // Ignore methods of invalid containers. 34380b57cec5SDimitry Andric if (cast<Decl>(Method->getDeclContext())->isInvalidDecl()) 34390b57cec5SDimitry Andric return; 34400b57cec5SDimitry Andric 3441*0fca6ea1SDimitry Andric if (SemaRef.ExternalSource) 34420b57cec5SDimitry Andric ReadMethodPool(Method->getSelector()); 34430b57cec5SDimitry Andric 34440b57cec5SDimitry Andric GlobalMethodPool::iterator Pos = MethodPool.find(Method->getSelector()); 34450b57cec5SDimitry Andric if (Pos == MethodPool.end()) 3446349cc55cSDimitry Andric Pos = MethodPool 3447349cc55cSDimitry Andric .insert(std::make_pair(Method->getSelector(), 3448349cc55cSDimitry Andric GlobalMethodPool::Lists())) 3449349cc55cSDimitry Andric .first; 34500b57cec5SDimitry Andric 34510b57cec5SDimitry Andric Method->setDefined(impl); 34520b57cec5SDimitry Andric 34530b57cec5SDimitry Andric ObjCMethodList &Entry = instance ? Pos->second.first : Pos->second.second; 34540b57cec5SDimitry Andric addMethodToGlobalList(&Entry, Method); 34550b57cec5SDimitry Andric } 34560b57cec5SDimitry Andric 34570b57cec5SDimitry Andric /// Determines if this is an "acceptable" loose mismatch in the global 34580b57cec5SDimitry Andric /// method pool. This exists mostly as a hack to get around certain 34590b57cec5SDimitry Andric /// global mismatches which we can't afford to make warnings / errors. 34600b57cec5SDimitry Andric /// Really, what we want is a way to take a method out of the global 34610b57cec5SDimitry Andric /// method pool. 34620b57cec5SDimitry Andric static bool isAcceptableMethodMismatch(ObjCMethodDecl *chosen, 34630b57cec5SDimitry Andric ObjCMethodDecl *other) { 34640b57cec5SDimitry Andric if (!chosen->isInstanceMethod()) 34650b57cec5SDimitry Andric return false; 34660b57cec5SDimitry Andric 3467480093f4SDimitry Andric if (chosen->isDirectMethod() != other->isDirectMethod()) 3468480093f4SDimitry Andric return false; 3469480093f4SDimitry Andric 34700b57cec5SDimitry Andric Selector sel = chosen->getSelector(); 34710b57cec5SDimitry Andric if (!sel.isUnarySelector() || sel.getNameForSlot(0) != "length") 34720b57cec5SDimitry Andric return false; 34730b57cec5SDimitry Andric 34740b57cec5SDimitry Andric // Don't complain about mismatches for -length if the method we 34750b57cec5SDimitry Andric // chose has an integral result type. 34760b57cec5SDimitry Andric return (chosen->getReturnType()->isIntegerType()); 34770b57cec5SDimitry Andric } 34780b57cec5SDimitry Andric 34790b57cec5SDimitry Andric /// Return true if the given method is wthin the type bound. 34800b57cec5SDimitry Andric static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method, 34810b57cec5SDimitry Andric const ObjCObjectType *TypeBound) { 34820b57cec5SDimitry Andric if (!TypeBound) 34830b57cec5SDimitry Andric return true; 34840b57cec5SDimitry Andric 34850b57cec5SDimitry Andric if (TypeBound->isObjCId()) 34860b57cec5SDimitry Andric // FIXME: should we handle the case of bounding to id<A, B> differently? 34870b57cec5SDimitry Andric return true; 34880b57cec5SDimitry Andric 34890b57cec5SDimitry Andric auto *BoundInterface = TypeBound->getInterface(); 34900b57cec5SDimitry Andric assert(BoundInterface && "unexpected object type!"); 34910b57cec5SDimitry Andric 34920b57cec5SDimitry Andric // Check if the Method belongs to a protocol. We should allow any method 34930b57cec5SDimitry Andric // defined in any protocol, because any subclass could adopt the protocol. 34940b57cec5SDimitry Andric auto *MethodProtocol = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext()); 34950b57cec5SDimitry Andric if (MethodProtocol) { 34960b57cec5SDimitry Andric return true; 34970b57cec5SDimitry Andric } 34980b57cec5SDimitry Andric 34990b57cec5SDimitry Andric // If the Method belongs to a class, check if it belongs to the class 35000b57cec5SDimitry Andric // hierarchy of the class bound. 35010b57cec5SDimitry Andric if (ObjCInterfaceDecl *MethodInterface = Method->getClassInterface()) { 35020b57cec5SDimitry Andric // We allow methods declared within classes that are part of the hierarchy 35030b57cec5SDimitry Andric // of the class bound (superclass of, subclass of, or the same as the class 35040b57cec5SDimitry Andric // bound). 35050b57cec5SDimitry Andric return MethodInterface == BoundInterface || 35060b57cec5SDimitry Andric MethodInterface->isSuperClassOf(BoundInterface) || 35070b57cec5SDimitry Andric BoundInterface->isSuperClassOf(MethodInterface); 35080b57cec5SDimitry Andric } 35090b57cec5SDimitry Andric llvm_unreachable("unknown method context"); 35100b57cec5SDimitry Andric } 35110b57cec5SDimitry Andric 35120b57cec5SDimitry Andric /// We first select the type of the method: Instance or Factory, then collect 35130b57cec5SDimitry Andric /// all methods with that type. 3514*0fca6ea1SDimitry Andric bool SemaObjC::CollectMultipleMethodsInGlobalPool( 35150b57cec5SDimitry Andric Selector Sel, SmallVectorImpl<ObjCMethodDecl *> &Methods, 3516*0fca6ea1SDimitry Andric bool InstanceFirst, bool CheckTheOther, const ObjCObjectType *TypeBound) { 3517*0fca6ea1SDimitry Andric if (SemaRef.ExternalSource) 35180b57cec5SDimitry Andric ReadMethodPool(Sel); 35190b57cec5SDimitry Andric 35200b57cec5SDimitry Andric GlobalMethodPool::iterator Pos = MethodPool.find(Sel); 35210b57cec5SDimitry Andric if (Pos == MethodPool.end()) 35220b57cec5SDimitry Andric return false; 35230b57cec5SDimitry Andric 35240b57cec5SDimitry Andric // Gather the non-hidden methods. 35250b57cec5SDimitry Andric ObjCMethodList &MethList = InstanceFirst ? Pos->second.first : 35260b57cec5SDimitry Andric Pos->second.second; 35270b57cec5SDimitry Andric for (ObjCMethodList *M = &MethList; M; M = M->getNext()) 35285ffd83dbSDimitry Andric if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) { 35290b57cec5SDimitry Andric if (FilterMethodsByTypeBound(M->getMethod(), TypeBound)) 35300b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 35310b57cec5SDimitry Andric } 35320b57cec5SDimitry Andric 35330b57cec5SDimitry Andric // Return if we find any method with the desired kind. 35340b57cec5SDimitry Andric if (!Methods.empty()) 35350b57cec5SDimitry Andric return Methods.size() > 1; 35360b57cec5SDimitry Andric 35370b57cec5SDimitry Andric if (!CheckTheOther) 35380b57cec5SDimitry Andric return false; 35390b57cec5SDimitry Andric 35400b57cec5SDimitry Andric // Gather the other kind. 35410b57cec5SDimitry Andric ObjCMethodList &MethList2 = InstanceFirst ? Pos->second.second : 35420b57cec5SDimitry Andric Pos->second.first; 35430b57cec5SDimitry Andric for (ObjCMethodList *M = &MethList2; M; M = M->getNext()) 35445ffd83dbSDimitry Andric if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) { 35450b57cec5SDimitry Andric if (FilterMethodsByTypeBound(M->getMethod(), TypeBound)) 35460b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 35470b57cec5SDimitry Andric } 35480b57cec5SDimitry Andric 35490b57cec5SDimitry Andric return Methods.size() > 1; 35500b57cec5SDimitry Andric } 35510b57cec5SDimitry Andric 3552*0fca6ea1SDimitry Andric bool SemaObjC::AreMultipleMethodsInGlobalPool( 35530b57cec5SDimitry Andric Selector Sel, ObjCMethodDecl *BestMethod, SourceRange R, 35540b57cec5SDimitry Andric bool receiverIdOrClass, SmallVectorImpl<ObjCMethodDecl *> &Methods) { 35550b57cec5SDimitry Andric // Diagnose finding more than one method in global pool. 35560b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 4> FilteredMethods; 35570b57cec5SDimitry Andric FilteredMethods.push_back(BestMethod); 35580b57cec5SDimitry Andric 35590b57cec5SDimitry Andric for (auto *M : Methods) 35600b57cec5SDimitry Andric if (M != BestMethod && !M->hasAttr<UnavailableAttr>()) 35610b57cec5SDimitry Andric FilteredMethods.push_back(M); 35620b57cec5SDimitry Andric 35630b57cec5SDimitry Andric if (FilteredMethods.size() > 1) 35640b57cec5SDimitry Andric DiagnoseMultipleMethodInGlobalPool(FilteredMethods, Sel, R, 35650b57cec5SDimitry Andric receiverIdOrClass); 35660b57cec5SDimitry Andric 35670b57cec5SDimitry Andric GlobalMethodPool::iterator Pos = MethodPool.find(Sel); 35680b57cec5SDimitry Andric // Test for no method in the pool which should not trigger any warning by 35690b57cec5SDimitry Andric // caller. 35700b57cec5SDimitry Andric if (Pos == MethodPool.end()) 35710b57cec5SDimitry Andric return true; 35720b57cec5SDimitry Andric ObjCMethodList &MethList = 35730b57cec5SDimitry Andric BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second; 35740b57cec5SDimitry Andric return MethList.hasMoreThanOneDecl(); 35750b57cec5SDimitry Andric } 35760b57cec5SDimitry Andric 3577*0fca6ea1SDimitry Andric ObjCMethodDecl *SemaObjC::LookupMethodInGlobalPool(Selector Sel, SourceRange R, 35780b57cec5SDimitry Andric bool receiverIdOrClass, 35790b57cec5SDimitry Andric bool instance) { 3580*0fca6ea1SDimitry Andric if (SemaRef.ExternalSource) 35810b57cec5SDimitry Andric ReadMethodPool(Sel); 35820b57cec5SDimitry Andric 35830b57cec5SDimitry Andric GlobalMethodPool::iterator Pos = MethodPool.find(Sel); 35840b57cec5SDimitry Andric if (Pos == MethodPool.end()) 35850b57cec5SDimitry Andric return nullptr; 35860b57cec5SDimitry Andric 35870b57cec5SDimitry Andric // Gather the non-hidden methods. 35880b57cec5SDimitry Andric ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; 35890b57cec5SDimitry Andric SmallVector<ObjCMethodDecl *, 4> Methods; 35900b57cec5SDimitry Andric for (ObjCMethodList *M = &MethList; M; M = M->getNext()) { 35915ffd83dbSDimitry Andric if (M->getMethod() && M->getMethod()->isUnconditionallyVisible()) 35920b57cec5SDimitry Andric return M->getMethod(); 35930b57cec5SDimitry Andric } 35940b57cec5SDimitry Andric return nullptr; 35950b57cec5SDimitry Andric } 35960b57cec5SDimitry Andric 3597*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseMultipleMethodInGlobalPool( 3598*0fca6ea1SDimitry Andric SmallVectorImpl<ObjCMethodDecl *> &Methods, Selector Sel, SourceRange R, 35990b57cec5SDimitry Andric bool receiverIdOrClass) { 36000b57cec5SDimitry Andric // We found multiple methods, so we may have to complain. 36010b57cec5SDimitry Andric bool issueDiagnostic = false, issueError = false; 36020b57cec5SDimitry Andric 36030b57cec5SDimitry Andric // We support a warning which complains about *any* difference in 36040b57cec5SDimitry Andric // method signature. 36050b57cec5SDimitry Andric bool strictSelectorMatch = 36060b57cec5SDimitry Andric receiverIdOrClass && 3607*0fca6ea1SDimitry Andric !getDiagnostics().isIgnored(diag::warn_strict_multiple_method_decl, 3608*0fca6ea1SDimitry Andric R.getBegin()); 36090b57cec5SDimitry Andric if (strictSelectorMatch) { 36100b57cec5SDimitry Andric for (unsigned I = 1, N = Methods.size(); I != N; ++I) { 36110b57cec5SDimitry Andric if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) { 36120b57cec5SDimitry Andric issueDiagnostic = true; 36130b57cec5SDimitry Andric break; 36140b57cec5SDimitry Andric } 36150b57cec5SDimitry Andric } 36160b57cec5SDimitry Andric } 36170b57cec5SDimitry Andric 36180b57cec5SDimitry Andric // If we didn't see any strict differences, we won't see any loose 36190b57cec5SDimitry Andric // differences. In ARC, however, we also need to check for loose 36200b57cec5SDimitry Andric // mismatches, because most of them are errors. 36210b57cec5SDimitry Andric if (!strictSelectorMatch || 36220b57cec5SDimitry Andric (issueDiagnostic && getLangOpts().ObjCAutoRefCount)) 36230b57cec5SDimitry Andric for (unsigned I = 1, N = Methods.size(); I != N; ++I) { 36240b57cec5SDimitry Andric // This checks if the methods differ in type mismatch. 36250b57cec5SDimitry Andric if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_loose) && 36260b57cec5SDimitry Andric !isAcceptableMethodMismatch(Methods[0], Methods[I])) { 36270b57cec5SDimitry Andric issueDiagnostic = true; 36280b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) 36290b57cec5SDimitry Andric issueError = true; 36300b57cec5SDimitry Andric break; 36310b57cec5SDimitry Andric } 36320b57cec5SDimitry Andric } 36330b57cec5SDimitry Andric 36340b57cec5SDimitry Andric if (issueDiagnostic) { 36350b57cec5SDimitry Andric if (issueError) 36360b57cec5SDimitry Andric Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; 36370b57cec5SDimitry Andric else if (strictSelectorMatch) 36380b57cec5SDimitry Andric Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; 36390b57cec5SDimitry Andric else 36400b57cec5SDimitry Andric Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; 36410b57cec5SDimitry Andric 36420b57cec5SDimitry Andric Diag(Methods[0]->getBeginLoc(), 36430b57cec5SDimitry Andric issueError ? diag::note_possibility : diag::note_using) 36440b57cec5SDimitry Andric << Methods[0]->getSourceRange(); 36450b57cec5SDimitry Andric for (unsigned I = 1, N = Methods.size(); I != N; ++I) { 36460b57cec5SDimitry Andric Diag(Methods[I]->getBeginLoc(), diag::note_also_found) 36470b57cec5SDimitry Andric << Methods[I]->getSourceRange(); 36480b57cec5SDimitry Andric } 36490b57cec5SDimitry Andric } 36500b57cec5SDimitry Andric } 36510b57cec5SDimitry Andric 3652*0fca6ea1SDimitry Andric ObjCMethodDecl *SemaObjC::LookupImplementedMethodInGlobalPool(Selector Sel) { 36530b57cec5SDimitry Andric GlobalMethodPool::iterator Pos = MethodPool.find(Sel); 36540b57cec5SDimitry Andric if (Pos == MethodPool.end()) 36550b57cec5SDimitry Andric return nullptr; 36560b57cec5SDimitry Andric 3657349cc55cSDimitry Andric GlobalMethodPool::Lists &Methods = Pos->second; 36580b57cec5SDimitry Andric for (const ObjCMethodList *Method = &Methods.first; Method; 36590b57cec5SDimitry Andric Method = Method->getNext()) 36600b57cec5SDimitry Andric if (Method->getMethod() && 36610b57cec5SDimitry Andric (Method->getMethod()->isDefined() || 36620b57cec5SDimitry Andric Method->getMethod()->isPropertyAccessor())) 36630b57cec5SDimitry Andric return Method->getMethod(); 36640b57cec5SDimitry Andric 36650b57cec5SDimitry Andric for (const ObjCMethodList *Method = &Methods.second; Method; 36660b57cec5SDimitry Andric Method = Method->getNext()) 36670b57cec5SDimitry Andric if (Method->getMethod() && 36680b57cec5SDimitry Andric (Method->getMethod()->isDefined() || 36690b57cec5SDimitry Andric Method->getMethod()->isPropertyAccessor())) 36700b57cec5SDimitry Andric return Method->getMethod(); 36710b57cec5SDimitry Andric return nullptr; 36720b57cec5SDimitry Andric } 36730b57cec5SDimitry Andric 36740b57cec5SDimitry Andric static void 36750b57cec5SDimitry Andric HelperSelectorsForTypoCorrection( 36760b57cec5SDimitry Andric SmallVectorImpl<const ObjCMethodDecl *> &BestMethod, 36770b57cec5SDimitry Andric StringRef Typo, const ObjCMethodDecl * Method) { 36780b57cec5SDimitry Andric const unsigned MaxEditDistance = 1; 36790b57cec5SDimitry Andric unsigned BestEditDistance = MaxEditDistance + 1; 36800b57cec5SDimitry Andric std::string MethodName = Method->getSelector().getAsString(); 36810b57cec5SDimitry Andric 36820b57cec5SDimitry Andric unsigned MinPossibleEditDistance = abs((int)MethodName.size() - (int)Typo.size()); 36830b57cec5SDimitry Andric if (MinPossibleEditDistance > 0 && 36840b57cec5SDimitry Andric Typo.size() / MinPossibleEditDistance < 1) 36850b57cec5SDimitry Andric return; 36860b57cec5SDimitry Andric unsigned EditDistance = Typo.edit_distance(MethodName, true, MaxEditDistance); 36870b57cec5SDimitry Andric if (EditDistance > MaxEditDistance) 36880b57cec5SDimitry Andric return; 36890b57cec5SDimitry Andric if (EditDistance == BestEditDistance) 36900b57cec5SDimitry Andric BestMethod.push_back(Method); 36910b57cec5SDimitry Andric else if (EditDistance < BestEditDistance) { 36920b57cec5SDimitry Andric BestMethod.clear(); 36930b57cec5SDimitry Andric BestMethod.push_back(Method); 36940b57cec5SDimitry Andric } 36950b57cec5SDimitry Andric } 36960b57cec5SDimitry Andric 36970b57cec5SDimitry Andric static bool HelperIsMethodInObjCType(Sema &S, Selector Sel, 36980b57cec5SDimitry Andric QualType ObjectType) { 36990b57cec5SDimitry Andric if (ObjectType.isNull()) 37000b57cec5SDimitry Andric return true; 3701*0fca6ea1SDimitry Andric if (S.ObjC().LookupMethodInObjectType(Sel, ObjectType, 3702*0fca6ea1SDimitry Andric true /*Instance method*/)) 37030b57cec5SDimitry Andric return true; 3704*0fca6ea1SDimitry Andric return S.ObjC().LookupMethodInObjectType(Sel, ObjectType, 3705*0fca6ea1SDimitry Andric false /*Class method*/) != nullptr; 37060b57cec5SDimitry Andric } 37070b57cec5SDimitry Andric 37080b57cec5SDimitry Andric const ObjCMethodDecl * 3709*0fca6ea1SDimitry Andric SemaObjC::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) { 37100b57cec5SDimitry Andric unsigned NumArgs = Sel.getNumArgs(); 37110b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 8> Methods; 37120b57cec5SDimitry Andric bool ObjectIsId = true, ObjectIsClass = true; 37130b57cec5SDimitry Andric if (ObjectType.isNull()) 37140b57cec5SDimitry Andric ObjectIsId = ObjectIsClass = false; 37150b57cec5SDimitry Andric else if (!ObjectType->isObjCObjectPointerType()) 37160b57cec5SDimitry Andric return nullptr; 37170b57cec5SDimitry Andric else if (const ObjCObjectPointerType *ObjCPtr = 37180b57cec5SDimitry Andric ObjectType->getAsObjCInterfacePointerType()) { 37190b57cec5SDimitry Andric ObjectType = QualType(ObjCPtr->getInterfaceType(), 0); 37200b57cec5SDimitry Andric ObjectIsId = ObjectIsClass = false; 37210b57cec5SDimitry Andric } 37220b57cec5SDimitry Andric else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType()) 37230b57cec5SDimitry Andric ObjectIsClass = false; 37240b57cec5SDimitry Andric else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType()) 37250b57cec5SDimitry Andric ObjectIsId = false; 37260b57cec5SDimitry Andric else 37270b57cec5SDimitry Andric return nullptr; 37280b57cec5SDimitry Andric 37290b57cec5SDimitry Andric for (GlobalMethodPool::iterator b = MethodPool.begin(), 37300b57cec5SDimitry Andric e = MethodPool.end(); b != e; b++) { 37310b57cec5SDimitry Andric // instance methods 37320b57cec5SDimitry Andric for (ObjCMethodList *M = &b->second.first; M; M=M->getNext()) 37330b57cec5SDimitry Andric if (M->getMethod() && 37340b57cec5SDimitry Andric (M->getMethod()->getSelector().getNumArgs() == NumArgs) && 37350b57cec5SDimitry Andric (M->getMethod()->getSelector() != Sel)) { 37360b57cec5SDimitry Andric if (ObjectIsId) 37370b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 37380b57cec5SDimitry Andric else if (!ObjectIsClass && 3739*0fca6ea1SDimitry Andric HelperIsMethodInObjCType( 3740*0fca6ea1SDimitry Andric SemaRef, M->getMethod()->getSelector(), ObjectType)) 37410b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 37420b57cec5SDimitry Andric } 37430b57cec5SDimitry Andric // class methods 37440b57cec5SDimitry Andric for (ObjCMethodList *M = &b->second.second; M; M=M->getNext()) 37450b57cec5SDimitry Andric if (M->getMethod() && 37460b57cec5SDimitry Andric (M->getMethod()->getSelector().getNumArgs() == NumArgs) && 37470b57cec5SDimitry Andric (M->getMethod()->getSelector() != Sel)) { 37480b57cec5SDimitry Andric if (ObjectIsClass) 37490b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 37500b57cec5SDimitry Andric else if (!ObjectIsId && 3751*0fca6ea1SDimitry Andric HelperIsMethodInObjCType( 3752*0fca6ea1SDimitry Andric SemaRef, M->getMethod()->getSelector(), ObjectType)) 37530b57cec5SDimitry Andric Methods.push_back(M->getMethod()); 37540b57cec5SDimitry Andric } 37550b57cec5SDimitry Andric } 37560b57cec5SDimitry Andric 37570b57cec5SDimitry Andric SmallVector<const ObjCMethodDecl *, 8> SelectedMethods; 37580b57cec5SDimitry Andric for (unsigned i = 0, e = Methods.size(); i < e; i++) { 37590b57cec5SDimitry Andric HelperSelectorsForTypoCorrection(SelectedMethods, 37600b57cec5SDimitry Andric Sel.getAsString(), Methods[i]); 37610b57cec5SDimitry Andric } 37620b57cec5SDimitry Andric return (SelectedMethods.size() == 1) ? SelectedMethods[0] : nullptr; 37630b57cec5SDimitry Andric } 37640b57cec5SDimitry Andric 37650b57cec5SDimitry Andric /// DiagnoseDuplicateIvars - 37660b57cec5SDimitry Andric /// Check for duplicate ivars in the entire class at the start of 3767bdd1243dSDimitry Andric /// \@implementation. This becomes necessary because class extension can 37680b57cec5SDimitry Andric /// add ivars to a class in random order which will not be known until 37690b57cec5SDimitry Andric /// class's \@implementation is seen. 3770*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseDuplicateIvars(ObjCInterfaceDecl *ID, 37710b57cec5SDimitry Andric ObjCInterfaceDecl *SID) { 37720b57cec5SDimitry Andric for (auto *Ivar : ID->ivars()) { 37730b57cec5SDimitry Andric if (Ivar->isInvalidDecl()) 37740b57cec5SDimitry Andric continue; 37750b57cec5SDimitry Andric if (IdentifierInfo *II = Ivar->getIdentifier()) { 37760b57cec5SDimitry Andric ObjCIvarDecl* prevIvar = SID->lookupInstanceVariable(II); 37770b57cec5SDimitry Andric if (prevIvar) { 37780b57cec5SDimitry Andric Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; 37790b57cec5SDimitry Andric Diag(prevIvar->getLocation(), diag::note_previous_declaration); 37800b57cec5SDimitry Andric Ivar->setInvalidDecl(); 37810b57cec5SDimitry Andric } 37820b57cec5SDimitry Andric } 37830b57cec5SDimitry Andric } 37840b57cec5SDimitry Andric } 37850b57cec5SDimitry Andric 37860b57cec5SDimitry Andric /// Diagnose attempts to define ARC-__weak ivars when __weak is disabled. 37870b57cec5SDimitry Andric static void DiagnoseWeakIvars(Sema &S, ObjCImplementationDecl *ID) { 37880b57cec5SDimitry Andric if (S.getLangOpts().ObjCWeak) return; 37890b57cec5SDimitry Andric 37900b57cec5SDimitry Andric for (auto ivar = ID->getClassInterface()->all_declared_ivar_begin(); 37910b57cec5SDimitry Andric ivar; ivar = ivar->getNextIvar()) { 37920b57cec5SDimitry Andric if (ivar->isInvalidDecl()) continue; 37930b57cec5SDimitry Andric if (ivar->getType().getObjCLifetime() == Qualifiers::OCL_Weak) { 37940b57cec5SDimitry Andric if (S.getLangOpts().ObjCWeakRuntime) { 37950b57cec5SDimitry Andric S.Diag(ivar->getLocation(), diag::err_arc_weak_disabled); 37960b57cec5SDimitry Andric } else { 37970b57cec5SDimitry Andric S.Diag(ivar->getLocation(), diag::err_arc_weak_no_runtime); 37980b57cec5SDimitry Andric } 37990b57cec5SDimitry Andric } 38000b57cec5SDimitry Andric } 38010b57cec5SDimitry Andric } 38020b57cec5SDimitry Andric 38030b57cec5SDimitry Andric /// Diagnose attempts to use flexible array member with retainable object type. 38040b57cec5SDimitry Andric static void DiagnoseRetainableFlexibleArrayMember(Sema &S, 38050b57cec5SDimitry Andric ObjCInterfaceDecl *ID) { 38060b57cec5SDimitry Andric if (!S.getLangOpts().ObjCAutoRefCount) 38070b57cec5SDimitry Andric return; 38080b57cec5SDimitry Andric 38090b57cec5SDimitry Andric for (auto ivar = ID->all_declared_ivar_begin(); ivar; 38100b57cec5SDimitry Andric ivar = ivar->getNextIvar()) { 38110b57cec5SDimitry Andric if (ivar->isInvalidDecl()) 38120b57cec5SDimitry Andric continue; 38130b57cec5SDimitry Andric QualType IvarTy = ivar->getType(); 38140b57cec5SDimitry Andric if (IvarTy->isIncompleteArrayType() && 38150b57cec5SDimitry Andric (IvarTy.getObjCLifetime() != Qualifiers::OCL_ExplicitNone) && 38160b57cec5SDimitry Andric IvarTy->isObjCLifetimeType()) { 38170b57cec5SDimitry Andric S.Diag(ivar->getLocation(), diag::err_flexible_array_arc_retainable); 38180b57cec5SDimitry Andric ivar->setInvalidDecl(); 38190b57cec5SDimitry Andric } 38200b57cec5SDimitry Andric } 38210b57cec5SDimitry Andric } 38220b57cec5SDimitry Andric 3823*0fca6ea1SDimitry Andric SemaObjC::ObjCContainerKind SemaObjC::getObjCContainerKind() const { 3824*0fca6ea1SDimitry Andric switch (SemaRef.CurContext->getDeclKind()) { 38250b57cec5SDimitry Andric case Decl::ObjCInterface: 3826*0fca6ea1SDimitry Andric return SemaObjC::OCK_Interface; 38270b57cec5SDimitry Andric case Decl::ObjCProtocol: 3828*0fca6ea1SDimitry Andric return SemaObjC::OCK_Protocol; 38290b57cec5SDimitry Andric case Decl::ObjCCategory: 3830*0fca6ea1SDimitry Andric if (cast<ObjCCategoryDecl>(SemaRef.CurContext)->IsClassExtension()) 3831*0fca6ea1SDimitry Andric return SemaObjC::OCK_ClassExtension; 3832*0fca6ea1SDimitry Andric return SemaObjC::OCK_Category; 38330b57cec5SDimitry Andric case Decl::ObjCImplementation: 3834*0fca6ea1SDimitry Andric return SemaObjC::OCK_Implementation; 38350b57cec5SDimitry Andric case Decl::ObjCCategoryImpl: 3836*0fca6ea1SDimitry Andric return SemaObjC::OCK_CategoryImplementation; 38370b57cec5SDimitry Andric 38380b57cec5SDimitry Andric default: 3839*0fca6ea1SDimitry Andric return SemaObjC::OCK_None; 38400b57cec5SDimitry Andric } 38410b57cec5SDimitry Andric } 38420b57cec5SDimitry Andric 38430b57cec5SDimitry Andric static bool IsVariableSizedType(QualType T) { 38440b57cec5SDimitry Andric if (T->isIncompleteArrayType()) 38450b57cec5SDimitry Andric return true; 38460b57cec5SDimitry Andric const auto *RecordTy = T->getAs<RecordType>(); 38470b57cec5SDimitry Andric return (RecordTy && RecordTy->getDecl()->hasFlexibleArrayMember()); 38480b57cec5SDimitry Andric } 38490b57cec5SDimitry Andric 38500b57cec5SDimitry Andric static void DiagnoseVariableSizedIvars(Sema &S, ObjCContainerDecl *OCD) { 38510b57cec5SDimitry Andric ObjCInterfaceDecl *IntfDecl = nullptr; 38520b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_range Ivars = llvm::make_range( 38530b57cec5SDimitry Andric ObjCInterfaceDecl::ivar_iterator(), ObjCInterfaceDecl::ivar_iterator()); 38540b57cec5SDimitry Andric if ((IntfDecl = dyn_cast<ObjCInterfaceDecl>(OCD))) { 38550b57cec5SDimitry Andric Ivars = IntfDecl->ivars(); 38560b57cec5SDimitry Andric } else if (auto *ImplDecl = dyn_cast<ObjCImplementationDecl>(OCD)) { 38570b57cec5SDimitry Andric IntfDecl = ImplDecl->getClassInterface(); 38580b57cec5SDimitry Andric Ivars = ImplDecl->ivars(); 38590b57cec5SDimitry Andric } else if (auto *CategoryDecl = dyn_cast<ObjCCategoryDecl>(OCD)) { 38600b57cec5SDimitry Andric if (CategoryDecl->IsClassExtension()) { 38610b57cec5SDimitry Andric IntfDecl = CategoryDecl->getClassInterface(); 38620b57cec5SDimitry Andric Ivars = CategoryDecl->ivars(); 38630b57cec5SDimitry Andric } 38640b57cec5SDimitry Andric } 38650b57cec5SDimitry Andric 38660b57cec5SDimitry Andric // Check if variable sized ivar is in interface and visible to subclasses. 38670b57cec5SDimitry Andric if (!isa<ObjCInterfaceDecl>(OCD)) { 3868bdd1243dSDimitry Andric for (auto *ivar : Ivars) { 38690b57cec5SDimitry Andric if (!ivar->isInvalidDecl() && IsVariableSizedType(ivar->getType())) { 38700b57cec5SDimitry Andric S.Diag(ivar->getLocation(), diag::warn_variable_sized_ivar_visibility) 38710b57cec5SDimitry Andric << ivar->getDeclName() << ivar->getType(); 38720b57cec5SDimitry Andric } 38730b57cec5SDimitry Andric } 38740b57cec5SDimitry Andric } 38750b57cec5SDimitry Andric 38760b57cec5SDimitry Andric // Subsequent checks require interface decl. 38770b57cec5SDimitry Andric if (!IntfDecl) 38780b57cec5SDimitry Andric return; 38790b57cec5SDimitry Andric 38800b57cec5SDimitry Andric // Check if variable sized ivar is followed by another ivar. 38810b57cec5SDimitry Andric for (ObjCIvarDecl *ivar = IntfDecl->all_declared_ivar_begin(); ivar; 38820b57cec5SDimitry Andric ivar = ivar->getNextIvar()) { 38830b57cec5SDimitry Andric if (ivar->isInvalidDecl() || !ivar->getNextIvar()) 38840b57cec5SDimitry Andric continue; 38850b57cec5SDimitry Andric QualType IvarTy = ivar->getType(); 38860b57cec5SDimitry Andric bool IsInvalidIvar = false; 38870b57cec5SDimitry Andric if (IvarTy->isIncompleteArrayType()) { 38880b57cec5SDimitry Andric S.Diag(ivar->getLocation(), diag::err_flexible_array_not_at_end) 38890b57cec5SDimitry Andric << ivar->getDeclName() << IvarTy 38905f757f3fSDimitry Andric << llvm::to_underlying(TagTypeKind::Class); // Use "class" for Obj-C. 38910b57cec5SDimitry Andric IsInvalidIvar = true; 38920b57cec5SDimitry Andric } else if (const RecordType *RecordTy = IvarTy->getAs<RecordType>()) { 38930b57cec5SDimitry Andric if (RecordTy->getDecl()->hasFlexibleArrayMember()) { 38940b57cec5SDimitry Andric S.Diag(ivar->getLocation(), 38950b57cec5SDimitry Andric diag::err_objc_variable_sized_type_not_at_end) 38960b57cec5SDimitry Andric << ivar->getDeclName() << IvarTy; 38970b57cec5SDimitry Andric IsInvalidIvar = true; 38980b57cec5SDimitry Andric } 38990b57cec5SDimitry Andric } 39000b57cec5SDimitry Andric if (IsInvalidIvar) { 39010b57cec5SDimitry Andric S.Diag(ivar->getNextIvar()->getLocation(), 39020b57cec5SDimitry Andric diag::note_next_ivar_declaration) 39030b57cec5SDimitry Andric << ivar->getNextIvar()->getSynthesize(); 39040b57cec5SDimitry Andric ivar->setInvalidDecl(); 39050b57cec5SDimitry Andric } 39060b57cec5SDimitry Andric } 39070b57cec5SDimitry Andric 39080b57cec5SDimitry Andric // Check if ObjC container adds ivars after variable sized ivar in superclass. 39090b57cec5SDimitry Andric // Perform the check only if OCD is the first container to declare ivars to 39100b57cec5SDimitry Andric // avoid multiple warnings for the same ivar. 39110b57cec5SDimitry Andric ObjCIvarDecl *FirstIvar = 39120b57cec5SDimitry Andric (Ivars.begin() == Ivars.end()) ? nullptr : *Ivars.begin(); 39130b57cec5SDimitry Andric if (FirstIvar && (FirstIvar == IntfDecl->all_declared_ivar_begin())) { 39140b57cec5SDimitry Andric const ObjCInterfaceDecl *SuperClass = IntfDecl->getSuperClass(); 39150b57cec5SDimitry Andric while (SuperClass && SuperClass->ivar_empty()) 39160b57cec5SDimitry Andric SuperClass = SuperClass->getSuperClass(); 39170b57cec5SDimitry Andric if (SuperClass) { 39180b57cec5SDimitry Andric auto IvarIter = SuperClass->ivar_begin(); 39190b57cec5SDimitry Andric std::advance(IvarIter, SuperClass->ivar_size() - 1); 39200b57cec5SDimitry Andric const ObjCIvarDecl *LastIvar = *IvarIter; 39210b57cec5SDimitry Andric if (IsVariableSizedType(LastIvar->getType())) { 39220b57cec5SDimitry Andric S.Diag(FirstIvar->getLocation(), 39230b57cec5SDimitry Andric diag::warn_superclass_variable_sized_type_not_at_end) 39240b57cec5SDimitry Andric << FirstIvar->getDeclName() << LastIvar->getDeclName() 39250b57cec5SDimitry Andric << LastIvar->getType() << SuperClass->getDeclName(); 39260b57cec5SDimitry Andric S.Diag(LastIvar->getLocation(), diag::note_entity_declared_at) 39270b57cec5SDimitry Andric << LastIvar->getDeclName(); 39280b57cec5SDimitry Andric } 39290b57cec5SDimitry Andric } 39300b57cec5SDimitry Andric } 39310b57cec5SDimitry Andric } 39320b57cec5SDimitry Andric 3933e8d8bef9SDimitry Andric static void DiagnoseCategoryDirectMembersProtocolConformance( 3934e8d8bef9SDimitry Andric Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl); 3935e8d8bef9SDimitry Andric 3936e8d8bef9SDimitry Andric static void DiagnoseCategoryDirectMembersProtocolConformance( 3937e8d8bef9SDimitry Andric Sema &S, ObjCCategoryDecl *CDecl, 3938e8d8bef9SDimitry Andric const llvm::iterator_range<ObjCProtocolList::iterator> &Protocols) { 3939e8d8bef9SDimitry Andric for (auto *PI : Protocols) 3940e8d8bef9SDimitry Andric DiagnoseCategoryDirectMembersProtocolConformance(S, PI, CDecl); 3941e8d8bef9SDimitry Andric } 3942e8d8bef9SDimitry Andric 3943e8d8bef9SDimitry Andric static void DiagnoseCategoryDirectMembersProtocolConformance( 3944e8d8bef9SDimitry Andric Sema &S, ObjCProtocolDecl *PDecl, ObjCCategoryDecl *CDecl) { 3945e8d8bef9SDimitry Andric if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition()) 3946e8d8bef9SDimitry Andric PDecl = PDecl->getDefinition(); 3947e8d8bef9SDimitry Andric 3948e8d8bef9SDimitry Andric llvm::SmallVector<const Decl *, 4> DirectMembers; 3949e8d8bef9SDimitry Andric const auto *IDecl = CDecl->getClassInterface(); 3950e8d8bef9SDimitry Andric for (auto *MD : PDecl->methods()) { 3951e8d8bef9SDimitry Andric if (!MD->isPropertyAccessor()) { 3952e8d8bef9SDimitry Andric if (const auto *CMD = 3953e8d8bef9SDimitry Andric IDecl->getMethod(MD->getSelector(), MD->isInstanceMethod())) { 3954e8d8bef9SDimitry Andric if (CMD->isDirectMethod()) 3955e8d8bef9SDimitry Andric DirectMembers.push_back(CMD); 3956e8d8bef9SDimitry Andric } 3957e8d8bef9SDimitry Andric } 3958e8d8bef9SDimitry Andric } 3959e8d8bef9SDimitry Andric for (auto *PD : PDecl->properties()) { 3960e8d8bef9SDimitry Andric if (const auto *CPD = IDecl->FindPropertyVisibleInPrimaryClass( 3961e8d8bef9SDimitry Andric PD->getIdentifier(), 3962e8d8bef9SDimitry Andric PD->isClassProperty() 3963e8d8bef9SDimitry Andric ? ObjCPropertyQueryKind::OBJC_PR_query_class 3964e8d8bef9SDimitry Andric : ObjCPropertyQueryKind::OBJC_PR_query_instance)) { 3965e8d8bef9SDimitry Andric if (CPD->isDirectProperty()) 3966e8d8bef9SDimitry Andric DirectMembers.push_back(CPD); 3967e8d8bef9SDimitry Andric } 3968e8d8bef9SDimitry Andric } 3969e8d8bef9SDimitry Andric if (!DirectMembers.empty()) { 3970e8d8bef9SDimitry Andric S.Diag(CDecl->getLocation(), diag::err_objc_direct_protocol_conformance) 3971e8d8bef9SDimitry Andric << CDecl->IsClassExtension() << CDecl << PDecl << IDecl; 3972e8d8bef9SDimitry Andric for (const auto *MD : DirectMembers) 3973e8d8bef9SDimitry Andric S.Diag(MD->getLocation(), diag::note_direct_member_here); 3974e8d8bef9SDimitry Andric return; 3975e8d8bef9SDimitry Andric } 3976e8d8bef9SDimitry Andric 3977e8d8bef9SDimitry Andric // Check on this protocols's referenced protocols, recursively. 3978e8d8bef9SDimitry Andric DiagnoseCategoryDirectMembersProtocolConformance(S, CDecl, 3979e8d8bef9SDimitry Andric PDecl->protocols()); 3980e8d8bef9SDimitry Andric } 3981e8d8bef9SDimitry Andric 39820b57cec5SDimitry Andric // Note: For class/category implementations, allMethods is always null. 3983*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnAtEnd(Scope *S, SourceRange AtEnd, 3984*0fca6ea1SDimitry Andric ArrayRef<Decl *> allMethods, 39850b57cec5SDimitry Andric ArrayRef<DeclGroupPtrTy> allTUVars) { 3986*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 3987*0fca6ea1SDimitry Andric if (getObjCContainerKind() == SemaObjC::OCK_None) 39880b57cec5SDimitry Andric return nullptr; 39890b57cec5SDimitry Andric 39900b57cec5SDimitry Andric assert(AtEnd.isValid() && "Invalid location for '@end'"); 39910b57cec5SDimitry Andric 3992*0fca6ea1SDimitry Andric auto *OCD = cast<ObjCContainerDecl>(SemaRef.CurContext); 39930b57cec5SDimitry Andric Decl *ClassDecl = OCD; 39940b57cec5SDimitry Andric 39950b57cec5SDimitry Andric bool isInterfaceDeclKind = 39960b57cec5SDimitry Andric isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) 39970b57cec5SDimitry Andric || isa<ObjCProtocolDecl>(ClassDecl); 39980b57cec5SDimitry Andric bool checkIdenticalMethods = isa<ObjCImplementationDecl>(ClassDecl); 39990b57cec5SDimitry Andric 4000480093f4SDimitry Andric // Make synthesized accessor stub functions visible. 4001480093f4SDimitry Andric // ActOnPropertyImplDecl() creates them as not visible in case 4002480093f4SDimitry Andric // they are overridden by an explicit method that is encountered 4003480093f4SDimitry Andric // later. 4004*0fca6ea1SDimitry Andric if (auto *OID = dyn_cast<ObjCImplementationDecl>(SemaRef.CurContext)) { 4005bdd1243dSDimitry Andric for (auto *PropImpl : OID->property_impls()) { 4006480093f4SDimitry Andric if (auto *Getter = PropImpl->getGetterMethodDecl()) 4007e8d8bef9SDimitry Andric if (Getter->isSynthesizedAccessorStub()) 4008480093f4SDimitry Andric OID->addDecl(Getter); 4009480093f4SDimitry Andric if (auto *Setter = PropImpl->getSetterMethodDecl()) 4010e8d8bef9SDimitry Andric if (Setter->isSynthesizedAccessorStub()) 4011480093f4SDimitry Andric OID->addDecl(Setter); 4012480093f4SDimitry Andric } 4013480093f4SDimitry Andric } 4014480093f4SDimitry Andric 40150b57cec5SDimitry Andric // FIXME: Remove these and use the ObjCContainerDecl/DeclContext. 40160b57cec5SDimitry Andric llvm::DenseMap<Selector, const ObjCMethodDecl*> InsMap; 40170b57cec5SDimitry Andric llvm::DenseMap<Selector, const ObjCMethodDecl*> ClsMap; 40180b57cec5SDimitry Andric 40190b57cec5SDimitry Andric for (unsigned i = 0, e = allMethods.size(); i != e; i++ ) { 40200b57cec5SDimitry Andric ObjCMethodDecl *Method = 40210b57cec5SDimitry Andric cast_or_null<ObjCMethodDecl>(allMethods[i]); 40220b57cec5SDimitry Andric 40230b57cec5SDimitry Andric if (!Method) continue; // Already issued a diagnostic. 40240b57cec5SDimitry Andric if (Method->isInstanceMethod()) { 40250b57cec5SDimitry Andric /// Check for instance method of the same name with incompatible types 40260b57cec5SDimitry Andric const ObjCMethodDecl *&PrevMethod = InsMap[Method->getSelector()]; 40270b57cec5SDimitry Andric bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 40280b57cec5SDimitry Andric : false; 40290b57cec5SDimitry Andric if ((isInterfaceDeclKind && PrevMethod && !match) 40300b57cec5SDimitry Andric || (checkIdenticalMethods && match)) { 40310b57cec5SDimitry Andric Diag(Method->getLocation(), diag::err_duplicate_method_decl) 40320b57cec5SDimitry Andric << Method->getDeclName(); 40330b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 40340b57cec5SDimitry Andric Method->setInvalidDecl(); 40350b57cec5SDimitry Andric } else { 40360b57cec5SDimitry Andric if (PrevMethod) { 40370b57cec5SDimitry Andric Method->setAsRedeclaration(PrevMethod); 40380b57cec5SDimitry Andric if (!Context.getSourceManager().isInSystemHeader( 40390b57cec5SDimitry Andric Method->getLocation())) 40400b57cec5SDimitry Andric Diag(Method->getLocation(), diag::warn_duplicate_method_decl) 40410b57cec5SDimitry Andric << Method->getDeclName(); 40420b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 40430b57cec5SDimitry Andric } 40440b57cec5SDimitry Andric InsMap[Method->getSelector()] = Method; 40450b57cec5SDimitry Andric /// The following allows us to typecheck messages to "id". 40460b57cec5SDimitry Andric AddInstanceMethodToGlobalPool(Method); 40470b57cec5SDimitry Andric } 40480b57cec5SDimitry Andric } else { 40490b57cec5SDimitry Andric /// Check for class method of the same name with incompatible types 40500b57cec5SDimitry Andric const ObjCMethodDecl *&PrevMethod = ClsMap[Method->getSelector()]; 40510b57cec5SDimitry Andric bool match = PrevMethod ? MatchTwoMethodDeclarations(Method, PrevMethod) 40520b57cec5SDimitry Andric : false; 40530b57cec5SDimitry Andric if ((isInterfaceDeclKind && PrevMethod && !match) 40540b57cec5SDimitry Andric || (checkIdenticalMethods && match)) { 40550b57cec5SDimitry Andric Diag(Method->getLocation(), diag::err_duplicate_method_decl) 40560b57cec5SDimitry Andric << Method->getDeclName(); 40570b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 40580b57cec5SDimitry Andric Method->setInvalidDecl(); 40590b57cec5SDimitry Andric } else { 40600b57cec5SDimitry Andric if (PrevMethod) { 40610b57cec5SDimitry Andric Method->setAsRedeclaration(PrevMethod); 40620b57cec5SDimitry Andric if (!Context.getSourceManager().isInSystemHeader( 40630b57cec5SDimitry Andric Method->getLocation())) 40640b57cec5SDimitry Andric Diag(Method->getLocation(), diag::warn_duplicate_method_decl) 40650b57cec5SDimitry Andric << Method->getDeclName(); 40660b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 40670b57cec5SDimitry Andric } 40680b57cec5SDimitry Andric ClsMap[Method->getSelector()] = Method; 40690b57cec5SDimitry Andric AddFactoryMethodToGlobalPool(Method); 40700b57cec5SDimitry Andric } 40710b57cec5SDimitry Andric } 40720b57cec5SDimitry Andric } 40730b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(ClassDecl)) { 40740b57cec5SDimitry Andric // Nothing to do here. 40750b57cec5SDimitry Andric } else if (ObjCCategoryDecl *C = dyn_cast<ObjCCategoryDecl>(ClassDecl)) { 40760b57cec5SDimitry Andric // Categories are used to extend the class by declaring new methods. 40770b57cec5SDimitry Andric // By the same token, they are also used to add new properties. No 40780b57cec5SDimitry Andric // need to compare the added property to those in the class. 40790b57cec5SDimitry Andric 40800b57cec5SDimitry Andric if (C->IsClassExtension()) { 40810b57cec5SDimitry Andric ObjCInterfaceDecl *CCPrimary = C->getClassInterface(); 40820b57cec5SDimitry Andric DiagnoseClassExtensionDupMethods(C, CCPrimary); 40830b57cec5SDimitry Andric } 4084e8d8bef9SDimitry Andric 4085*0fca6ea1SDimitry Andric DiagnoseCategoryDirectMembersProtocolConformance(SemaRef, C, 4086*0fca6ea1SDimitry Andric C->protocols()); 40870b57cec5SDimitry Andric } 40880b57cec5SDimitry Andric if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(ClassDecl)) { 40890b57cec5SDimitry Andric if (CDecl->getIdentifier()) 40900b57cec5SDimitry Andric // ProcessPropertyDecl is responsible for diagnosing conflicts with any 40910b57cec5SDimitry Andric // user-defined setter/getter. It also synthesizes setter/getter methods 40920b57cec5SDimitry Andric // and adds them to the DeclContext and global method pools. 40930b57cec5SDimitry Andric for (auto *I : CDecl->properties()) 40940b57cec5SDimitry Andric ProcessPropertyDecl(I); 40950b57cec5SDimitry Andric CDecl->setAtEndRange(AtEnd); 40960b57cec5SDimitry Andric } 40970b57cec5SDimitry Andric if (ObjCImplementationDecl *IC=dyn_cast<ObjCImplementationDecl>(ClassDecl)) { 40980b57cec5SDimitry Andric IC->setAtEndRange(AtEnd); 40990b57cec5SDimitry Andric if (ObjCInterfaceDecl* IDecl = IC->getClassInterface()) { 41000b57cec5SDimitry Andric // Any property declared in a class extension might have user 41010b57cec5SDimitry Andric // declared setter or getter in current class extension or one 41020b57cec5SDimitry Andric // of the other class extensions. Mark them as synthesized as 41030b57cec5SDimitry Andric // property will be synthesized when property with same name is 41040b57cec5SDimitry Andric // seen in the @implementation. 41050b57cec5SDimitry Andric for (const auto *Ext : IDecl->visible_extensions()) { 41060b57cec5SDimitry Andric for (const auto *Property : Ext->instance_properties()) { 41070b57cec5SDimitry Andric // Skip over properties declared @dynamic 41080b57cec5SDimitry Andric if (const ObjCPropertyImplDecl *PIDecl 41090b57cec5SDimitry Andric = IC->FindPropertyImplDecl(Property->getIdentifier(), 41100b57cec5SDimitry Andric Property->getQueryKind())) 41110b57cec5SDimitry Andric if (PIDecl->getPropertyImplementation() 41120b57cec5SDimitry Andric == ObjCPropertyImplDecl::Dynamic) 41130b57cec5SDimitry Andric continue; 41140b57cec5SDimitry Andric 41150b57cec5SDimitry Andric for (const auto *Ext : IDecl->visible_extensions()) { 4116480093f4SDimitry Andric if (ObjCMethodDecl *GetterMethod = 4117480093f4SDimitry Andric Ext->getInstanceMethod(Property->getGetterName())) 41180b57cec5SDimitry Andric GetterMethod->setPropertyAccessor(true); 41190b57cec5SDimitry Andric if (!Property->isReadOnly()) 41200b57cec5SDimitry Andric if (ObjCMethodDecl *SetterMethod 41210b57cec5SDimitry Andric = Ext->getInstanceMethod(Property->getSetterName())) 41220b57cec5SDimitry Andric SetterMethod->setPropertyAccessor(true); 41230b57cec5SDimitry Andric } 41240b57cec5SDimitry Andric } 41250b57cec5SDimitry Andric } 41260b57cec5SDimitry Andric ImplMethodsVsClassMethods(S, IC, IDecl); 41270b57cec5SDimitry Andric AtomicPropertySetterGetterRules(IC, IDecl); 41280b57cec5SDimitry Andric DiagnoseOwningPropertyGetterSynthesis(IC); 41290b57cec5SDimitry Andric DiagnoseUnusedBackingIvarInAccessor(S, IC); 41300b57cec5SDimitry Andric if (IDecl->hasDesignatedInitializers()) 41310b57cec5SDimitry Andric DiagnoseMissingDesignatedInitOverrides(IC, IDecl); 4132*0fca6ea1SDimitry Andric DiagnoseWeakIvars(SemaRef, IC); 4133*0fca6ea1SDimitry Andric DiagnoseRetainableFlexibleArrayMember(SemaRef, IDecl); 41340b57cec5SDimitry Andric 41350b57cec5SDimitry Andric bool HasRootClassAttr = IDecl->hasAttr<ObjCRootClassAttr>(); 41360b57cec5SDimitry Andric if (IDecl->getSuperClass() == nullptr) { 41370b57cec5SDimitry Andric // This class has no superclass, so check that it has been marked with 41380b57cec5SDimitry Andric // __attribute((objc_root_class)). 41390b57cec5SDimitry Andric if (!HasRootClassAttr) { 41400b57cec5SDimitry Andric SourceLocation DeclLoc(IDecl->getLocation()); 4141*0fca6ea1SDimitry Andric SourceLocation SuperClassLoc(SemaRef.getLocForEndOfToken(DeclLoc)); 41420b57cec5SDimitry Andric Diag(DeclLoc, diag::warn_objc_root_class_missing) 41430b57cec5SDimitry Andric << IDecl->getIdentifier(); 41440b57cec5SDimitry Andric // See if NSObject is in the current scope, and if it is, suggest 41450b57cec5SDimitry Andric // adding " : NSObject " to the class declaration. 4146*0fca6ea1SDimitry Andric NamedDecl *IF = SemaRef.LookupSingleName( 4147*0fca6ea1SDimitry Andric SemaRef.TUScope, NSAPIObj->getNSClassId(NSAPI::ClassId_NSObject), 4148*0fca6ea1SDimitry Andric DeclLoc, Sema::LookupOrdinaryName); 41490b57cec5SDimitry Andric ObjCInterfaceDecl *NSObjectDecl = dyn_cast_or_null<ObjCInterfaceDecl>(IF); 41500b57cec5SDimitry Andric if (NSObjectDecl && NSObjectDecl->getDefinition()) { 41510b57cec5SDimitry Andric Diag(SuperClassLoc, diag::note_objc_needs_superclass) 41520b57cec5SDimitry Andric << FixItHint::CreateInsertion(SuperClassLoc, " : NSObject "); 41530b57cec5SDimitry Andric } else { 41540b57cec5SDimitry Andric Diag(SuperClassLoc, diag::note_objc_needs_superclass); 41550b57cec5SDimitry Andric } 41560b57cec5SDimitry Andric } 41570b57cec5SDimitry Andric } else if (HasRootClassAttr) { 41580b57cec5SDimitry Andric // Complain that only root classes may have this attribute. 41590b57cec5SDimitry Andric Diag(IDecl->getLocation(), diag::err_objc_root_class_subclass); 41600b57cec5SDimitry Andric } 41610b57cec5SDimitry Andric 41620b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = IDecl->getSuperClass()) { 41630b57cec5SDimitry Andric // An interface can subclass another interface with a 41640b57cec5SDimitry Andric // objc_subclassing_restricted attribute when it has that attribute as 41650b57cec5SDimitry Andric // well (because of interfaces imported from Swift). Therefore we have 41660b57cec5SDimitry Andric // to check if we can subclass in the implementation as well. 41670b57cec5SDimitry Andric if (IDecl->hasAttr<ObjCSubclassingRestrictedAttr>() && 41680b57cec5SDimitry Andric Super->hasAttr<ObjCSubclassingRestrictedAttr>()) { 41690b57cec5SDimitry Andric Diag(IC->getLocation(), diag::err_restricted_superclass_mismatch); 41700b57cec5SDimitry Andric Diag(Super->getLocation(), diag::note_class_declared); 41710b57cec5SDimitry Andric } 41720b57cec5SDimitry Andric } 41730b57cec5SDimitry Andric 41740b57cec5SDimitry Andric if (IDecl->hasAttr<ObjCClassStubAttr>()) 41750b57cec5SDimitry Andric Diag(IC->getLocation(), diag::err_implementation_of_class_stub); 41760b57cec5SDimitry Andric 4177*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isNonFragile()) { 41780b57cec5SDimitry Andric while (IDecl->getSuperClass()) { 41790b57cec5SDimitry Andric DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); 41800b57cec5SDimitry Andric IDecl = IDecl->getSuperClass(); 41810b57cec5SDimitry Andric } 41820b57cec5SDimitry Andric } 41830b57cec5SDimitry Andric } 41840b57cec5SDimitry Andric SetIvarInitializers(IC); 41850b57cec5SDimitry Andric } else if (ObjCCategoryImplDecl* CatImplClass = 41860b57cec5SDimitry Andric dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { 41870b57cec5SDimitry Andric CatImplClass->setAtEndRange(AtEnd); 41880b57cec5SDimitry Andric 41890b57cec5SDimitry Andric // Find category interface decl and then check that all methods declared 41900b57cec5SDimitry Andric // in this interface are implemented in the category @implementation. 41910b57cec5SDimitry Andric if (ObjCInterfaceDecl* IDecl = CatImplClass->getClassInterface()) { 41920b57cec5SDimitry Andric if (ObjCCategoryDecl *Cat 41930b57cec5SDimitry Andric = IDecl->FindCategoryDeclaration(CatImplClass->getIdentifier())) { 41940b57cec5SDimitry Andric ImplMethodsVsClassMethods(S, CatImplClass, Cat); 41950b57cec5SDimitry Andric } 41960b57cec5SDimitry Andric } 41970b57cec5SDimitry Andric } else if (const auto *IntfDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) { 41980b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Super = IntfDecl->getSuperClass()) { 41990b57cec5SDimitry Andric if (!IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>() && 42000b57cec5SDimitry Andric Super->hasAttr<ObjCSubclassingRestrictedAttr>()) { 42010b57cec5SDimitry Andric Diag(IntfDecl->getLocation(), diag::err_restricted_superclass_mismatch); 42020b57cec5SDimitry Andric Diag(Super->getLocation(), diag::note_class_declared); 42030b57cec5SDimitry Andric } 42040b57cec5SDimitry Andric } 42050b57cec5SDimitry Andric 42060b57cec5SDimitry Andric if (IntfDecl->hasAttr<ObjCClassStubAttr>() && 42070b57cec5SDimitry Andric !IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>()) 42080b57cec5SDimitry Andric Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch); 42090b57cec5SDimitry Andric } 4210*0fca6ea1SDimitry Andric DiagnoseVariableSizedIvars(SemaRef, OCD); 42110b57cec5SDimitry Andric if (isInterfaceDeclKind) { 42120b57cec5SDimitry Andric // Reject invalid vardecls. 42130b57cec5SDimitry Andric for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { 42140b57cec5SDimitry Andric DeclGroupRef DG = allTUVars[i].get(); 42150b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 42160b57cec5SDimitry Andric if (VarDecl *VDecl = dyn_cast<VarDecl>(*I)) { 42170b57cec5SDimitry Andric if (!VDecl->hasExternalStorage()) 42180b57cec5SDimitry Andric Diag(VDecl->getLocation(), diag::err_objc_var_decl_inclass); 42190b57cec5SDimitry Andric } 42200b57cec5SDimitry Andric } 42210b57cec5SDimitry Andric } 42220b57cec5SDimitry Andric ActOnObjCContainerFinishDefinition(); 42230b57cec5SDimitry Andric 42240b57cec5SDimitry Andric for (unsigned i = 0, e = allTUVars.size(); i != e; i++) { 42250b57cec5SDimitry Andric DeclGroupRef DG = allTUVars[i].get(); 42260b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 42270b57cec5SDimitry Andric (*I)->setTopLevelDeclInObjCContainer(); 4228*0fca6ea1SDimitry Andric SemaRef.Consumer.HandleTopLevelDeclInObjCContainer(DG); 42290b57cec5SDimitry Andric } 42300b57cec5SDimitry Andric 4231*0fca6ea1SDimitry Andric SemaRef.ActOnDocumentableDecl(ClassDecl); 42320b57cec5SDimitry Andric return ClassDecl; 42330b57cec5SDimitry Andric } 42340b57cec5SDimitry Andric 42350b57cec5SDimitry Andric /// CvtQTToAstBitMask - utility routine to produce an AST bitmask for 42360b57cec5SDimitry Andric /// objective-c's type qualifier from the parser version of the same info. 42370b57cec5SDimitry Andric static Decl::ObjCDeclQualifier 42380b57cec5SDimitry Andric CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { 42390b57cec5SDimitry Andric return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; 42400b57cec5SDimitry Andric } 42410b57cec5SDimitry Andric 42420b57cec5SDimitry Andric /// Check whether the declared result type of the given Objective-C 42430b57cec5SDimitry Andric /// method declaration is compatible with the method's class. 42440b57cec5SDimitry Andric /// 4245*0fca6ea1SDimitry Andric static SemaObjC::ResultTypeCompatibilityKind 42460b57cec5SDimitry Andric CheckRelatedResultTypeCompatibility(Sema &S, ObjCMethodDecl *Method, 42470b57cec5SDimitry Andric ObjCInterfaceDecl *CurrentClass) { 42480b57cec5SDimitry Andric QualType ResultType = Method->getReturnType(); 42490b57cec5SDimitry Andric 42500b57cec5SDimitry Andric // If an Objective-C method inherits its related result type, then its 42510b57cec5SDimitry Andric // declared result type must be compatible with its own class type. The 42520b57cec5SDimitry Andric // declared result type is compatible if: 42530b57cec5SDimitry Andric if (const ObjCObjectPointerType *ResultObjectType 42540b57cec5SDimitry Andric = ResultType->getAs<ObjCObjectPointerType>()) { 42550b57cec5SDimitry Andric // - it is id or qualified id, or 42560b57cec5SDimitry Andric if (ResultObjectType->isObjCIdType() || 42570b57cec5SDimitry Andric ResultObjectType->isObjCQualifiedIdType()) 4258*0fca6ea1SDimitry Andric return SemaObjC::RTC_Compatible; 42590b57cec5SDimitry Andric 42600b57cec5SDimitry Andric if (CurrentClass) { 42610b57cec5SDimitry Andric if (ObjCInterfaceDecl *ResultClass 42620b57cec5SDimitry Andric = ResultObjectType->getInterfaceDecl()) { 42630b57cec5SDimitry Andric // - it is the same as the method's class type, or 42640b57cec5SDimitry Andric if (declaresSameEntity(CurrentClass, ResultClass)) 4265*0fca6ea1SDimitry Andric return SemaObjC::RTC_Compatible; 42660b57cec5SDimitry Andric 42670b57cec5SDimitry Andric // - it is a superclass of the method's class type 42680b57cec5SDimitry Andric if (ResultClass->isSuperClassOf(CurrentClass)) 4269*0fca6ea1SDimitry Andric return SemaObjC::RTC_Compatible; 42700b57cec5SDimitry Andric } 42710b57cec5SDimitry Andric } else { 42720b57cec5SDimitry Andric // Any Objective-C pointer type might be acceptable for a protocol 42730b57cec5SDimitry Andric // method; we just don't know. 4274*0fca6ea1SDimitry Andric return SemaObjC::RTC_Unknown; 42750b57cec5SDimitry Andric } 42760b57cec5SDimitry Andric } 42770b57cec5SDimitry Andric 4278*0fca6ea1SDimitry Andric return SemaObjC::RTC_Incompatible; 42790b57cec5SDimitry Andric } 42800b57cec5SDimitry Andric 42810b57cec5SDimitry Andric namespace { 42820b57cec5SDimitry Andric /// A helper class for searching for methods which a particular method 42830b57cec5SDimitry Andric /// overrides. 42840b57cec5SDimitry Andric class OverrideSearch { 42850b57cec5SDimitry Andric public: 42860b57cec5SDimitry Andric const ObjCMethodDecl *Method; 42870b57cec5SDimitry Andric llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden; 42880b57cec5SDimitry Andric bool Recursive; 42890b57cec5SDimitry Andric 42900b57cec5SDimitry Andric public: 42910b57cec5SDimitry Andric OverrideSearch(Sema &S, const ObjCMethodDecl *method) : Method(method) { 42920b57cec5SDimitry Andric Selector selector = method->getSelector(); 42930b57cec5SDimitry Andric 42940b57cec5SDimitry Andric // Bypass this search if we've never seen an instance/class method 42950b57cec5SDimitry Andric // with this selector before. 4296*0fca6ea1SDimitry Andric SemaObjC::GlobalMethodPool::iterator it = 4297*0fca6ea1SDimitry Andric S.ObjC().MethodPool.find(selector); 4298*0fca6ea1SDimitry Andric if (it == S.ObjC().MethodPool.end()) { 42990b57cec5SDimitry Andric if (!S.getExternalSource()) return; 4300*0fca6ea1SDimitry Andric S.ObjC().ReadMethodPool(selector); 43010b57cec5SDimitry Andric 4302*0fca6ea1SDimitry Andric it = S.ObjC().MethodPool.find(selector); 4303*0fca6ea1SDimitry Andric if (it == S.ObjC().MethodPool.end()) 43040b57cec5SDimitry Andric return; 43050b57cec5SDimitry Andric } 43060b57cec5SDimitry Andric const ObjCMethodList &list = 43070b57cec5SDimitry Andric method->isInstanceMethod() ? it->second.first : it->second.second; 43080b57cec5SDimitry Andric if (!list.getMethod()) return; 43090b57cec5SDimitry Andric 43100b57cec5SDimitry Andric const ObjCContainerDecl *container 43110b57cec5SDimitry Andric = cast<ObjCContainerDecl>(method->getDeclContext()); 43120b57cec5SDimitry Andric 43130b57cec5SDimitry Andric // Prevent the search from reaching this container again. This is 43140b57cec5SDimitry Andric // important with categories, which override methods from the 43150b57cec5SDimitry Andric // interface and each other. 43160b57cec5SDimitry Andric if (const ObjCCategoryDecl *Category = 43170b57cec5SDimitry Andric dyn_cast<ObjCCategoryDecl>(container)) { 43180b57cec5SDimitry Andric searchFromContainer(container); 43190b57cec5SDimitry Andric if (const ObjCInterfaceDecl *Interface = Category->getClassInterface()) 43200b57cec5SDimitry Andric searchFromContainer(Interface); 43210b57cec5SDimitry Andric } else { 43220b57cec5SDimitry Andric searchFromContainer(container); 43230b57cec5SDimitry Andric } 43240b57cec5SDimitry Andric } 43250b57cec5SDimitry Andric 43260b57cec5SDimitry Andric typedef decltype(Overridden)::iterator iterator; 43270b57cec5SDimitry Andric iterator begin() const { return Overridden.begin(); } 43280b57cec5SDimitry Andric iterator end() const { return Overridden.end(); } 43290b57cec5SDimitry Andric 43300b57cec5SDimitry Andric private: 43310b57cec5SDimitry Andric void searchFromContainer(const ObjCContainerDecl *container) { 43320b57cec5SDimitry Andric if (container->isInvalidDecl()) return; 43330b57cec5SDimitry Andric 43340b57cec5SDimitry Andric switch (container->getDeclKind()) { 43350b57cec5SDimitry Andric #define OBJCCONTAINER(type, base) \ 43360b57cec5SDimitry Andric case Decl::type: \ 43370b57cec5SDimitry Andric searchFrom(cast<type##Decl>(container)); \ 43380b57cec5SDimitry Andric break; 43390b57cec5SDimitry Andric #define ABSTRACT_DECL(expansion) 43400b57cec5SDimitry Andric #define DECL(type, base) \ 43410b57cec5SDimitry Andric case Decl::type: 43420b57cec5SDimitry Andric #include "clang/AST/DeclNodes.inc" 43430b57cec5SDimitry Andric llvm_unreachable("not an ObjC container!"); 43440b57cec5SDimitry Andric } 43450b57cec5SDimitry Andric } 43460b57cec5SDimitry Andric 43470b57cec5SDimitry Andric void searchFrom(const ObjCProtocolDecl *protocol) { 43480b57cec5SDimitry Andric if (!protocol->hasDefinition()) 43490b57cec5SDimitry Andric return; 43500b57cec5SDimitry Andric 43510b57cec5SDimitry Andric // A method in a protocol declaration overrides declarations from 43520b57cec5SDimitry Andric // referenced ("parent") protocols. 43530b57cec5SDimitry Andric search(protocol->getReferencedProtocols()); 43540b57cec5SDimitry Andric } 43550b57cec5SDimitry Andric 43560b57cec5SDimitry Andric void searchFrom(const ObjCCategoryDecl *category) { 43570b57cec5SDimitry Andric // A method in a category declaration overrides declarations from 43580b57cec5SDimitry Andric // the main class and from protocols the category references. 43590b57cec5SDimitry Andric // The main class is handled in the constructor. 43600b57cec5SDimitry Andric search(category->getReferencedProtocols()); 43610b57cec5SDimitry Andric } 43620b57cec5SDimitry Andric 43630b57cec5SDimitry Andric void searchFrom(const ObjCCategoryImplDecl *impl) { 43640b57cec5SDimitry Andric // A method in a category definition that has a category 43650b57cec5SDimitry Andric // declaration overrides declarations from the category 43660b57cec5SDimitry Andric // declaration. 43670b57cec5SDimitry Andric if (ObjCCategoryDecl *category = impl->getCategoryDecl()) { 43680b57cec5SDimitry Andric search(category); 43690b57cec5SDimitry Andric if (ObjCInterfaceDecl *Interface = category->getClassInterface()) 43700b57cec5SDimitry Andric search(Interface); 43710b57cec5SDimitry Andric 43720b57cec5SDimitry Andric // Otherwise it overrides declarations from the class. 43730b57cec5SDimitry Andric } else if (const auto *Interface = impl->getClassInterface()) { 43740b57cec5SDimitry Andric search(Interface); 43750b57cec5SDimitry Andric } 43760b57cec5SDimitry Andric } 43770b57cec5SDimitry Andric 43780b57cec5SDimitry Andric void searchFrom(const ObjCInterfaceDecl *iface) { 43790b57cec5SDimitry Andric // A method in a class declaration overrides declarations from 43800b57cec5SDimitry Andric if (!iface->hasDefinition()) 43810b57cec5SDimitry Andric return; 43820b57cec5SDimitry Andric 43830b57cec5SDimitry Andric // - categories, 43840b57cec5SDimitry Andric for (auto *Cat : iface->known_categories()) 43850b57cec5SDimitry Andric search(Cat); 43860b57cec5SDimitry Andric 43870b57cec5SDimitry Andric // - the super class, and 43880b57cec5SDimitry Andric if (ObjCInterfaceDecl *super = iface->getSuperClass()) 43890b57cec5SDimitry Andric search(super); 43900b57cec5SDimitry Andric 43910b57cec5SDimitry Andric // - any referenced protocols. 43920b57cec5SDimitry Andric search(iface->getReferencedProtocols()); 43930b57cec5SDimitry Andric } 43940b57cec5SDimitry Andric 43950b57cec5SDimitry Andric void searchFrom(const ObjCImplementationDecl *impl) { 43960b57cec5SDimitry Andric // A method in a class implementation overrides declarations from 43970b57cec5SDimitry Andric // the class interface. 43980b57cec5SDimitry Andric if (const auto *Interface = impl->getClassInterface()) 43990b57cec5SDimitry Andric search(Interface); 44000b57cec5SDimitry Andric } 44010b57cec5SDimitry Andric 44020b57cec5SDimitry Andric void search(const ObjCProtocolList &protocols) { 44030b57cec5SDimitry Andric for (const auto *Proto : protocols) 44040b57cec5SDimitry Andric search(Proto); 44050b57cec5SDimitry Andric } 44060b57cec5SDimitry Andric 44070b57cec5SDimitry Andric void search(const ObjCContainerDecl *container) { 44080b57cec5SDimitry Andric // Check for a method in this container which matches this selector. 44090b57cec5SDimitry Andric ObjCMethodDecl *meth = container->getMethod(Method->getSelector(), 44100b57cec5SDimitry Andric Method->isInstanceMethod(), 44110b57cec5SDimitry Andric /*AllowHidden=*/true); 44120b57cec5SDimitry Andric 44130b57cec5SDimitry Andric // If we find one, record it and bail out. 44140b57cec5SDimitry Andric if (meth) { 44150b57cec5SDimitry Andric Overridden.insert(meth); 44160b57cec5SDimitry Andric return; 44170b57cec5SDimitry Andric } 44180b57cec5SDimitry Andric 44190b57cec5SDimitry Andric // Otherwise, search for methods that a hypothetical method here 44200b57cec5SDimitry Andric // would have overridden. 44210b57cec5SDimitry Andric 44220b57cec5SDimitry Andric // Note that we're now in a recursive case. 44230b57cec5SDimitry Andric Recursive = true; 44240b57cec5SDimitry Andric 44250b57cec5SDimitry Andric searchFromContainer(container); 44260b57cec5SDimitry Andric } 44270b57cec5SDimitry Andric }; 44280b57cec5SDimitry Andric } // end anonymous namespace 44290b57cec5SDimitry Andric 4430*0fca6ea1SDimitry Andric void SemaObjC::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method, 4431480093f4SDimitry Andric ObjCMethodDecl *overridden) { 4432fe6060f1SDimitry Andric if (overridden->isDirectMethod()) { 4433fe6060f1SDimitry Andric const auto *attr = overridden->getAttr<ObjCDirectAttr>(); 4434480093f4SDimitry Andric Diag(method->getLocation(), diag::err_objc_override_direct_method); 4435480093f4SDimitry Andric Diag(attr->getLocation(), diag::note_previous_declaration); 4436fe6060f1SDimitry Andric } else if (method->isDirectMethod()) { 4437fe6060f1SDimitry Andric const auto *attr = method->getAttr<ObjCDirectAttr>(); 4438480093f4SDimitry Andric Diag(attr->getLocation(), diag::err_objc_direct_on_override) 4439480093f4SDimitry Andric << isa<ObjCProtocolDecl>(overridden->getDeclContext()); 4440480093f4SDimitry Andric Diag(overridden->getLocation(), diag::note_previous_declaration); 4441480093f4SDimitry Andric } 4442480093f4SDimitry Andric } 4443480093f4SDimitry Andric 4444*0fca6ea1SDimitry Andric void SemaObjC::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, 44450b57cec5SDimitry Andric ObjCInterfaceDecl *CurrentClass, 44460b57cec5SDimitry Andric ResultTypeCompatibilityKind RTC) { 4447*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 44480b57cec5SDimitry Andric if (!ObjCMethod) 44490b57cec5SDimitry Andric return; 4450bdd1243dSDimitry Andric auto IsMethodInCurrentClass = [CurrentClass](const ObjCMethodDecl *M) { 4451bdd1243dSDimitry Andric // Checking canonical decl works across modules. 4452bdd1243dSDimitry Andric return M->getClassInterface()->getCanonicalDecl() == 4453bdd1243dSDimitry Andric CurrentClass->getCanonicalDecl(); 4454bdd1243dSDimitry Andric }; 44550b57cec5SDimitry Andric // Search for overridden methods and merge information down from them. 4456*0fca6ea1SDimitry Andric OverrideSearch overrides(SemaRef, ObjCMethod); 44570b57cec5SDimitry Andric // Keep track if the method overrides any method in the class's base classes, 44580b57cec5SDimitry Andric // its protocols, or its categories' protocols; we will keep that info 44590b57cec5SDimitry Andric // in the ObjCMethodDecl. 44600b57cec5SDimitry Andric // For this info, a method in an implementation is not considered as 44610b57cec5SDimitry Andric // overriding the same method in the interface or its categories. 44620b57cec5SDimitry Andric bool hasOverriddenMethodsInBaseOrProtocol = false; 44630b57cec5SDimitry Andric for (ObjCMethodDecl *overridden : overrides) { 44640b57cec5SDimitry Andric if (!hasOverriddenMethodsInBaseOrProtocol) { 44650b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) || 4466bdd1243dSDimitry Andric !IsMethodInCurrentClass(overridden) || overridden->isOverriding()) { 4467480093f4SDimitry Andric CheckObjCMethodDirectOverrides(ObjCMethod, overridden); 44680b57cec5SDimitry Andric hasOverriddenMethodsInBaseOrProtocol = true; 44690b57cec5SDimitry Andric } else if (isa<ObjCImplDecl>(ObjCMethod->getDeclContext())) { 44700b57cec5SDimitry Andric // OverrideSearch will return as "overridden" the same method in the 44710b57cec5SDimitry Andric // interface. For hasOverriddenMethodsInBaseOrProtocol, we need to 44720b57cec5SDimitry Andric // check whether a category of a base class introduced a method with the 44730b57cec5SDimitry Andric // same selector, after the interface method declaration. 44740b57cec5SDimitry Andric // To avoid unnecessary lookups in the majority of cases, we use the 44750b57cec5SDimitry Andric // extra info bits in GlobalMethodPool to check whether there were any 44760b57cec5SDimitry Andric // category methods with this selector. 44770b57cec5SDimitry Andric GlobalMethodPool::iterator It = 44780b57cec5SDimitry Andric MethodPool.find(ObjCMethod->getSelector()); 44790b57cec5SDimitry Andric if (It != MethodPool.end()) { 44800b57cec5SDimitry Andric ObjCMethodList &List = 44810b57cec5SDimitry Andric ObjCMethod->isInstanceMethod()? It->second.first: It->second.second; 44820b57cec5SDimitry Andric unsigned CategCount = List.getBits(); 44830b57cec5SDimitry Andric if (CategCount > 0) { 44840b57cec5SDimitry Andric // If the method is in a category we'll do lookup if there were at 44850b57cec5SDimitry Andric // least 2 category methods recorded, otherwise only one will do. 44860b57cec5SDimitry Andric if (CategCount > 1 || 44870b57cec5SDimitry Andric !isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) { 4488*0fca6ea1SDimitry Andric OverrideSearch overrides(SemaRef, overridden); 44890b57cec5SDimitry Andric for (ObjCMethodDecl *SuperOverridden : overrides) { 44900b57cec5SDimitry Andric if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) || 4491bdd1243dSDimitry Andric !IsMethodInCurrentClass(SuperOverridden)) { 4492480093f4SDimitry Andric CheckObjCMethodDirectOverrides(ObjCMethod, SuperOverridden); 44930b57cec5SDimitry Andric hasOverriddenMethodsInBaseOrProtocol = true; 44940b57cec5SDimitry Andric overridden->setOverriding(true); 44950b57cec5SDimitry Andric break; 44960b57cec5SDimitry Andric } 44970b57cec5SDimitry Andric } 44980b57cec5SDimitry Andric } 44990b57cec5SDimitry Andric } 45000b57cec5SDimitry Andric } 45010b57cec5SDimitry Andric } 45020b57cec5SDimitry Andric } 45030b57cec5SDimitry Andric 45040b57cec5SDimitry Andric // Propagate down the 'related result type' bit from overridden methods. 4505*0fca6ea1SDimitry Andric if (RTC != SemaObjC::RTC_Incompatible && overridden->hasRelatedResultType()) 45060b57cec5SDimitry Andric ObjCMethod->setRelatedResultType(); 45070b57cec5SDimitry Andric 45080b57cec5SDimitry Andric // Then merge the declarations. 4509*0fca6ea1SDimitry Andric SemaRef.mergeObjCMethodDecls(ObjCMethod, overridden); 45100b57cec5SDimitry Andric 45110b57cec5SDimitry Andric if (ObjCMethod->isImplicit() && overridden->isImplicit()) 45120b57cec5SDimitry Andric continue; // Conflicting properties are detected elsewhere. 45130b57cec5SDimitry Andric 45140b57cec5SDimitry Andric // Check for overriding methods 45150b57cec5SDimitry Andric if (isa<ObjCInterfaceDecl>(ObjCMethod->getDeclContext()) || 45160b57cec5SDimitry Andric isa<ObjCImplementationDecl>(ObjCMethod->getDeclContext())) 45170b57cec5SDimitry Andric CheckConflictingOverridingMethod(ObjCMethod, overridden, 45180b57cec5SDimitry Andric isa<ObjCProtocolDecl>(overridden->getDeclContext())); 45190b57cec5SDimitry Andric 45200b57cec5SDimitry Andric if (CurrentClass && overridden->getDeclContext() != CurrentClass && 45210b57cec5SDimitry Andric isa<ObjCInterfaceDecl>(overridden->getDeclContext()) && 45220b57cec5SDimitry Andric !overridden->isImplicit() /* not meant for properties */) { 45230b57cec5SDimitry Andric ObjCMethodDecl::param_iterator ParamI = ObjCMethod->param_begin(), 45240b57cec5SDimitry Andric E = ObjCMethod->param_end(); 45250b57cec5SDimitry Andric ObjCMethodDecl::param_iterator PrevI = overridden->param_begin(), 45260b57cec5SDimitry Andric PrevE = overridden->param_end(); 45270b57cec5SDimitry Andric for (; ParamI != E && PrevI != PrevE; ++ParamI, ++PrevI) { 45280b57cec5SDimitry Andric assert(PrevI != overridden->param_end() && "Param mismatch"); 45290b57cec5SDimitry Andric QualType T1 = Context.getCanonicalType((*ParamI)->getType()); 45300b57cec5SDimitry Andric QualType T2 = Context.getCanonicalType((*PrevI)->getType()); 45310b57cec5SDimitry Andric // If type of argument of method in this class does not match its 45320b57cec5SDimitry Andric // respective argument type in the super class method, issue warning; 45330b57cec5SDimitry Andric if (!Context.typesAreCompatible(T1, T2)) { 45340b57cec5SDimitry Andric Diag((*ParamI)->getLocation(), diag::ext_typecheck_base_super) 45350b57cec5SDimitry Andric << T1 << T2; 45360b57cec5SDimitry Andric Diag(overridden->getLocation(), diag::note_previous_declaration); 45370b57cec5SDimitry Andric break; 45380b57cec5SDimitry Andric } 45390b57cec5SDimitry Andric } 45400b57cec5SDimitry Andric } 45410b57cec5SDimitry Andric } 45420b57cec5SDimitry Andric 45430b57cec5SDimitry Andric ObjCMethod->setOverriding(hasOverriddenMethodsInBaseOrProtocol); 45440b57cec5SDimitry Andric } 45450b57cec5SDimitry Andric 45460b57cec5SDimitry Andric /// Merge type nullability from for a redeclaration of the same entity, 45470b57cec5SDimitry Andric /// producing the updated type of the redeclared entity. 45480b57cec5SDimitry Andric static QualType mergeTypeNullabilityForRedecl(Sema &S, SourceLocation loc, 45490b57cec5SDimitry Andric QualType type, 45500b57cec5SDimitry Andric bool usesCSKeyword, 45510b57cec5SDimitry Andric SourceLocation prevLoc, 45520b57cec5SDimitry Andric QualType prevType, 45530b57cec5SDimitry Andric bool prevUsesCSKeyword) { 45540b57cec5SDimitry Andric // Determine the nullability of both types. 4555bdd1243dSDimitry Andric auto nullability = type->getNullability(); 4556bdd1243dSDimitry Andric auto prevNullability = prevType->getNullability(); 45570b57cec5SDimitry Andric 45580b57cec5SDimitry Andric // Easy case: both have nullability. 455981ad6265SDimitry Andric if (nullability.has_value() == prevNullability.has_value()) { 45600b57cec5SDimitry Andric // Neither has nullability; continue. 45610b57cec5SDimitry Andric if (!nullability) 45620b57cec5SDimitry Andric return type; 45630b57cec5SDimitry Andric 45640b57cec5SDimitry Andric // The nullabilities are equivalent; do nothing. 45650b57cec5SDimitry Andric if (*nullability == *prevNullability) 45660b57cec5SDimitry Andric return type; 45670b57cec5SDimitry Andric 45680b57cec5SDimitry Andric // Complain about mismatched nullability. 45690b57cec5SDimitry Andric S.Diag(loc, diag::err_nullability_conflicting) 45700b57cec5SDimitry Andric << DiagNullabilityKind(*nullability, usesCSKeyword) 45710b57cec5SDimitry Andric << DiagNullabilityKind(*prevNullability, prevUsesCSKeyword); 45720b57cec5SDimitry Andric return type; 45730b57cec5SDimitry Andric } 45740b57cec5SDimitry Andric 45750b57cec5SDimitry Andric // If it's the redeclaration that has nullability, don't change anything. 45760b57cec5SDimitry Andric if (nullability) 45770b57cec5SDimitry Andric return type; 45780b57cec5SDimitry Andric 45790b57cec5SDimitry Andric // Otherwise, provide the result with the same nullability. 45800b57cec5SDimitry Andric return S.Context.getAttributedType( 45810b57cec5SDimitry Andric AttributedType::getNullabilityAttrKind(*prevNullability), 45820b57cec5SDimitry Andric type, type); 45830b57cec5SDimitry Andric } 45840b57cec5SDimitry Andric 45850b57cec5SDimitry Andric /// Merge information from the declaration of a method in the \@interface 45860b57cec5SDimitry Andric /// (or a category/extension) into the corresponding method in the 45870b57cec5SDimitry Andric /// @implementation (for a class or category). 45880b57cec5SDimitry Andric static void mergeInterfaceMethodToImpl(Sema &S, 45890b57cec5SDimitry Andric ObjCMethodDecl *method, 45900b57cec5SDimitry Andric ObjCMethodDecl *prevMethod) { 45910b57cec5SDimitry Andric // Merge the objc_requires_super attribute. 45920b57cec5SDimitry Andric if (prevMethod->hasAttr<ObjCRequiresSuperAttr>() && 45930b57cec5SDimitry Andric !method->hasAttr<ObjCRequiresSuperAttr>()) { 45940b57cec5SDimitry Andric // merge the attribute into implementation. 45950b57cec5SDimitry Andric method->addAttr( 45960b57cec5SDimitry Andric ObjCRequiresSuperAttr::CreateImplicit(S.Context, 45970b57cec5SDimitry Andric method->getLocation())); 45980b57cec5SDimitry Andric } 45990b57cec5SDimitry Andric 46000b57cec5SDimitry Andric // Merge nullability of the result type. 46010b57cec5SDimitry Andric QualType newReturnType 46020b57cec5SDimitry Andric = mergeTypeNullabilityForRedecl( 46030b57cec5SDimitry Andric S, method->getReturnTypeSourceRange().getBegin(), 46040b57cec5SDimitry Andric method->getReturnType(), 46050b57cec5SDimitry Andric method->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability, 46060b57cec5SDimitry Andric prevMethod->getReturnTypeSourceRange().getBegin(), 46070b57cec5SDimitry Andric prevMethod->getReturnType(), 46080b57cec5SDimitry Andric prevMethod->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability); 46090b57cec5SDimitry Andric method->setReturnType(newReturnType); 46100b57cec5SDimitry Andric 46110b57cec5SDimitry Andric // Handle each of the parameters. 46120b57cec5SDimitry Andric unsigned numParams = method->param_size(); 46130b57cec5SDimitry Andric unsigned numPrevParams = prevMethod->param_size(); 46140b57cec5SDimitry Andric for (unsigned i = 0, n = std::min(numParams, numPrevParams); i != n; ++i) { 46150b57cec5SDimitry Andric ParmVarDecl *param = method->param_begin()[i]; 46160b57cec5SDimitry Andric ParmVarDecl *prevParam = prevMethod->param_begin()[i]; 46170b57cec5SDimitry Andric 46180b57cec5SDimitry Andric // Merge nullability. 46190b57cec5SDimitry Andric QualType newParamType 46200b57cec5SDimitry Andric = mergeTypeNullabilityForRedecl( 46210b57cec5SDimitry Andric S, param->getLocation(), param->getType(), 46220b57cec5SDimitry Andric param->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability, 46230b57cec5SDimitry Andric prevParam->getLocation(), prevParam->getType(), 46240b57cec5SDimitry Andric prevParam->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability); 46250b57cec5SDimitry Andric param->setType(newParamType); 46260b57cec5SDimitry Andric } 46270b57cec5SDimitry Andric } 46280b57cec5SDimitry Andric 46290b57cec5SDimitry Andric /// Verify that the method parameters/return value have types that are supported 46300b57cec5SDimitry Andric /// by the x86 target. 46310b57cec5SDimitry Andric static void checkObjCMethodX86VectorTypes(Sema &SemaRef, 46320b57cec5SDimitry Andric const ObjCMethodDecl *Method) { 46330b57cec5SDimitry Andric assert(SemaRef.getASTContext().getTargetInfo().getTriple().getArch() == 46340b57cec5SDimitry Andric llvm::Triple::x86 && 46350b57cec5SDimitry Andric "x86-specific check invoked for a different target"); 46360b57cec5SDimitry Andric SourceLocation Loc; 46370b57cec5SDimitry Andric QualType T; 46380b57cec5SDimitry Andric for (const ParmVarDecl *P : Method->parameters()) { 46390b57cec5SDimitry Andric if (P->getType()->isVectorType()) { 46400b57cec5SDimitry Andric Loc = P->getBeginLoc(); 46410b57cec5SDimitry Andric T = P->getType(); 46420b57cec5SDimitry Andric break; 46430b57cec5SDimitry Andric } 46440b57cec5SDimitry Andric } 46450b57cec5SDimitry Andric if (Loc.isInvalid()) { 46460b57cec5SDimitry Andric if (Method->getReturnType()->isVectorType()) { 46470b57cec5SDimitry Andric Loc = Method->getReturnTypeSourceRange().getBegin(); 46480b57cec5SDimitry Andric T = Method->getReturnType(); 46490b57cec5SDimitry Andric } else 46500b57cec5SDimitry Andric return; 46510b57cec5SDimitry Andric } 46520b57cec5SDimitry Andric 46530b57cec5SDimitry Andric // Vector parameters/return values are not supported by objc_msgSend on x86 in 46540b57cec5SDimitry Andric // iOS < 9 and macOS < 10.11. 46550b57cec5SDimitry Andric const auto &Triple = SemaRef.getASTContext().getTargetInfo().getTriple(); 46560b57cec5SDimitry Andric VersionTuple AcceptedInVersion; 46570b57cec5SDimitry Andric if (Triple.getOS() == llvm::Triple::IOS) 46580b57cec5SDimitry Andric AcceptedInVersion = VersionTuple(/*Major=*/9); 46590b57cec5SDimitry Andric else if (Triple.isMacOSX()) 46600b57cec5SDimitry Andric AcceptedInVersion = VersionTuple(/*Major=*/10, /*Minor=*/11); 46610b57cec5SDimitry Andric else 46620b57cec5SDimitry Andric return; 46630b57cec5SDimitry Andric if (SemaRef.getASTContext().getTargetInfo().getPlatformMinVersion() >= 46640b57cec5SDimitry Andric AcceptedInVersion) 46650b57cec5SDimitry Andric return; 46660b57cec5SDimitry Andric SemaRef.Diag(Loc, diag::err_objc_method_unsupported_param_ret_type) 46670b57cec5SDimitry Andric << T << (Method->getReturnType()->isVectorType() ? /*return value*/ 1 46680b57cec5SDimitry Andric : /*parameter*/ 0) 46690b57cec5SDimitry Andric << (Triple.isMacOSX() ? "macOS 10.11" : "iOS 9"); 46700b57cec5SDimitry Andric } 46710b57cec5SDimitry Andric 46725ffd83dbSDimitry Andric static void mergeObjCDirectMembers(Sema &S, Decl *CD, ObjCMethodDecl *Method) { 46735ffd83dbSDimitry Andric if (!Method->isDirectMethod() && !Method->hasAttr<UnavailableAttr>() && 46745ffd83dbSDimitry Andric CD->hasAttr<ObjCDirectMembersAttr>()) { 46755ffd83dbSDimitry Andric Method->addAttr( 46765ffd83dbSDimitry Andric ObjCDirectAttr::CreateImplicit(S.Context, Method->getLocation())); 46775ffd83dbSDimitry Andric } 46785ffd83dbSDimitry Andric } 46795ffd83dbSDimitry Andric 46805ffd83dbSDimitry Andric static void checkObjCDirectMethodClashes(Sema &S, ObjCInterfaceDecl *IDecl, 46815ffd83dbSDimitry Andric ObjCMethodDecl *Method, 46825ffd83dbSDimitry Andric ObjCImplDecl *ImpDecl = nullptr) { 46835ffd83dbSDimitry Andric auto Sel = Method->getSelector(); 46845ffd83dbSDimitry Andric bool isInstance = Method->isInstanceMethod(); 46855ffd83dbSDimitry Andric bool diagnosed = false; 46865ffd83dbSDimitry Andric 46875ffd83dbSDimitry Andric auto diagClash = [&](const ObjCMethodDecl *IMD) { 46885ffd83dbSDimitry Andric if (diagnosed || IMD->isImplicit()) 46895ffd83dbSDimitry Andric return; 46905ffd83dbSDimitry Andric if (Method->isDirectMethod() || IMD->isDirectMethod()) { 46915ffd83dbSDimitry Andric S.Diag(Method->getLocation(), diag::err_objc_direct_duplicate_decl) 46925ffd83dbSDimitry Andric << Method->isDirectMethod() << /* method */ 0 << IMD->isDirectMethod() 46935ffd83dbSDimitry Andric << Method->getDeclName(); 46945ffd83dbSDimitry Andric S.Diag(IMD->getLocation(), diag::note_previous_declaration); 46955ffd83dbSDimitry Andric diagnosed = true; 46965ffd83dbSDimitry Andric } 46975ffd83dbSDimitry Andric }; 46985ffd83dbSDimitry Andric 46995ffd83dbSDimitry Andric // Look for any other declaration of this method anywhere we can see in this 47005ffd83dbSDimitry Andric // compilation unit. 47015ffd83dbSDimitry Andric // 47025ffd83dbSDimitry Andric // We do not use IDecl->lookupMethod() because we have specific needs: 47035ffd83dbSDimitry Andric // 47045ffd83dbSDimitry Andric // - we absolutely do not need to walk protocols, because 47055ffd83dbSDimitry Andric // diag::err_objc_direct_on_protocol has already been emitted 47065ffd83dbSDimitry Andric // during parsing if there's a conflict, 47075ffd83dbSDimitry Andric // 47085ffd83dbSDimitry Andric // - when we do not find a match in a given @interface container, 47095ffd83dbSDimitry Andric // we need to attempt looking it up in the @implementation block if the 47105ffd83dbSDimitry Andric // translation unit sees it to find more clashes. 47115ffd83dbSDimitry Andric 47125ffd83dbSDimitry Andric if (auto *IMD = IDecl->getMethod(Sel, isInstance)) 47135ffd83dbSDimitry Andric diagClash(IMD); 47145ffd83dbSDimitry Andric else if (auto *Impl = IDecl->getImplementation()) 47155ffd83dbSDimitry Andric if (Impl != ImpDecl) 47165ffd83dbSDimitry Andric if (auto *IMD = IDecl->getImplementation()->getMethod(Sel, isInstance)) 47175ffd83dbSDimitry Andric diagClash(IMD); 47185ffd83dbSDimitry Andric 47195ffd83dbSDimitry Andric for (const auto *Cat : IDecl->visible_categories()) 47205ffd83dbSDimitry Andric if (auto *IMD = Cat->getMethod(Sel, isInstance)) 47215ffd83dbSDimitry Andric diagClash(IMD); 47225ffd83dbSDimitry Andric else if (auto CatImpl = Cat->getImplementation()) 47235ffd83dbSDimitry Andric if (CatImpl != ImpDecl) 47245ffd83dbSDimitry Andric if (auto *IMD = Cat->getMethod(Sel, isInstance)) 47255ffd83dbSDimitry Andric diagClash(IMD); 47265ffd83dbSDimitry Andric } 47275ffd83dbSDimitry Andric 4728*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnMethodDeclaration( 47290b57cec5SDimitry Andric Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, 47300b57cec5SDimitry Andric tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, 47310b57cec5SDimitry Andric ArrayRef<SourceLocation> SelectorLocs, Selector Sel, 47320b57cec5SDimitry Andric // optional arguments. The number of types/arguments is obtained 47330b57cec5SDimitry Andric // from the Sel.getNumArgs(). 47340b57cec5SDimitry Andric ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, 47350b57cec5SDimitry Andric unsigned CNumArgs, // c-style args 47360b57cec5SDimitry Andric const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, 47370b57cec5SDimitry Andric bool isVariadic, bool MethodDefinition) { 4738*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 47390b57cec5SDimitry Andric // Make sure we can establish a context for the method. 4740*0fca6ea1SDimitry Andric if (!SemaRef.CurContext->isObjCContainer()) { 47410b57cec5SDimitry Andric Diag(MethodLoc, diag::err_missing_method_context); 47420b57cec5SDimitry Andric return nullptr; 47430b57cec5SDimitry Andric } 4744480093f4SDimitry Andric 4745*0fca6ea1SDimitry Andric Decl *ClassDecl = cast<ObjCContainerDecl>(SemaRef.CurContext); 47460b57cec5SDimitry Andric QualType resultDeclType; 47470b57cec5SDimitry Andric 47480b57cec5SDimitry Andric bool HasRelatedResultType = false; 47490b57cec5SDimitry Andric TypeSourceInfo *ReturnTInfo = nullptr; 47500b57cec5SDimitry Andric if (ReturnType) { 4751*0fca6ea1SDimitry Andric resultDeclType = SemaRef.GetTypeFromParser(ReturnType, &ReturnTInfo); 47520b57cec5SDimitry Andric 4753*0fca6ea1SDimitry Andric if (SemaRef.CheckFunctionReturnType(resultDeclType, MethodLoc)) 47540b57cec5SDimitry Andric return nullptr; 47550b57cec5SDimitry Andric 47560b57cec5SDimitry Andric QualType bareResultType = resultDeclType; 47570b57cec5SDimitry Andric (void)AttributedType::stripOuterNullability(bareResultType); 47580b57cec5SDimitry Andric HasRelatedResultType = (bareResultType == Context.getObjCInstanceType()); 47590b57cec5SDimitry Andric } else { // get the type for "id". 47600b57cec5SDimitry Andric resultDeclType = Context.getObjCIdType(); 47610b57cec5SDimitry Andric Diag(MethodLoc, diag::warn_missing_method_return_type) 47620b57cec5SDimitry Andric << FixItHint::CreateInsertion(SelectorLocs.front(), "(id)"); 47630b57cec5SDimitry Andric } 47640b57cec5SDimitry Andric 47650b57cec5SDimitry Andric ObjCMethodDecl *ObjCMethod = ObjCMethodDecl::Create( 4766*0fca6ea1SDimitry Andric Context, MethodLoc, EndLoc, Sel, resultDeclType, ReturnTInfo, 4767*0fca6ea1SDimitry Andric SemaRef.CurContext, MethodType == tok::minus, isVariadic, 4768480093f4SDimitry Andric /*isPropertyAccessor=*/false, /*isSynthesizedAccessorStub=*/false, 47690b57cec5SDimitry Andric /*isImplicitlyDeclared=*/false, /*isDefined=*/false, 47705f757f3fSDimitry Andric MethodDeclKind == tok::objc_optional 47715f757f3fSDimitry Andric ? ObjCImplementationControl::Optional 47725f757f3fSDimitry Andric : ObjCImplementationControl::Required, 47730b57cec5SDimitry Andric HasRelatedResultType); 47740b57cec5SDimitry Andric 47750b57cec5SDimitry Andric SmallVector<ParmVarDecl*, 16> Params; 47760b57cec5SDimitry Andric 47770b57cec5SDimitry Andric for (unsigned i = 0, e = Sel.getNumArgs(); i != e; ++i) { 47780b57cec5SDimitry Andric QualType ArgType; 47790b57cec5SDimitry Andric TypeSourceInfo *DI; 47800b57cec5SDimitry Andric 47810b57cec5SDimitry Andric if (!ArgInfo[i].Type) { 47820b57cec5SDimitry Andric ArgType = Context.getObjCIdType(); 47830b57cec5SDimitry Andric DI = nullptr; 47840b57cec5SDimitry Andric } else { 4785*0fca6ea1SDimitry Andric ArgType = SemaRef.GetTypeFromParser(ArgInfo[i].Type, &DI); 47860b57cec5SDimitry Andric } 47870b57cec5SDimitry Andric 4788*0fca6ea1SDimitry Andric LookupResult R(SemaRef, ArgInfo[i].Name, ArgInfo[i].NameLoc, 4789*0fca6ea1SDimitry Andric Sema::LookupOrdinaryName, 4790*0fca6ea1SDimitry Andric SemaRef.forRedeclarationInCurContext()); 4791*0fca6ea1SDimitry Andric SemaRef.LookupName(R, S); 47920b57cec5SDimitry Andric if (R.isSingleResult()) { 47930b57cec5SDimitry Andric NamedDecl *PrevDecl = R.getFoundDecl(); 47940b57cec5SDimitry Andric if (S->isDeclScope(PrevDecl)) { 47950b57cec5SDimitry Andric Diag(ArgInfo[i].NameLoc, 47960b57cec5SDimitry Andric (MethodDefinition ? diag::warn_method_param_redefinition 47970b57cec5SDimitry Andric : diag::warn_method_param_declaration)) 47980b57cec5SDimitry Andric << ArgInfo[i].Name; 47990b57cec5SDimitry Andric Diag(PrevDecl->getLocation(), 48000b57cec5SDimitry Andric diag::note_previous_declaration); 48010b57cec5SDimitry Andric } 48020b57cec5SDimitry Andric } 48030b57cec5SDimitry Andric 48040b57cec5SDimitry Andric SourceLocation StartLoc = DI 48050b57cec5SDimitry Andric ? DI->getTypeLoc().getBeginLoc() 48060b57cec5SDimitry Andric : ArgInfo[i].NameLoc; 48070b57cec5SDimitry Andric 4808*0fca6ea1SDimitry Andric ParmVarDecl *Param = 4809*0fca6ea1SDimitry Andric SemaRef.CheckParameter(ObjCMethod, StartLoc, ArgInfo[i].NameLoc, 4810*0fca6ea1SDimitry Andric ArgInfo[i].Name, ArgType, DI, SC_None); 48110b57cec5SDimitry Andric 48120b57cec5SDimitry Andric Param->setObjCMethodScopeInfo(i); 48130b57cec5SDimitry Andric 48140b57cec5SDimitry Andric Param->setObjCDeclQualifier( 48150b57cec5SDimitry Andric CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); 48160b57cec5SDimitry Andric 48170b57cec5SDimitry Andric // Apply the attributes to the parameter. 4818*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, Param, 4819*0fca6ea1SDimitry Andric ArgInfo[i].ArgAttrs); 4820*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, Param); 4821*0fca6ea1SDimitry Andric SemaRef.ProcessAPINotes(Param); 48220b57cec5SDimitry Andric 48230b57cec5SDimitry Andric if (Param->hasAttr<BlocksAttr>()) { 48240b57cec5SDimitry Andric Diag(Param->getLocation(), diag::err_block_on_nonlocal); 48250b57cec5SDimitry Andric Param->setInvalidDecl(); 48260b57cec5SDimitry Andric } 48270b57cec5SDimitry Andric S->AddDecl(Param); 4828*0fca6ea1SDimitry Andric SemaRef.IdResolver.AddDecl(Param); 48290b57cec5SDimitry Andric 48300b57cec5SDimitry Andric Params.push_back(Param); 48310b57cec5SDimitry Andric } 48320b57cec5SDimitry Andric 48330b57cec5SDimitry Andric for (unsigned i = 0, e = CNumArgs; i != e; ++i) { 48340b57cec5SDimitry Andric ParmVarDecl *Param = cast<ParmVarDecl>(CParamInfo[i].Param); 48350b57cec5SDimitry Andric QualType ArgType = Param->getType(); 48360b57cec5SDimitry Andric if (ArgType.isNull()) 48370b57cec5SDimitry Andric ArgType = Context.getObjCIdType(); 48380b57cec5SDimitry Andric else 48390b57cec5SDimitry Andric // Perform the default array/function conversions (C99 6.7.5.3p[7,8]). 48400b57cec5SDimitry Andric ArgType = Context.getAdjustedParameterType(ArgType); 48410b57cec5SDimitry Andric 48420b57cec5SDimitry Andric Param->setDeclContext(ObjCMethod); 48430b57cec5SDimitry Andric Params.push_back(Param); 48440b57cec5SDimitry Andric } 48450b57cec5SDimitry Andric 48460b57cec5SDimitry Andric ObjCMethod->setMethodParams(Context, Params, SelectorLocs); 48470b57cec5SDimitry Andric ObjCMethod->setObjCDeclQualifier( 48480b57cec5SDimitry Andric CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); 48490b57cec5SDimitry Andric 4850*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, ObjCMethod, AttrList); 4851*0fca6ea1SDimitry Andric SemaRef.AddPragmaAttributes(SemaRef.TUScope, ObjCMethod); 4852*0fca6ea1SDimitry Andric SemaRef.ProcessAPINotes(ObjCMethod); 48530b57cec5SDimitry Andric 48540b57cec5SDimitry Andric // Add the method now. 48550b57cec5SDimitry Andric const ObjCMethodDecl *PrevMethod = nullptr; 48560b57cec5SDimitry Andric if (ObjCImplDecl *ImpDecl = dyn_cast<ObjCImplDecl>(ClassDecl)) { 48570b57cec5SDimitry Andric if (MethodType == tok::minus) { 48580b57cec5SDimitry Andric PrevMethod = ImpDecl->getInstanceMethod(Sel); 48590b57cec5SDimitry Andric ImpDecl->addInstanceMethod(ObjCMethod); 48600b57cec5SDimitry Andric } else { 48610b57cec5SDimitry Andric PrevMethod = ImpDecl->getClassMethod(Sel); 48620b57cec5SDimitry Andric ImpDecl->addClassMethod(ObjCMethod); 48630b57cec5SDimitry Andric } 48640b57cec5SDimitry Andric 4865480093f4SDimitry Andric // If this method overrides a previous @synthesize declaration, 4866480093f4SDimitry Andric // register it with the property. Linear search through all 4867480093f4SDimitry Andric // properties here, because the autosynthesized stub hasn't been 4868349cc55cSDimitry Andric // made visible yet, so it can be overridden by a later 4869480093f4SDimitry Andric // user-specified implementation. 4870480093f4SDimitry Andric for (ObjCPropertyImplDecl *PropertyImpl : ImpDecl->property_impls()) { 4871480093f4SDimitry Andric if (auto *Setter = PropertyImpl->getSetterMethodDecl()) 4872480093f4SDimitry Andric if (Setter->getSelector() == Sel && 4873480093f4SDimitry Andric Setter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) { 4874480093f4SDimitry Andric assert(Setter->isSynthesizedAccessorStub() && "autosynth stub expected"); 4875480093f4SDimitry Andric PropertyImpl->setSetterMethodDecl(ObjCMethod); 4876480093f4SDimitry Andric } 4877480093f4SDimitry Andric if (auto *Getter = PropertyImpl->getGetterMethodDecl()) 4878480093f4SDimitry Andric if (Getter->getSelector() == Sel && 4879480093f4SDimitry Andric Getter->isInstanceMethod() == ObjCMethod->isInstanceMethod()) { 4880480093f4SDimitry Andric assert(Getter->isSynthesizedAccessorStub() && "autosynth stub expected"); 4881480093f4SDimitry Andric PropertyImpl->setGetterMethodDecl(ObjCMethod); 4882480093f4SDimitry Andric break; 4883480093f4SDimitry Andric } 4884480093f4SDimitry Andric } 4885480093f4SDimitry Andric 4886480093f4SDimitry Andric // A method is either tagged direct explicitly, or inherits it from its 4887480093f4SDimitry Andric // canonical declaration. 4888480093f4SDimitry Andric // 4889480093f4SDimitry Andric // We have to do the merge upfront and not in mergeInterfaceMethodToImpl() 4890480093f4SDimitry Andric // because IDecl->lookupMethod() returns more possible matches than just 4891480093f4SDimitry Andric // the canonical declaration. 4892480093f4SDimitry Andric if (!ObjCMethod->isDirectMethod()) { 4893480093f4SDimitry Andric const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl(); 4894fe6060f1SDimitry Andric if (CanonicalMD->isDirectMethod()) { 4895fe6060f1SDimitry Andric const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>(); 4896480093f4SDimitry Andric ObjCMethod->addAttr( 4897480093f4SDimitry Andric ObjCDirectAttr::CreateImplicit(Context, attr->getLocation())); 4898480093f4SDimitry Andric } 4899480093f4SDimitry Andric } 4900480093f4SDimitry Andric 49010b57cec5SDimitry Andric // Merge information from the @interface declaration into the 49020b57cec5SDimitry Andric // @implementation. 49030b57cec5SDimitry Andric if (ObjCInterfaceDecl *IDecl = ImpDecl->getClassInterface()) { 49040b57cec5SDimitry Andric if (auto *IMD = IDecl->lookupMethod(ObjCMethod->getSelector(), 49050b57cec5SDimitry Andric ObjCMethod->isInstanceMethod())) { 4906*0fca6ea1SDimitry Andric mergeInterfaceMethodToImpl(SemaRef, ObjCMethod, IMD); 49070b57cec5SDimitry Andric 4908480093f4SDimitry Andric // The Idecl->lookupMethod() above will find declarations for ObjCMethod 4909480093f4SDimitry Andric // in one of these places: 4910480093f4SDimitry Andric // 4911480093f4SDimitry Andric // (1) the canonical declaration in an @interface container paired 4912480093f4SDimitry Andric // with the ImplDecl, 4913480093f4SDimitry Andric // (2) non canonical declarations in @interface not paired with the 4914480093f4SDimitry Andric // ImplDecl for the same Class, 4915480093f4SDimitry Andric // (3) any superclass container. 4916480093f4SDimitry Andric // 4917480093f4SDimitry Andric // Direct methods only allow for canonical declarations in the matching 4918480093f4SDimitry Andric // container (case 1). 4919480093f4SDimitry Andric // 4920480093f4SDimitry Andric // Direct methods overriding a superclass declaration (case 3) is 4921480093f4SDimitry Andric // handled during overrides checks in CheckObjCMethodOverrides(). 4922480093f4SDimitry Andric // 4923480093f4SDimitry Andric // We deal with same-class container mismatches (Case 2) here. 4924480093f4SDimitry Andric if (IDecl == IMD->getClassInterface()) { 4925480093f4SDimitry Andric auto diagContainerMismatch = [&] { 4926480093f4SDimitry Andric int decl = 0, impl = 0; 4927480093f4SDimitry Andric 4928480093f4SDimitry Andric if (auto *Cat = dyn_cast<ObjCCategoryDecl>(IMD->getDeclContext())) 4929480093f4SDimitry Andric decl = Cat->IsClassExtension() ? 1 : 2; 4930480093f4SDimitry Andric 4931480093f4SDimitry Andric if (isa<ObjCCategoryImplDecl>(ImpDecl)) 4932480093f4SDimitry Andric impl = 1 + (decl != 0); 4933480093f4SDimitry Andric 4934480093f4SDimitry Andric Diag(ObjCMethod->getLocation(), 4935480093f4SDimitry Andric diag::err_objc_direct_impl_decl_mismatch) 4936480093f4SDimitry Andric << decl << impl; 4937480093f4SDimitry Andric Diag(IMD->getLocation(), diag::note_previous_declaration); 4938480093f4SDimitry Andric }; 4939480093f4SDimitry Andric 4940fe6060f1SDimitry Andric if (ObjCMethod->isDirectMethod()) { 4941fe6060f1SDimitry Andric const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>(); 4942480093f4SDimitry Andric if (ObjCMethod->getCanonicalDecl() != IMD) { 4943480093f4SDimitry Andric diagContainerMismatch(); 4944480093f4SDimitry Andric } else if (!IMD->isDirectMethod()) { 4945480093f4SDimitry Andric Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl); 4946480093f4SDimitry Andric Diag(IMD->getLocation(), diag::note_previous_declaration); 4947480093f4SDimitry Andric } 4948fe6060f1SDimitry Andric } else if (IMD->isDirectMethod()) { 4949fe6060f1SDimitry Andric const auto *attr = IMD->getAttr<ObjCDirectAttr>(); 4950480093f4SDimitry Andric if (ObjCMethod->getCanonicalDecl() != IMD) { 4951480093f4SDimitry Andric diagContainerMismatch(); 4952480093f4SDimitry Andric } else { 4953480093f4SDimitry Andric ObjCMethod->addAttr( 4954480093f4SDimitry Andric ObjCDirectAttr::CreateImplicit(Context, attr->getLocation())); 4955480093f4SDimitry Andric } 4956480093f4SDimitry Andric } 4957480093f4SDimitry Andric } 4958480093f4SDimitry Andric 49590b57cec5SDimitry Andric // Warn about defining -dealloc in a category. 49600b57cec5SDimitry Andric if (isa<ObjCCategoryImplDecl>(ImpDecl) && IMD->isOverriding() && 49610b57cec5SDimitry Andric ObjCMethod->getSelector().getMethodFamily() == OMF_dealloc) { 49620b57cec5SDimitry Andric Diag(ObjCMethod->getLocation(), diag::warn_dealloc_in_category) 49630b57cec5SDimitry Andric << ObjCMethod->getDeclName(); 49640b57cec5SDimitry Andric } 49655ffd83dbSDimitry Andric } else { 4966*0fca6ea1SDimitry Andric mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod); 4967*0fca6ea1SDimitry Andric checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod, ImpDecl); 49680b57cec5SDimitry Andric } 49690b57cec5SDimitry Andric 49700b57cec5SDimitry Andric // Warn if a method declared in a protocol to which a category or 49710b57cec5SDimitry Andric // extension conforms is non-escaping and the implementation's method is 49720b57cec5SDimitry Andric // escaping. 49730b57cec5SDimitry Andric for (auto *C : IDecl->visible_categories()) 49740b57cec5SDimitry Andric for (auto &P : C->protocols()) 49750b57cec5SDimitry Andric if (auto *IMD = P->lookupMethod(ObjCMethod->getSelector(), 49760b57cec5SDimitry Andric ObjCMethod->isInstanceMethod())) { 49770b57cec5SDimitry Andric assert(ObjCMethod->parameters().size() == 49780b57cec5SDimitry Andric IMD->parameters().size() && 49790b57cec5SDimitry Andric "Methods have different number of parameters"); 49800b57cec5SDimitry Andric auto OI = IMD->param_begin(), OE = IMD->param_end(); 49810b57cec5SDimitry Andric auto NI = ObjCMethod->param_begin(); 49820b57cec5SDimitry Andric for (; OI != OE; ++OI, ++NI) 4983*0fca6ea1SDimitry Andric diagnoseNoescape(*NI, *OI, C, P, SemaRef); 49840b57cec5SDimitry Andric } 49850b57cec5SDimitry Andric } 49860b57cec5SDimitry Andric } else { 4987480093f4SDimitry Andric if (!isa<ObjCProtocolDecl>(ClassDecl)) { 4988*0fca6ea1SDimitry Andric mergeObjCDirectMembers(SemaRef, ClassDecl, ObjCMethod); 4989480093f4SDimitry Andric 4990480093f4SDimitry Andric ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl); 4991480093f4SDimitry Andric if (!IDecl) 4992480093f4SDimitry Andric IDecl = cast<ObjCCategoryDecl>(ClassDecl)->getClassInterface(); 49935ffd83dbSDimitry Andric // For valid code, we should always know the primary interface 49945ffd83dbSDimitry Andric // declaration by now, however for invalid code we'll keep parsing 49955ffd83dbSDimitry Andric // but we won't find the primary interface and IDecl will be nil. 4996480093f4SDimitry Andric if (IDecl) 4997*0fca6ea1SDimitry Andric checkObjCDirectMethodClashes(SemaRef, IDecl, ObjCMethod); 4998480093f4SDimitry Andric } 4999480093f4SDimitry Andric 50000b57cec5SDimitry Andric cast<DeclContext>(ClassDecl)->addDecl(ObjCMethod); 50010b57cec5SDimitry Andric } 50020b57cec5SDimitry Andric 50030b57cec5SDimitry Andric if (PrevMethod) { 50040b57cec5SDimitry Andric // You can never have two method definitions with the same name. 50050b57cec5SDimitry Andric Diag(ObjCMethod->getLocation(), diag::err_duplicate_method_decl) 50060b57cec5SDimitry Andric << ObjCMethod->getDeclName(); 50070b57cec5SDimitry Andric Diag(PrevMethod->getLocation(), diag::note_previous_declaration); 50080b57cec5SDimitry Andric ObjCMethod->setInvalidDecl(); 50090b57cec5SDimitry Andric return ObjCMethod; 50100b57cec5SDimitry Andric } 50110b57cec5SDimitry Andric 50120b57cec5SDimitry Andric // If this Objective-C method does not have a related result type, but we 50130b57cec5SDimitry Andric // are allowed to infer related result types, try to do so based on the 50140b57cec5SDimitry Andric // method family. 50150b57cec5SDimitry Andric ObjCInterfaceDecl *CurrentClass = dyn_cast<ObjCInterfaceDecl>(ClassDecl); 50160b57cec5SDimitry Andric if (!CurrentClass) { 50170b57cec5SDimitry Andric if (ObjCCategoryDecl *Cat = dyn_cast<ObjCCategoryDecl>(ClassDecl)) 50180b57cec5SDimitry Andric CurrentClass = Cat->getClassInterface(); 50190b57cec5SDimitry Andric else if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(ClassDecl)) 50200b57cec5SDimitry Andric CurrentClass = Impl->getClassInterface(); 50210b57cec5SDimitry Andric else if (ObjCCategoryImplDecl *CatImpl 50220b57cec5SDimitry Andric = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) 50230b57cec5SDimitry Andric CurrentClass = CatImpl->getClassInterface(); 50240b57cec5SDimitry Andric } 50250b57cec5SDimitry Andric 5026*0fca6ea1SDimitry Andric ResultTypeCompatibilityKind RTC = 5027*0fca6ea1SDimitry Andric CheckRelatedResultTypeCompatibility(SemaRef, ObjCMethod, CurrentClass); 50280b57cec5SDimitry Andric 50290b57cec5SDimitry Andric CheckObjCMethodOverrides(ObjCMethod, CurrentClass, RTC); 50300b57cec5SDimitry Andric 50310b57cec5SDimitry Andric bool ARCError = false; 50320b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount) 50330b57cec5SDimitry Andric ARCError = CheckARCMethodDecl(ObjCMethod); 50340b57cec5SDimitry Andric 50350b57cec5SDimitry Andric // Infer the related result type when possible. 5036*0fca6ea1SDimitry Andric if (!ARCError && RTC == SemaObjC::RTC_Compatible && 50370b57cec5SDimitry Andric !ObjCMethod->hasRelatedResultType() && 5038*0fca6ea1SDimitry Andric getLangOpts().ObjCInferRelatedResultType) { 50390b57cec5SDimitry Andric bool InferRelatedResultType = false; 50400b57cec5SDimitry Andric switch (ObjCMethod->getMethodFamily()) { 50410b57cec5SDimitry Andric case OMF_None: 50420b57cec5SDimitry Andric case OMF_copy: 50430b57cec5SDimitry Andric case OMF_dealloc: 50440b57cec5SDimitry Andric case OMF_finalize: 50450b57cec5SDimitry Andric case OMF_mutableCopy: 50460b57cec5SDimitry Andric case OMF_release: 50470b57cec5SDimitry Andric case OMF_retainCount: 50480b57cec5SDimitry Andric case OMF_initialize: 50490b57cec5SDimitry Andric case OMF_performSelector: 50500b57cec5SDimitry Andric break; 50510b57cec5SDimitry Andric 50520b57cec5SDimitry Andric case OMF_alloc: 50530b57cec5SDimitry Andric case OMF_new: 50540b57cec5SDimitry Andric InferRelatedResultType = ObjCMethod->isClassMethod(); 50550b57cec5SDimitry Andric break; 50560b57cec5SDimitry Andric 50570b57cec5SDimitry Andric case OMF_init: 50580b57cec5SDimitry Andric case OMF_autorelease: 50590b57cec5SDimitry Andric case OMF_retain: 50600b57cec5SDimitry Andric case OMF_self: 50610b57cec5SDimitry Andric InferRelatedResultType = ObjCMethod->isInstanceMethod(); 50620b57cec5SDimitry Andric break; 50630b57cec5SDimitry Andric } 50640b57cec5SDimitry Andric 50650b57cec5SDimitry Andric if (InferRelatedResultType && 50660b57cec5SDimitry Andric !ObjCMethod->getReturnType()->isObjCIndependentClassType()) 50670b57cec5SDimitry Andric ObjCMethod->setRelatedResultType(); 50680b57cec5SDimitry Andric } 50690b57cec5SDimitry Andric 50700b57cec5SDimitry Andric if (MethodDefinition && 50710b57cec5SDimitry Andric Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) 5072*0fca6ea1SDimitry Andric checkObjCMethodX86VectorTypes(SemaRef, ObjCMethod); 50730b57cec5SDimitry Andric 50740b57cec5SDimitry Andric // + load method cannot have availability attributes. It get called on 50750b57cec5SDimitry Andric // startup, so it has to have the availability of the deployment target. 50760b57cec5SDimitry Andric if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) { 50770b57cec5SDimitry Andric if (ObjCMethod->isClassMethod() && 50780b57cec5SDimitry Andric ObjCMethod->getSelector().getAsString() == "load") { 50790b57cec5SDimitry Andric Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) 50800b57cec5SDimitry Andric << 0; 50810b57cec5SDimitry Andric ObjCMethod->dropAttr<AvailabilityAttr>(); 50820b57cec5SDimitry Andric } 50830b57cec5SDimitry Andric } 50840b57cec5SDimitry Andric 5085480093f4SDimitry Andric // Insert the invisible arguments, self and _cmd! 5086480093f4SDimitry Andric ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface()); 5087480093f4SDimitry Andric 5088*0fca6ea1SDimitry Andric SemaRef.ActOnDocumentableDecl(ObjCMethod); 50890b57cec5SDimitry Andric 50900b57cec5SDimitry Andric return ObjCMethod; 50910b57cec5SDimitry Andric } 50920b57cec5SDimitry Andric 5093*0fca6ea1SDimitry Andric bool SemaObjC::CheckObjCDeclScope(Decl *D) { 50940b57cec5SDimitry Andric // Following is also an error. But it is caused by a missing @end 50950b57cec5SDimitry Andric // and diagnostic is issued elsewhere. 5096*0fca6ea1SDimitry Andric if (isa<ObjCContainerDecl>(SemaRef.CurContext->getRedeclContext())) 50970b57cec5SDimitry Andric return false; 50980b57cec5SDimitry Andric 50990b57cec5SDimitry Andric // If we switched context to translation unit while we are still lexically in 51000b57cec5SDimitry Andric // an objc container, it means the parser missed emitting an error. 5101*0fca6ea1SDimitry Andric if (isa<TranslationUnitDecl>( 5102*0fca6ea1SDimitry Andric SemaRef.getCurLexicalContext()->getRedeclContext())) 51030b57cec5SDimitry Andric return false; 51040b57cec5SDimitry Andric 51050b57cec5SDimitry Andric Diag(D->getLocation(), diag::err_objc_decls_may_only_appear_in_global_scope); 51060b57cec5SDimitry Andric D->setInvalidDecl(); 51070b57cec5SDimitry Andric 51080b57cec5SDimitry Andric return true; 51090b57cec5SDimitry Andric } 51100b57cec5SDimitry Andric 51110b57cec5SDimitry Andric /// Called whenever \@defs(ClassName) is encountered in the source. Inserts the 51120b57cec5SDimitry Andric /// instance variables of ClassName into Decls. 5113*0fca6ea1SDimitry Andric void SemaObjC::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, 5114*0fca6ea1SDimitry Andric const IdentifierInfo *ClassName, 51150b57cec5SDimitry Andric SmallVectorImpl<Decl *> &Decls) { 5116*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 51170b57cec5SDimitry Andric // Check that ClassName is a valid class 51180b57cec5SDimitry Andric ObjCInterfaceDecl *Class = getObjCInterfaceDecl(ClassName, DeclStart); 51190b57cec5SDimitry Andric if (!Class) { 51200b57cec5SDimitry Andric Diag(DeclStart, diag::err_undef_interface) << ClassName; 51210b57cec5SDimitry Andric return; 51220b57cec5SDimitry Andric } 5123*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isNonFragile()) { 51240b57cec5SDimitry Andric Diag(DeclStart, diag::err_atdef_nonfragile_interface); 51250b57cec5SDimitry Andric return; 51260b57cec5SDimitry Andric } 51270b57cec5SDimitry Andric 51280b57cec5SDimitry Andric // Collect the instance variables 51290b57cec5SDimitry Andric SmallVector<const ObjCIvarDecl*, 32> Ivars; 51300b57cec5SDimitry Andric Context.DeepCollectObjCIvars(Class, true, Ivars); 51310b57cec5SDimitry Andric // For each ivar, create a fresh ObjCAtDefsFieldDecl. 51320b57cec5SDimitry Andric for (unsigned i = 0; i < Ivars.size(); i++) { 51330b57cec5SDimitry Andric const FieldDecl* ID = Ivars[i]; 51340b57cec5SDimitry Andric RecordDecl *Record = dyn_cast<RecordDecl>(TagD); 51350b57cec5SDimitry Andric Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, 51360b57cec5SDimitry Andric /*FIXME: StartL=*/ID->getLocation(), 51370b57cec5SDimitry Andric ID->getLocation(), 51380b57cec5SDimitry Andric ID->getIdentifier(), ID->getType(), 51390b57cec5SDimitry Andric ID->getBitWidth()); 51400b57cec5SDimitry Andric Decls.push_back(FD); 51410b57cec5SDimitry Andric } 51420b57cec5SDimitry Andric 51430b57cec5SDimitry Andric // Introduce all of these fields into the appropriate scope. 51440b57cec5SDimitry Andric for (SmallVectorImpl<Decl*>::iterator D = Decls.begin(); 51450b57cec5SDimitry Andric D != Decls.end(); ++D) { 51460b57cec5SDimitry Andric FieldDecl *FD = cast<FieldDecl>(*D); 51470b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) 5148*0fca6ea1SDimitry Andric SemaRef.PushOnScopeChains(FD, S); 51490b57cec5SDimitry Andric else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD)) 51500b57cec5SDimitry Andric Record->addDecl(FD); 51510b57cec5SDimitry Andric } 51520b57cec5SDimitry Andric } 51530b57cec5SDimitry Andric 51540b57cec5SDimitry Andric /// Build a type-check a new Objective-C exception variable declaration. 5155*0fca6ea1SDimitry Andric VarDecl *SemaObjC::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, 51560b57cec5SDimitry Andric SourceLocation StartLoc, 51570b57cec5SDimitry Andric SourceLocation IdLoc, 5158*0fca6ea1SDimitry Andric const IdentifierInfo *Id, 51590b57cec5SDimitry Andric bool Invalid) { 5160*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 51610b57cec5SDimitry Andric // ISO/IEC TR 18037 S6.7.3: "The type of an object with automatic storage 51620b57cec5SDimitry Andric // duration shall not be qualified by an address-space qualifier." 51630b57cec5SDimitry Andric // Since all parameters have automatic store duration, they can not have 51640b57cec5SDimitry Andric // an address space. 51650b57cec5SDimitry Andric if (T.getAddressSpace() != LangAS::Default) { 51660b57cec5SDimitry Andric Diag(IdLoc, diag::err_arg_with_address_space); 51670b57cec5SDimitry Andric Invalid = true; 51680b57cec5SDimitry Andric } 51690b57cec5SDimitry Andric 51700b57cec5SDimitry Andric // An @catch parameter must be an unqualified object pointer type; 51710b57cec5SDimitry Andric // FIXME: Recover from "NSObject foo" by inserting the * in "NSObject *foo"? 51720b57cec5SDimitry Andric if (Invalid) { 51730b57cec5SDimitry Andric // Don't do any further checking. 51740b57cec5SDimitry Andric } else if (T->isDependentType()) { 51750b57cec5SDimitry Andric // Okay: we don't know what this type will instantiate to. 51760b57cec5SDimitry Andric } else if (T->isObjCQualifiedIdType()) { 51770b57cec5SDimitry Andric Invalid = true; 51780b57cec5SDimitry Andric Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); 51790b57cec5SDimitry Andric } else if (T->isObjCIdType()) { 51800b57cec5SDimitry Andric // Okay: we don't know what this type will instantiate to. 51810b57cec5SDimitry Andric } else if (!T->isObjCObjectPointerType()) { 51820b57cec5SDimitry Andric Invalid = true; 51830b57cec5SDimitry Andric Diag(IdLoc, diag::err_catch_param_not_objc_type); 5184a7dea167SDimitry Andric } else if (!T->castAs<ObjCObjectPointerType>()->getInterfaceType()) { 51850b57cec5SDimitry Andric Invalid = true; 51860b57cec5SDimitry Andric Diag(IdLoc, diag::err_catch_param_not_objc_type); 51870b57cec5SDimitry Andric } 51880b57cec5SDimitry Andric 5189*0fca6ea1SDimitry Andric VarDecl *New = VarDecl::Create(Context, SemaRef.CurContext, StartLoc, IdLoc, 5190*0fca6ea1SDimitry Andric Id, T, TInfo, SC_None); 51910b57cec5SDimitry Andric New->setExceptionVariable(true); 51920b57cec5SDimitry Andric 51930b57cec5SDimitry Andric // In ARC, infer 'retaining' for variables of retainable type. 51940b57cec5SDimitry Andric if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(New)) 51950b57cec5SDimitry Andric Invalid = true; 51960b57cec5SDimitry Andric 51970b57cec5SDimitry Andric if (Invalid) 51980b57cec5SDimitry Andric New->setInvalidDecl(); 51990b57cec5SDimitry Andric return New; 52000b57cec5SDimitry Andric } 52010b57cec5SDimitry Andric 5202*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnObjCExceptionDecl(Scope *S, Declarator &D) { 52030b57cec5SDimitry Andric const DeclSpec &DS = D.getDeclSpec(); 52040b57cec5SDimitry Andric 52050b57cec5SDimitry Andric // We allow the "register" storage class on exception variables because 52060b57cec5SDimitry Andric // GCC did, but we drop it completely. Any other storage class is an error. 52070b57cec5SDimitry Andric if (DS.getStorageClassSpec() == DeclSpec::SCS_register) { 52080b57cec5SDimitry Andric Diag(DS.getStorageClassSpecLoc(), diag::warn_register_objc_catch_parm) 52090b57cec5SDimitry Andric << FixItHint::CreateRemoval(SourceRange(DS.getStorageClassSpecLoc())); 52100b57cec5SDimitry Andric } else if (DeclSpec::SCS SCS = DS.getStorageClassSpec()) { 52110b57cec5SDimitry Andric Diag(DS.getStorageClassSpecLoc(), diag::err_storage_spec_on_catch_parm) 52120b57cec5SDimitry Andric << DeclSpec::getSpecifierName(SCS); 52130b57cec5SDimitry Andric } 52140b57cec5SDimitry Andric if (DS.isInlineSpecified()) 52150b57cec5SDimitry Andric Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) 52160b57cec5SDimitry Andric << getLangOpts().CPlusPlus17; 52170b57cec5SDimitry Andric if (DeclSpec::TSCS TSCS = D.getDeclSpec().getThreadStorageClassSpec()) 52180b57cec5SDimitry Andric Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), 52190b57cec5SDimitry Andric diag::err_invalid_thread) 52200b57cec5SDimitry Andric << DeclSpec::getSpecifierName(TSCS); 52210b57cec5SDimitry Andric D.getMutableDeclSpec().ClearStorageClassSpecs(); 52220b57cec5SDimitry Andric 5223*0fca6ea1SDimitry Andric SemaRef.DiagnoseFunctionSpecifiers(D.getDeclSpec()); 52240b57cec5SDimitry Andric 52250b57cec5SDimitry Andric // Check that there are no default arguments inside the type of this 52260b57cec5SDimitry Andric // exception object (C++ only). 52270b57cec5SDimitry Andric if (getLangOpts().CPlusPlus) 5228*0fca6ea1SDimitry Andric SemaRef.CheckExtraCXXDefaultArguments(D); 52290b57cec5SDimitry Andric 5230*0fca6ea1SDimitry Andric TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 52310b57cec5SDimitry Andric QualType ExceptionType = TInfo->getType(); 52320b57cec5SDimitry Andric 52330b57cec5SDimitry Andric VarDecl *New = BuildObjCExceptionDecl(TInfo, ExceptionType, 52340b57cec5SDimitry Andric D.getSourceRange().getBegin(), 52350b57cec5SDimitry Andric D.getIdentifierLoc(), 52360b57cec5SDimitry Andric D.getIdentifier(), 52370b57cec5SDimitry Andric D.isInvalidType()); 52380b57cec5SDimitry Andric 52390b57cec5SDimitry Andric // Parameter declarators cannot be qualified (C++ [dcl.meaning]p1). 52400b57cec5SDimitry Andric if (D.getCXXScopeSpec().isSet()) { 52410b57cec5SDimitry Andric Diag(D.getIdentifierLoc(), diag::err_qualified_objc_catch_parm) 52420b57cec5SDimitry Andric << D.getCXXScopeSpec().getRange(); 52430b57cec5SDimitry Andric New->setInvalidDecl(); 52440b57cec5SDimitry Andric } 52450b57cec5SDimitry Andric 52460b57cec5SDimitry Andric // Add the parameter declaration into this scope. 52470b57cec5SDimitry Andric S->AddDecl(New); 52480b57cec5SDimitry Andric if (D.getIdentifier()) 5249*0fca6ea1SDimitry Andric SemaRef.IdResolver.AddDecl(New); 52500b57cec5SDimitry Andric 5251*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributes(S, New, D); 52520b57cec5SDimitry Andric 52530b57cec5SDimitry Andric if (New->hasAttr<BlocksAttr>()) 52540b57cec5SDimitry Andric Diag(New->getLocation(), diag::err_block_on_nonlocal); 52550b57cec5SDimitry Andric return New; 52560b57cec5SDimitry Andric } 52570b57cec5SDimitry Andric 52580b57cec5SDimitry Andric /// CollectIvarsToConstructOrDestruct - Collect those ivars which require 52590b57cec5SDimitry Andric /// initialization. 5260*0fca6ea1SDimitry Andric void SemaObjC::CollectIvarsToConstructOrDestruct( 5261*0fca6ea1SDimitry Andric ObjCInterfaceDecl *OI, SmallVectorImpl<ObjCIvarDecl *> &Ivars) { 5262*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 52630b57cec5SDimitry Andric for (ObjCIvarDecl *Iv = OI->all_declared_ivar_begin(); Iv; 52640b57cec5SDimitry Andric Iv= Iv->getNextIvar()) { 52650b57cec5SDimitry Andric QualType QT = Context.getBaseElementType(Iv->getType()); 52660b57cec5SDimitry Andric if (QT->isRecordType()) 52670b57cec5SDimitry Andric Ivars.push_back(Iv); 52680b57cec5SDimitry Andric } 52690b57cec5SDimitry Andric } 52700b57cec5SDimitry Andric 5271*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseUseOfUnimplementedSelectors() { 5272*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 52730b57cec5SDimitry Andric // Load referenced selectors from the external source. 5274*0fca6ea1SDimitry Andric if (SemaRef.ExternalSource) { 52750b57cec5SDimitry Andric SmallVector<std::pair<Selector, SourceLocation>, 4> Sels; 5276*0fca6ea1SDimitry Andric SemaRef.ExternalSource->ReadReferencedSelectors(Sels); 52770b57cec5SDimitry Andric for (unsigned I = 0, N = Sels.size(); I != N; ++I) 52780b57cec5SDimitry Andric ReferencedSelectors[Sels[I].first] = Sels[I].second; 52790b57cec5SDimitry Andric } 52800b57cec5SDimitry Andric 52810b57cec5SDimitry Andric // Warning will be issued only when selector table is 52820b57cec5SDimitry Andric // generated (which means there is at lease one implementation 52830b57cec5SDimitry Andric // in the TU). This is to match gcc's behavior. 52840b57cec5SDimitry Andric if (ReferencedSelectors.empty() || 52850b57cec5SDimitry Andric !Context.AnyObjCImplementation()) 52860b57cec5SDimitry Andric return; 52870b57cec5SDimitry Andric for (auto &SelectorAndLocation : ReferencedSelectors) { 52880b57cec5SDimitry Andric Selector Sel = SelectorAndLocation.first; 52890b57cec5SDimitry Andric SourceLocation Loc = SelectorAndLocation.second; 52900b57cec5SDimitry Andric if (!LookupImplementedMethodInGlobalPool(Sel)) 52910b57cec5SDimitry Andric Diag(Loc, diag::warn_unimplemented_selector) << Sel; 52920b57cec5SDimitry Andric } 52930b57cec5SDimitry Andric } 52940b57cec5SDimitry Andric 52950b57cec5SDimitry Andric ObjCIvarDecl * 5296*0fca6ea1SDimitry Andric SemaObjC::GetIvarBackingPropertyAccessor(const ObjCMethodDecl *Method, 52970b57cec5SDimitry Andric const ObjCPropertyDecl *&PDecl) const { 52980b57cec5SDimitry Andric if (Method->isClassMethod()) 52990b57cec5SDimitry Andric return nullptr; 53000b57cec5SDimitry Andric const ObjCInterfaceDecl *IDecl = Method->getClassInterface(); 53010b57cec5SDimitry Andric if (!IDecl) 53020b57cec5SDimitry Andric return nullptr; 53030b57cec5SDimitry Andric Method = IDecl->lookupMethod(Method->getSelector(), /*isInstance=*/true, 53040b57cec5SDimitry Andric /*shallowCategoryLookup=*/false, 53050b57cec5SDimitry Andric /*followSuper=*/false); 53060b57cec5SDimitry Andric if (!Method || !Method->isPropertyAccessor()) 53070b57cec5SDimitry Andric return nullptr; 53080b57cec5SDimitry Andric if ((PDecl = Method->findPropertyDecl())) 53090b57cec5SDimitry Andric if (ObjCIvarDecl *IV = PDecl->getPropertyIvarDecl()) { 53100b57cec5SDimitry Andric // property backing ivar must belong to property's class 53110b57cec5SDimitry Andric // or be a private ivar in class's implementation. 53120b57cec5SDimitry Andric // FIXME. fix the const-ness issue. 53130b57cec5SDimitry Andric IV = const_cast<ObjCInterfaceDecl *>(IDecl)->lookupInstanceVariable( 53140b57cec5SDimitry Andric IV->getIdentifier()); 53150b57cec5SDimitry Andric return IV; 53160b57cec5SDimitry Andric } 53170b57cec5SDimitry Andric return nullptr; 53180b57cec5SDimitry Andric } 53190b57cec5SDimitry Andric 53200b57cec5SDimitry Andric namespace { 5321*0fca6ea1SDimitry Andric /// Used by SemaObjC::DiagnoseUnusedBackingIvarInAccessor to check if a property 53220b57cec5SDimitry Andric /// accessor references the backing ivar. 5323*0fca6ea1SDimitry Andric class UnusedBackingIvarChecker 5324*0fca6ea1SDimitry Andric : public RecursiveASTVisitor<UnusedBackingIvarChecker> { 53250b57cec5SDimitry Andric public: 53260b57cec5SDimitry Andric Sema &S; 53270b57cec5SDimitry Andric const ObjCMethodDecl *Method; 53280b57cec5SDimitry Andric const ObjCIvarDecl *IvarD; 53290b57cec5SDimitry Andric bool AccessedIvar; 53300b57cec5SDimitry Andric bool InvokedSelfMethod; 53310b57cec5SDimitry Andric 53320b57cec5SDimitry Andric UnusedBackingIvarChecker(Sema &S, const ObjCMethodDecl *Method, 53330b57cec5SDimitry Andric const ObjCIvarDecl *IvarD) 5334*0fca6ea1SDimitry Andric : S(S), Method(Method), IvarD(IvarD), AccessedIvar(false), 5335*0fca6ea1SDimitry Andric InvokedSelfMethod(false) { 53360b57cec5SDimitry Andric assert(IvarD); 53370b57cec5SDimitry Andric } 53380b57cec5SDimitry Andric 53390b57cec5SDimitry Andric bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 53400b57cec5SDimitry Andric if (E->getDecl() == IvarD) { 53410b57cec5SDimitry Andric AccessedIvar = true; 53420b57cec5SDimitry Andric return false; 53430b57cec5SDimitry Andric } 53440b57cec5SDimitry Andric return true; 53450b57cec5SDimitry Andric } 53460b57cec5SDimitry Andric 53470b57cec5SDimitry Andric bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 53480b57cec5SDimitry Andric if (E->getReceiverKind() == ObjCMessageExpr::Instance && 5349*0fca6ea1SDimitry Andric S.ObjC().isSelfExpr(E->getInstanceReceiver(), Method)) { 53500b57cec5SDimitry Andric InvokedSelfMethod = true; 53510b57cec5SDimitry Andric } 53520b57cec5SDimitry Andric return true; 53530b57cec5SDimitry Andric } 53540b57cec5SDimitry Andric }; 53550b57cec5SDimitry Andric } // end anonymous namespace 53560b57cec5SDimitry Andric 5357*0fca6ea1SDimitry Andric void SemaObjC::DiagnoseUnusedBackingIvarInAccessor( 5358*0fca6ea1SDimitry Andric Scope *S, const ObjCImplementationDecl *ImplD) { 53590b57cec5SDimitry Andric if (S->hasUnrecoverableErrorOccurred()) 53600b57cec5SDimitry Andric return; 53610b57cec5SDimitry Andric 53620b57cec5SDimitry Andric for (const auto *CurMethod : ImplD->instance_methods()) { 53630b57cec5SDimitry Andric unsigned DIAG = diag::warn_unused_property_backing_ivar; 53640b57cec5SDimitry Andric SourceLocation Loc = CurMethod->getLocation(); 5365*0fca6ea1SDimitry Andric if (getDiagnostics().isIgnored(DIAG, Loc)) 53660b57cec5SDimitry Andric continue; 53670b57cec5SDimitry Andric 53680b57cec5SDimitry Andric const ObjCPropertyDecl *PDecl; 53690b57cec5SDimitry Andric const ObjCIvarDecl *IV = GetIvarBackingPropertyAccessor(CurMethod, PDecl); 53700b57cec5SDimitry Andric if (!IV) 53710b57cec5SDimitry Andric continue; 53720b57cec5SDimitry Andric 5373480093f4SDimitry Andric if (CurMethod->isSynthesizedAccessorStub()) 5374480093f4SDimitry Andric continue; 5375480093f4SDimitry Andric 5376*0fca6ea1SDimitry Andric UnusedBackingIvarChecker Checker(SemaRef, CurMethod, IV); 53770b57cec5SDimitry Andric Checker.TraverseStmt(CurMethod->getBody()); 53780b57cec5SDimitry Andric if (Checker.AccessedIvar) 53790b57cec5SDimitry Andric continue; 53800b57cec5SDimitry Andric 53810b57cec5SDimitry Andric // Do not issue this warning if backing ivar is used somewhere and accessor 53820b57cec5SDimitry Andric // implementation makes a self call. This is to prevent false positive in 53830b57cec5SDimitry Andric // cases where the ivar is accessed by another method that the accessor 53840b57cec5SDimitry Andric // delegates to. 53850b57cec5SDimitry Andric if (!IV->isReferenced() || !Checker.InvokedSelfMethod) { 53860b57cec5SDimitry Andric Diag(Loc, DIAG) << IV; 53870b57cec5SDimitry Andric Diag(PDecl->getLocation(), diag::note_property_declare); 53880b57cec5SDimitry Andric } 53890b57cec5SDimitry Andric } 53900b57cec5SDimitry Andric } 5391*0fca6ea1SDimitry Andric 5392*0fca6ea1SDimitry Andric QualType SemaObjC::AdjustParameterTypeForObjCAutoRefCount( 5393*0fca6ea1SDimitry Andric QualType T, SourceLocation NameLoc, TypeSourceInfo *TSInfo) { 5394*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 5395*0fca6ea1SDimitry Andric // In ARC, infer a lifetime qualifier for appropriate parameter types. 5396*0fca6ea1SDimitry Andric if (!getLangOpts().ObjCAutoRefCount || 5397*0fca6ea1SDimitry Andric T.getObjCLifetime() != Qualifiers::OCL_None || !T->isObjCLifetimeType()) 5398*0fca6ea1SDimitry Andric return T; 5399*0fca6ea1SDimitry Andric 5400*0fca6ea1SDimitry Andric Qualifiers::ObjCLifetime Lifetime; 5401*0fca6ea1SDimitry Andric 5402*0fca6ea1SDimitry Andric // Special cases for arrays: 5403*0fca6ea1SDimitry Andric // - if it's const, use __unsafe_unretained 5404*0fca6ea1SDimitry Andric // - otherwise, it's an error 5405*0fca6ea1SDimitry Andric if (T->isArrayType()) { 5406*0fca6ea1SDimitry Andric if (!T.isConstQualified()) { 5407*0fca6ea1SDimitry Andric if (SemaRef.DelayedDiagnostics.shouldDelayDiagnostics()) 5408*0fca6ea1SDimitry Andric SemaRef.DelayedDiagnostics.add( 5409*0fca6ea1SDimitry Andric sema::DelayedDiagnostic::makeForbiddenType( 5410*0fca6ea1SDimitry Andric NameLoc, diag::err_arc_array_param_no_ownership, T, false)); 5411*0fca6ea1SDimitry Andric else 5412*0fca6ea1SDimitry Andric Diag(NameLoc, diag::err_arc_array_param_no_ownership) 5413*0fca6ea1SDimitry Andric << TSInfo->getTypeLoc().getSourceRange(); 5414*0fca6ea1SDimitry Andric } 5415*0fca6ea1SDimitry Andric Lifetime = Qualifiers::OCL_ExplicitNone; 5416*0fca6ea1SDimitry Andric } else { 5417*0fca6ea1SDimitry Andric Lifetime = T->getObjCARCImplicitLifetime(); 5418*0fca6ea1SDimitry Andric } 5419*0fca6ea1SDimitry Andric T = Context.getLifetimeQualifiedType(T, Lifetime); 5420*0fca6ea1SDimitry Andric 5421*0fca6ea1SDimitry Andric return T; 5422*0fca6ea1SDimitry Andric } 5423*0fca6ea1SDimitry Andric 5424*0fca6ea1SDimitry Andric ObjCInterfaceDecl *SemaObjC::getObjCInterfaceDecl(const IdentifierInfo *&Id, 5425*0fca6ea1SDimitry Andric SourceLocation IdLoc, 5426*0fca6ea1SDimitry Andric bool DoTypoCorrection) { 5427*0fca6ea1SDimitry Andric // The third "scope" argument is 0 since we aren't enabling lazy built-in 5428*0fca6ea1SDimitry Andric // creation from this context. 5429*0fca6ea1SDimitry Andric NamedDecl *IDecl = SemaRef.LookupSingleName(SemaRef.TUScope, Id, IdLoc, 5430*0fca6ea1SDimitry Andric Sema::LookupOrdinaryName); 5431*0fca6ea1SDimitry Andric 5432*0fca6ea1SDimitry Andric if (!IDecl && DoTypoCorrection) { 5433*0fca6ea1SDimitry Andric // Perform typo correction at the given location, but only if we 5434*0fca6ea1SDimitry Andric // find an Objective-C class name. 5435*0fca6ea1SDimitry Andric DeclFilterCCC<ObjCInterfaceDecl> CCC{}; 5436*0fca6ea1SDimitry Andric if (TypoCorrection C = SemaRef.CorrectTypo( 5437*0fca6ea1SDimitry Andric DeclarationNameInfo(Id, IdLoc), Sema::LookupOrdinaryName, 5438*0fca6ea1SDimitry Andric SemaRef.TUScope, nullptr, CCC, Sema::CTK_ErrorRecovery)) { 5439*0fca6ea1SDimitry Andric SemaRef.diagnoseTypo(C, PDiag(diag::err_undef_interface_suggest) << Id); 5440*0fca6ea1SDimitry Andric IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>(); 5441*0fca6ea1SDimitry Andric Id = IDecl->getIdentifier(); 5442*0fca6ea1SDimitry Andric } 5443*0fca6ea1SDimitry Andric } 5444*0fca6ea1SDimitry Andric ObjCInterfaceDecl *Def = dyn_cast_or_null<ObjCInterfaceDecl>(IDecl); 5445*0fca6ea1SDimitry Andric // This routine must always return a class definition, if any. 5446*0fca6ea1SDimitry Andric if (Def && Def->getDefinition()) 5447*0fca6ea1SDimitry Andric Def = Def->getDefinition(); 5448*0fca6ea1SDimitry Andric return Def; 5449*0fca6ea1SDimitry Andric } 5450*0fca6ea1SDimitry Andric 5451*0fca6ea1SDimitry Andric bool SemaObjC::inferObjCARCLifetime(ValueDecl *decl) { 5452*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 5453*0fca6ea1SDimitry Andric QualType type = decl->getType(); 5454*0fca6ea1SDimitry Andric Qualifiers::ObjCLifetime lifetime = type.getObjCLifetime(); 5455*0fca6ea1SDimitry Andric if (lifetime == Qualifiers::OCL_Autoreleasing) { 5456*0fca6ea1SDimitry Andric // Various kinds of declaration aren't allowed to be __autoreleasing. 5457*0fca6ea1SDimitry Andric unsigned kind = -1U; 5458*0fca6ea1SDimitry Andric if (VarDecl *var = dyn_cast<VarDecl>(decl)) { 5459*0fca6ea1SDimitry Andric if (var->hasAttr<BlocksAttr>()) 5460*0fca6ea1SDimitry Andric kind = 0; // __block 5461*0fca6ea1SDimitry Andric else if (!var->hasLocalStorage()) 5462*0fca6ea1SDimitry Andric kind = 1; // global 5463*0fca6ea1SDimitry Andric } else if (isa<ObjCIvarDecl>(decl)) { 5464*0fca6ea1SDimitry Andric kind = 3; // ivar 5465*0fca6ea1SDimitry Andric } else if (isa<FieldDecl>(decl)) { 5466*0fca6ea1SDimitry Andric kind = 2; // field 5467*0fca6ea1SDimitry Andric } 5468*0fca6ea1SDimitry Andric 5469*0fca6ea1SDimitry Andric if (kind != -1U) { 5470*0fca6ea1SDimitry Andric Diag(decl->getLocation(), diag::err_arc_autoreleasing_var) << kind; 5471*0fca6ea1SDimitry Andric } 5472*0fca6ea1SDimitry Andric } else if (lifetime == Qualifiers::OCL_None) { 5473*0fca6ea1SDimitry Andric // Try to infer lifetime. 5474*0fca6ea1SDimitry Andric if (!type->isObjCLifetimeType()) 5475*0fca6ea1SDimitry Andric return false; 5476*0fca6ea1SDimitry Andric 5477*0fca6ea1SDimitry Andric lifetime = type->getObjCARCImplicitLifetime(); 5478*0fca6ea1SDimitry Andric type = Context.getLifetimeQualifiedType(type, lifetime); 5479*0fca6ea1SDimitry Andric decl->setType(type); 5480*0fca6ea1SDimitry Andric } 5481*0fca6ea1SDimitry Andric 5482*0fca6ea1SDimitry Andric if (VarDecl *var = dyn_cast<VarDecl>(decl)) { 5483*0fca6ea1SDimitry Andric // Thread-local variables cannot have lifetime. 5484*0fca6ea1SDimitry Andric if (lifetime && lifetime != Qualifiers::OCL_ExplicitNone && 5485*0fca6ea1SDimitry Andric var->getTLSKind()) { 5486*0fca6ea1SDimitry Andric Diag(var->getLocation(), diag::err_arc_thread_ownership) 5487*0fca6ea1SDimitry Andric << var->getType(); 5488*0fca6ea1SDimitry Andric return true; 5489*0fca6ea1SDimitry Andric } 5490*0fca6ea1SDimitry Andric } 5491*0fca6ea1SDimitry Andric 5492*0fca6ea1SDimitry Andric return false; 5493*0fca6ea1SDimitry Andric } 5494*0fca6ea1SDimitry Andric 5495*0fca6ea1SDimitry Andric ObjCContainerDecl *SemaObjC::getObjCDeclContext() const { 5496*0fca6ea1SDimitry Andric return (dyn_cast_or_null<ObjCContainerDecl>(SemaRef.CurContext)); 5497*0fca6ea1SDimitry Andric } 5498*0fca6ea1SDimitry Andric 5499*0fca6ea1SDimitry Andric void SemaObjC::SetIvarInitializers(ObjCImplementationDecl *ObjCImplementation) { 5500*0fca6ea1SDimitry Andric if (!getLangOpts().CPlusPlus) 5501*0fca6ea1SDimitry Andric return; 5502*0fca6ea1SDimitry Andric if (ObjCInterfaceDecl *OID = ObjCImplementation->getClassInterface()) { 5503*0fca6ea1SDimitry Andric ASTContext &Context = getASTContext(); 5504*0fca6ea1SDimitry Andric SmallVector<ObjCIvarDecl *, 8> ivars; 5505*0fca6ea1SDimitry Andric CollectIvarsToConstructOrDestruct(OID, ivars); 5506*0fca6ea1SDimitry Andric if (ivars.empty()) 5507*0fca6ea1SDimitry Andric return; 5508*0fca6ea1SDimitry Andric SmallVector<CXXCtorInitializer *, 32> AllToInit; 5509*0fca6ea1SDimitry Andric for (unsigned i = 0; i < ivars.size(); i++) { 5510*0fca6ea1SDimitry Andric FieldDecl *Field = ivars[i]; 5511*0fca6ea1SDimitry Andric if (Field->isInvalidDecl()) 5512*0fca6ea1SDimitry Andric continue; 5513*0fca6ea1SDimitry Andric 5514*0fca6ea1SDimitry Andric CXXCtorInitializer *Member; 5515*0fca6ea1SDimitry Andric InitializedEntity InitEntity = InitializedEntity::InitializeMember(Field); 5516*0fca6ea1SDimitry Andric InitializationKind InitKind = 5517*0fca6ea1SDimitry Andric InitializationKind::CreateDefault(ObjCImplementation->getLocation()); 5518*0fca6ea1SDimitry Andric 5519*0fca6ea1SDimitry Andric InitializationSequence InitSeq(SemaRef, InitEntity, InitKind, 5520*0fca6ea1SDimitry Andric std::nullopt); 5521*0fca6ea1SDimitry Andric ExprResult MemberInit = 5522*0fca6ea1SDimitry Andric InitSeq.Perform(SemaRef, InitEntity, InitKind, std::nullopt); 5523*0fca6ea1SDimitry Andric MemberInit = SemaRef.MaybeCreateExprWithCleanups(MemberInit); 5524*0fca6ea1SDimitry Andric // Note, MemberInit could actually come back empty if no initialization 5525*0fca6ea1SDimitry Andric // is required (e.g., because it would call a trivial default constructor) 5526*0fca6ea1SDimitry Andric if (!MemberInit.get() || MemberInit.isInvalid()) 5527*0fca6ea1SDimitry Andric continue; 5528*0fca6ea1SDimitry Andric 5529*0fca6ea1SDimitry Andric Member = new (Context) 5530*0fca6ea1SDimitry Andric CXXCtorInitializer(Context, Field, SourceLocation(), SourceLocation(), 5531*0fca6ea1SDimitry Andric MemberInit.getAs<Expr>(), SourceLocation()); 5532*0fca6ea1SDimitry Andric AllToInit.push_back(Member); 5533*0fca6ea1SDimitry Andric 5534*0fca6ea1SDimitry Andric // Be sure that the destructor is accessible and is marked as referenced. 5535*0fca6ea1SDimitry Andric if (const RecordType *RecordTy = 5536*0fca6ea1SDimitry Andric Context.getBaseElementType(Field->getType()) 5537*0fca6ea1SDimitry Andric ->getAs<RecordType>()) { 5538*0fca6ea1SDimitry Andric CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl()); 5539*0fca6ea1SDimitry Andric if (CXXDestructorDecl *Destructor = SemaRef.LookupDestructor(RD)) { 5540*0fca6ea1SDimitry Andric SemaRef.MarkFunctionReferenced(Field->getLocation(), Destructor); 5541*0fca6ea1SDimitry Andric SemaRef.CheckDestructorAccess( 5542*0fca6ea1SDimitry Andric Field->getLocation(), Destructor, 5543*0fca6ea1SDimitry Andric PDiag(diag::err_access_dtor_ivar) 5544*0fca6ea1SDimitry Andric << Context.getBaseElementType(Field->getType())); 5545*0fca6ea1SDimitry Andric } 5546*0fca6ea1SDimitry Andric } 5547*0fca6ea1SDimitry Andric } 5548*0fca6ea1SDimitry Andric ObjCImplementation->setIvarInitializers(Context, AllToInit.data(), 5549*0fca6ea1SDimitry Andric AllToInit.size()); 5550*0fca6ea1SDimitry Andric } 5551*0fca6ea1SDimitry Andric } 5552*0fca6ea1SDimitry Andric 5553*0fca6ea1SDimitry Andric /// TranslateIvarVisibility - Translate visibility from a token ID to an 5554*0fca6ea1SDimitry Andric /// AST enum value. 5555*0fca6ea1SDimitry Andric static ObjCIvarDecl::AccessControl 5556*0fca6ea1SDimitry Andric TranslateIvarVisibility(tok::ObjCKeywordKind ivarVisibility) { 5557*0fca6ea1SDimitry Andric switch (ivarVisibility) { 5558*0fca6ea1SDimitry Andric default: 5559*0fca6ea1SDimitry Andric llvm_unreachable("Unknown visitibility kind"); 5560*0fca6ea1SDimitry Andric case tok::objc_private: 5561*0fca6ea1SDimitry Andric return ObjCIvarDecl::Private; 5562*0fca6ea1SDimitry Andric case tok::objc_public: 5563*0fca6ea1SDimitry Andric return ObjCIvarDecl::Public; 5564*0fca6ea1SDimitry Andric case tok::objc_protected: 5565*0fca6ea1SDimitry Andric return ObjCIvarDecl::Protected; 5566*0fca6ea1SDimitry Andric case tok::objc_package: 5567*0fca6ea1SDimitry Andric return ObjCIvarDecl::Package; 5568*0fca6ea1SDimitry Andric } 5569*0fca6ea1SDimitry Andric } 5570*0fca6ea1SDimitry Andric 5571*0fca6ea1SDimitry Andric /// ActOnIvar - Each ivar field of an objective-c class is passed into this 5572*0fca6ea1SDimitry Andric /// in order to create an IvarDecl object for it. 5573*0fca6ea1SDimitry Andric Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, 5574*0fca6ea1SDimitry Andric Expr *BitWidth, tok::ObjCKeywordKind Visibility) { 5575*0fca6ea1SDimitry Andric 5576*0fca6ea1SDimitry Andric const IdentifierInfo *II = D.getIdentifier(); 5577*0fca6ea1SDimitry Andric SourceLocation Loc = DeclStart; 5578*0fca6ea1SDimitry Andric if (II) 5579*0fca6ea1SDimitry Andric Loc = D.getIdentifierLoc(); 5580*0fca6ea1SDimitry Andric 5581*0fca6ea1SDimitry Andric // FIXME: Unnamed fields can be handled in various different ways, for 5582*0fca6ea1SDimitry Andric // example, unnamed unions inject all members into the struct namespace! 5583*0fca6ea1SDimitry Andric 5584*0fca6ea1SDimitry Andric TypeSourceInfo *TInfo = SemaRef.GetTypeForDeclarator(D); 5585*0fca6ea1SDimitry Andric QualType T = TInfo->getType(); 5586*0fca6ea1SDimitry Andric 5587*0fca6ea1SDimitry Andric if (BitWidth) { 5588*0fca6ea1SDimitry Andric // 6.7.2.1p3, 6.7.2.1p4 5589*0fca6ea1SDimitry Andric BitWidth = 5590*0fca6ea1SDimitry Andric SemaRef.VerifyBitField(Loc, II, T, /*IsMsStruct*/ false, BitWidth) 5591*0fca6ea1SDimitry Andric .get(); 5592*0fca6ea1SDimitry Andric if (!BitWidth) 5593*0fca6ea1SDimitry Andric D.setInvalidType(); 5594*0fca6ea1SDimitry Andric } else { 5595*0fca6ea1SDimitry Andric // Not a bitfield. 5596*0fca6ea1SDimitry Andric 5597*0fca6ea1SDimitry Andric // validate II. 5598*0fca6ea1SDimitry Andric } 5599*0fca6ea1SDimitry Andric if (T->isReferenceType()) { 5600*0fca6ea1SDimitry Andric Diag(Loc, diag::err_ivar_reference_type); 5601*0fca6ea1SDimitry Andric D.setInvalidType(); 5602*0fca6ea1SDimitry Andric } 5603*0fca6ea1SDimitry Andric // C99 6.7.2.1p8: A member of a structure or union may have any type other 5604*0fca6ea1SDimitry Andric // than a variably modified type. 5605*0fca6ea1SDimitry Andric else if (T->isVariablyModifiedType()) { 5606*0fca6ea1SDimitry Andric if (!SemaRef.tryToFixVariablyModifiedVarType( 5607*0fca6ea1SDimitry Andric TInfo, T, Loc, diag::err_typecheck_ivar_variable_size)) 5608*0fca6ea1SDimitry Andric D.setInvalidType(); 5609*0fca6ea1SDimitry Andric } 5610*0fca6ea1SDimitry Andric 5611*0fca6ea1SDimitry Andric // Get the visibility (access control) for this ivar. 5612*0fca6ea1SDimitry Andric ObjCIvarDecl::AccessControl ac = Visibility != tok::objc_not_keyword 5613*0fca6ea1SDimitry Andric ? TranslateIvarVisibility(Visibility) 5614*0fca6ea1SDimitry Andric : ObjCIvarDecl::None; 5615*0fca6ea1SDimitry Andric // Must set ivar's DeclContext to its enclosing interface. 5616*0fca6ea1SDimitry Andric ObjCContainerDecl *EnclosingDecl = 5617*0fca6ea1SDimitry Andric cast<ObjCContainerDecl>(SemaRef.CurContext); 5618*0fca6ea1SDimitry Andric if (!EnclosingDecl || EnclosingDecl->isInvalidDecl()) 5619*0fca6ea1SDimitry Andric return nullptr; 5620*0fca6ea1SDimitry Andric ObjCContainerDecl *EnclosingContext; 5621*0fca6ea1SDimitry Andric if (ObjCImplementationDecl *IMPDecl = 5622*0fca6ea1SDimitry Andric dyn_cast<ObjCImplementationDecl>(EnclosingDecl)) { 5623*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isFragile()) { 5624*0fca6ea1SDimitry Andric // Case of ivar declared in an implementation. Context is that of its 5625*0fca6ea1SDimitry Andric // class. 5626*0fca6ea1SDimitry Andric EnclosingContext = IMPDecl->getClassInterface(); 5627*0fca6ea1SDimitry Andric assert(EnclosingContext && "Implementation has no class interface!"); 5628*0fca6ea1SDimitry Andric } else 5629*0fca6ea1SDimitry Andric EnclosingContext = EnclosingDecl; 5630*0fca6ea1SDimitry Andric } else { 5631*0fca6ea1SDimitry Andric if (ObjCCategoryDecl *CDecl = dyn_cast<ObjCCategoryDecl>(EnclosingDecl)) { 5632*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isFragile() || !CDecl->IsClassExtension()) { 5633*0fca6ea1SDimitry Andric Diag(Loc, diag::err_misplaced_ivar) << CDecl->IsClassExtension(); 5634*0fca6ea1SDimitry Andric return nullptr; 5635*0fca6ea1SDimitry Andric } 5636*0fca6ea1SDimitry Andric } 5637*0fca6ea1SDimitry Andric EnclosingContext = EnclosingDecl; 5638*0fca6ea1SDimitry Andric } 5639*0fca6ea1SDimitry Andric 5640*0fca6ea1SDimitry Andric // Construct the decl. 5641*0fca6ea1SDimitry Andric ObjCIvarDecl *NewID = 5642*0fca6ea1SDimitry Andric ObjCIvarDecl::Create(getASTContext(), EnclosingContext, DeclStart, Loc, 5643*0fca6ea1SDimitry Andric II, T, TInfo, ac, BitWidth); 5644*0fca6ea1SDimitry Andric 5645*0fca6ea1SDimitry Andric if (T->containsErrors()) 5646*0fca6ea1SDimitry Andric NewID->setInvalidDecl(); 5647*0fca6ea1SDimitry Andric 5648*0fca6ea1SDimitry Andric if (II) { 5649*0fca6ea1SDimitry Andric NamedDecl *PrevDecl = 5650*0fca6ea1SDimitry Andric SemaRef.LookupSingleName(S, II, Loc, Sema::LookupMemberName, 5651*0fca6ea1SDimitry Andric RedeclarationKind::ForVisibleRedeclaration); 5652*0fca6ea1SDimitry Andric if (PrevDecl && SemaRef.isDeclInScope(PrevDecl, EnclosingContext, S) && 5653*0fca6ea1SDimitry Andric !isa<TagDecl>(PrevDecl)) { 5654*0fca6ea1SDimitry Andric Diag(Loc, diag::err_duplicate_member) << II; 5655*0fca6ea1SDimitry Andric Diag(PrevDecl->getLocation(), diag::note_previous_declaration); 5656*0fca6ea1SDimitry Andric NewID->setInvalidDecl(); 5657*0fca6ea1SDimitry Andric } 5658*0fca6ea1SDimitry Andric } 5659*0fca6ea1SDimitry Andric 5660*0fca6ea1SDimitry Andric // Process attributes attached to the ivar. 5661*0fca6ea1SDimitry Andric SemaRef.ProcessDeclAttributes(S, NewID, D); 5662*0fca6ea1SDimitry Andric 5663*0fca6ea1SDimitry Andric if (D.isInvalidType()) 5664*0fca6ea1SDimitry Andric NewID->setInvalidDecl(); 5665*0fca6ea1SDimitry Andric 5666*0fca6ea1SDimitry Andric // In ARC, infer 'retaining' for ivars of retainable type. 5667*0fca6ea1SDimitry Andric if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(NewID)) 5668*0fca6ea1SDimitry Andric NewID->setInvalidDecl(); 5669*0fca6ea1SDimitry Andric 5670*0fca6ea1SDimitry Andric if (D.getDeclSpec().isModulePrivateSpecified()) 5671*0fca6ea1SDimitry Andric NewID->setModulePrivate(); 5672*0fca6ea1SDimitry Andric 5673*0fca6ea1SDimitry Andric if (II) { 5674*0fca6ea1SDimitry Andric // FIXME: When interfaces are DeclContexts, we'll need to add 5675*0fca6ea1SDimitry Andric // these to the interface. 5676*0fca6ea1SDimitry Andric S->AddDecl(NewID); 5677*0fca6ea1SDimitry Andric SemaRef.IdResolver.AddDecl(NewID); 5678*0fca6ea1SDimitry Andric } 5679*0fca6ea1SDimitry Andric 5680*0fca6ea1SDimitry Andric if (getLangOpts().ObjCRuntime.isNonFragile() && !NewID->isInvalidDecl() && 5681*0fca6ea1SDimitry Andric isa<ObjCInterfaceDecl>(EnclosingDecl)) 5682*0fca6ea1SDimitry Andric Diag(Loc, diag::warn_ivars_in_interface); 5683*0fca6ea1SDimitry Andric 5684*0fca6ea1SDimitry Andric return NewID; 5685*0fca6ea1SDimitry Andric } 5686