diff options
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 121 |
1 files changed, 69 insertions, 52 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 3746bdad0358..e629837eb71d 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -1,9 +1,8 @@ //===--- SemaDeclObjC.cpp - Semantic Analysis for ObjC Declarations -------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -360,6 +359,7 @@ HasExplicitOwnershipAttr(Sema &S, ParmVarDecl *Param) { /// ActOnStartOfObjCMethodDef - This routine sets up parameters; invisible /// and user declared, in the method definition's AST. void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { + ImplicitlyRetainedSelfLocs.clear(); assert((getCurMethodDecl() == nullptr) && "Methodparsing confused"); ObjCMethodDecl *MDecl = dyn_cast_or_null<ObjCMethodDecl>(D); @@ -500,7 +500,7 @@ namespace { // Callback to only accept typo corrections that are Objective-C classes. // If an ObjCInterfaceDecl* is given to the constructor, then the validation // function will reject corrections to that class. -class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { +class ObjCInterfaceValidatorCCC final : public CorrectionCandidateCallback { public: ObjCInterfaceValidatorCCC() : CurrentIDecl(nullptr) {} explicit ObjCInterfaceValidatorCCC(ObjCInterfaceDecl *IDecl) @@ -511,6 +511,10 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { return ID && !declaresSameEntity(ID, CurrentIDecl); } + std::unique_ptr<CorrectionCandidateCallback> clone() override { + return llvm::make_unique<ObjCInterfaceValidatorCCC>(*this); + } + private: ObjCInterfaceDecl *CurrentIDecl; }; @@ -550,11 +554,10 @@ ActOnSuperClassOfClassInterface(Scope *S, if (!PrevDecl) { // Try to correct for a typo in the superclass name without correcting // to the class we're defining. + ObjCInterfaceValidatorCCC CCC(IDecl); if (TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(SuperName, SuperLoc), - LookupOrdinaryName, TUScope, - nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(IDecl), - CTK_ErrorRecovery)) { + DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, + TUScope, nullptr, CCC, CTK_ErrorRecovery)) { diagnoseTypo(Corrected, PDiag(diag::err_undef_superclass_suggest) << SuperName << ClassName); PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>(); @@ -1293,11 +1296,10 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, for (const IdentifierLocPair &Pair : ProtocolId) { ObjCProtocolDecl *PDecl = LookupProtocol(Pair.first, Pair.second); if (!PDecl) { + DeclFilterCCC<ObjCProtocolDecl> CCC{}; TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(Pair.first, Pair.second), - LookupObjCProtocolName, TUScope, nullptr, - llvm::make_unique<DeclFilterCCC<ObjCProtocolDecl>>(), - CTK_ErrorRecovery); + DeclarationNameInfo(Pair.first, Pair.second), LookupObjCProtocolName, + TUScope, nullptr, CCC, CTK_ErrorRecovery); if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) diagnoseTypo(Corrected, PDiag(diag::err_undeclared_protocol_suggest) << Pair.first); @@ -1335,7 +1337,8 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, namespace { // Callback to only accept typo corrections that are either // Objective-C protocols or valid Objective-C type arguments. -class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback { +class ObjCTypeArgOrProtocolValidatorCCC final + : public CorrectionCandidateCallback { ASTContext &Context; Sema::LookupNameKind LookupKind; public: @@ -1382,6 +1385,10 @@ class ObjCTypeArgOrProtocolValidatorCCC : public CorrectionCandidateCallback { return false; } + + std::unique_ptr<CorrectionCandidateCallback> clone() override { + return llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(*this); + } }; } // end anonymous namespace @@ -1580,7 +1587,7 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // add the '*'. if (type->getAs<ObjCInterfaceType>()) { SourceLocation starLoc = getLocForEndOfToken(loc); - D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, + D.AddTypeInfo(DeclaratorChunk::getPointer(/*TypeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), @@ -1671,12 +1678,10 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( } // Perform typo correction on the name. - TypoCorrection corrected = CorrectTypo( - DeclarationNameInfo(identifiers[i], identifierLocs[i]), lookupKind, S, - nullptr, - llvm::make_unique<ObjCTypeArgOrProtocolValidatorCCC>(Context, - lookupKind), - CTK_ErrorRecovery); + ObjCTypeArgOrProtocolValidatorCCC CCC(Context, lookupKind); + TypoCorrection corrected = + CorrectTypo(DeclarationNameInfo(identifiers[i], identifierLocs[i]), + lookupKind, S, nullptr, CCC, CTK_ErrorRecovery); if (corrected) { // Did we find a protocol? if (auto proto = corrected.getCorrectionDeclAs<ObjCProtocolDecl>()) { @@ -1888,7 +1893,8 @@ Decl *Sema::ActOnStartCategoryInterface( Decl *Sema::ActOnStartCategoryImplementation( SourceLocation AtCatImplLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, - IdentifierInfo *CatName, SourceLocation CatLoc) { + IdentifierInfo *CatName, SourceLocation CatLoc, + const ParsedAttributesView &Attrs) { ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); ObjCCategoryDecl *CatIDecl = nullptr; if (IDecl && IDecl->hasDefinition()) { @@ -1916,6 +1922,9 @@ Decl *Sema::ActOnStartCategoryImplementation( CDecl->setInvalidDecl(); } + ProcessDeclAttributeList(TUScope, CDecl, Attrs); + AddPragmaAttributes(TUScope, CDecl); + // FIXME: PushOnScopeChains? CurContext->addDecl(CDecl); @@ -1951,7 +1960,8 @@ Decl *Sema::ActOnStartClassImplementation( SourceLocation AtClassImplLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, IdentifierInfo *SuperClassname, - SourceLocation SuperClassLoc) { + SourceLocation SuperClassLoc, + const ParsedAttributesView &Attrs) { ObjCInterfaceDecl *IDecl = nullptr; // Check for another declaration kind with the same name. NamedDecl *PrevDecl @@ -1968,9 +1978,10 @@ Decl *Sema::ActOnStartClassImplementation( } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. - TypoCorrection Corrected = CorrectTypo( - DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, - nullptr, llvm::make_unique<ObjCInterfaceValidatorCCC>(), CTK_NonError); + ObjCInterfaceValidatorCCC CCC{}; + TypoCorrection Corrected = + CorrectTypo(DeclarationNameInfo(ClassName, ClassLoc), + LookupOrdinaryName, TUScope, nullptr, CCC, CTK_NonError); if (Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>()) { // Suggest the (potentially) correct interface name. Don't provide a // code-modification hint or use the typo name for recovery, because @@ -2044,6 +2055,9 @@ Decl *Sema::ActOnStartClassImplementation( ObjCImplementationDecl::Create(Context, CurContext, IDecl, SDecl, ClassLoc, AtClassImplLoc, SuperClassLoc); + ProcessDeclAttributeList(TUScope, IMPDecl, Attrs); + AddPragmaAttributes(TUScope, IMPDecl); + if (CheckObjCDeclScope(IMPDecl)) return ActOnObjCContainerStartDefinition(IMPDecl); @@ -4047,6 +4061,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, } } + if (IDecl->hasAttr<ObjCClassStubAttr>()) + Diag(IC->getLocation(), diag::err_implementation_of_class_stub); + if (LangOpts.ObjCRuntime.isNonFragile()) { while (IDecl->getSuperClass()) { DiagnoseDuplicateIvars(IDecl, IDecl->getSuperClass()); @@ -4075,6 +4092,10 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, Diag(Super->getLocation(), diag::note_class_declared); } } + + if (IntfDecl->hasAttr<ObjCClassStubAttr>() && + !IntfDecl->hasAttr<ObjCSubclassingRestrictedAttr>()) + Diag(IntfDecl->getLocation(), diag::err_class_stub_subclassing_mismatch); } DiagnoseVariableSizedIvars(*this, OCD); if (isInterfaceDeclKind) { @@ -4152,13 +4173,12 @@ namespace { /// overrides. class OverrideSearch { public: - Sema &S; - ObjCMethodDecl *Method; + const ObjCMethodDecl *Method; llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden; bool Recursive; public: - OverrideSearch(Sema &S, ObjCMethodDecl *method) : S(S), Method(method) { + OverrideSearch(Sema &S, const ObjCMethodDecl *method) : Method(method) { Selector selector = method->getSelector(); // Bypass this search if we've never seen an instance/class method @@ -4172,19 +4192,20 @@ public: if (it == S.MethodPool.end()) return; } - ObjCMethodList &list = + const ObjCMethodList &list = method->isInstanceMethod() ? it->second.first : it->second.second; if (!list.getMethod()) return; - ObjCContainerDecl *container + const ObjCContainerDecl *container = cast<ObjCContainerDecl>(method->getDeclContext()); // Prevent the search from reaching this container again. This is // important with categories, which override methods from the // interface and each other. - if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(container)) { + if (const ObjCCategoryDecl *Category = + dyn_cast<ObjCCategoryDecl>(container)) { searchFromContainer(container); - if (ObjCInterfaceDecl *Interface = Category->getClassInterface()) + if (const ObjCInterfaceDecl *Interface = Category->getClassInterface()) searchFromContainer(Interface); } else { searchFromContainer(container); @@ -4196,7 +4217,7 @@ public: iterator end() const { return Overridden.end(); } private: - void searchFromContainer(ObjCContainerDecl *container) { + void searchFromContainer(const ObjCContainerDecl *container) { if (container->isInvalidDecl()) return; switch (container->getDeclKind()) { @@ -4212,7 +4233,7 @@ private: } } - void searchFrom(ObjCProtocolDecl *protocol) { + void searchFrom(const ObjCProtocolDecl *protocol) { if (!protocol->hasDefinition()) return; @@ -4221,14 +4242,14 @@ private: search(protocol->getReferencedProtocols()); } - void searchFrom(ObjCCategoryDecl *category) { + void searchFrom(const ObjCCategoryDecl *category) { // A method in a category declaration overrides declarations from // the main class and from protocols the category references. // The main class is handled in the constructor. search(category->getReferencedProtocols()); } - void searchFrom(ObjCCategoryImplDecl *impl) { + void searchFrom(const ObjCCategoryImplDecl *impl) { // A method in a category definition that has a category // declaration overrides declarations from the category // declaration. @@ -4238,12 +4259,12 @@ private: search(Interface); // Otherwise it overrides declarations from the class. - } else if (ObjCInterfaceDecl *Interface = impl->getClassInterface()) { + } else if (const auto *Interface = impl->getClassInterface()) { search(Interface); } } - void searchFrom(ObjCInterfaceDecl *iface) { + void searchFrom(const ObjCInterfaceDecl *iface) { // A method in a class declaration overrides declarations from if (!iface->hasDefinition()) return; @@ -4260,20 +4281,19 @@ private: search(iface->getReferencedProtocols()); } - void searchFrom(ObjCImplementationDecl *impl) { + void searchFrom(const ObjCImplementationDecl *impl) { // A method in a class implementation overrides declarations from // the class interface. - if (ObjCInterfaceDecl *Interface = impl->getClassInterface()) + if (const auto *Interface = impl->getClassInterface()) search(Interface); } void search(const ObjCProtocolList &protocols) { - for (ObjCProtocolList::iterator i = protocols.begin(), e = protocols.end(); - i != e; ++i) - search(*i); + for (const auto *Proto : protocols) + search(Proto); } - void search(ObjCContainerDecl *container) { + void search(const ObjCContainerDecl *container) { // Check for a method in this container which matches this selector. ObjCMethodDecl *meth = container->getMethod(Method->getSelector(), Method->isInstanceMethod(), @@ -4299,6 +4319,8 @@ private: void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, ObjCInterfaceDecl *CurrentClass, ResultTypeCompatibilityKind RTC) { + if (!ObjCMethod) + return; // Search for overridden methods and merge information down from them. OverrideSearch overrides(*this, ObjCMethod); // Keep track if the method overrides any method in the class's base classes, @@ -4307,10 +4329,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, // For this info, a method in an implementation is not considered as // overriding the same method in the interface or its categories. bool hasOverriddenMethodsInBaseOrProtocol = false; - for (OverrideSearch::iterator - i = overrides.begin(), e = overrides.end(); i != e; ++i) { - ObjCMethodDecl *overridden = *i; - + for (ObjCMethodDecl *overridden : overrides) { if (!hasOverriddenMethodsInBaseOrProtocol) { if (isa<ObjCProtocolDecl>(overridden->getDeclContext()) || CurrentClass != overridden->getClassInterface() || @@ -4337,9 +4356,7 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, if (CategCount > 1 || !isa<ObjCCategoryImplDecl>(overridden->getDeclContext())) { OverrideSearch overrides(*this, overridden); - for (OverrideSearch::iterator - OI= overrides.begin(), OE= overrides.end(); OI!=OE; ++OI) { - ObjCMethodDecl *SuperOverridden = *OI; + for (ObjCMethodDecl *SuperOverridden : overrides) { if (isa<ObjCProtocolDecl>(SuperOverridden->getDeclContext()) || CurrentClass != SuperOverridden->getClassInterface()) { hasOverriddenMethodsInBaseOrProtocol = true; |