diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Sema/SemaDeclObjC.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
download | src-486754660bb926339aefcf012a3f848592babb8b.tar.gz src-486754660bb926339aefcf012a3f848592babb8b.zip |
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
Notes
Notes:
svn path=/vendor/clang/dist/; revision=336815
svn path=/vendor/clang/clang-trunk-r338150/; revision=336816; tag=vendor/clang/clang-trunk-r338150
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 211 |
1 files changed, 110 insertions, 101 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index abbdc9574b8c..e1b033ea8282 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -156,23 +156,23 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, Diag(Overridden->getLocation(), diag::note_related_result_type_overridden); } - if (getLangOpts().ObjCAutoRefCount) { - Diags.setSeverity(diag::warn_nsreturns_retained_attribute_mismatch, - diag::Severity::Error, SourceLocation()); - Diags.setSeverity(diag::warn_nsconsumed_attribute_mismatch, - diag::Severity::Error, SourceLocation()); - } if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() != Overridden->hasAttr<NSReturnsRetainedAttr>())) { Diag(NewMethod->getLocation(), - diag::warn_nsreturns_retained_attribute_mismatch) << 1; + getLangOpts().ObjCAutoRefCount + ? diag::err_nsreturns_retained_attribute_mismatch + : diag::warn_nsreturns_retained_attribute_mismatch) + << 1; Diag(Overridden->getLocation(), diag::note_previous_decl) << "method"; } if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() != Overridden->hasAttr<NSReturnsNotRetainedAttr>())) { Diag(NewMethod->getLocation(), - diag::warn_nsreturns_retained_attribute_mismatch) << 0; + getLangOpts().ObjCAutoRefCount + ? diag::err_nsreturns_retained_attribute_mismatch + : diag::warn_nsreturns_retained_attribute_mismatch) + << 0; Diag(Overridden->getLocation(), diag::note_previous_decl) << "method"; } @@ -185,7 +185,10 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, ParmVarDecl *newDecl = (*ni); if (newDecl->hasAttr<NSConsumedAttr>() != oldDecl->hasAttr<NSConsumedAttr>()) { - Diag(newDecl->getLocation(), diag::warn_nsconsumed_attribute_mismatch); + Diag(newDecl->getLocation(), + getLangOpts().ObjCAutoRefCount + ? diag::err_nsconsumed_attribute_mismatch + : diag::warn_nsconsumed_attribute_mismatch); Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter"; } @@ -199,7 +202,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, } } -/// \brief Check a method declaration for compatibility with the Objective-C +/// Check a method declaration for compatibility with the Objective-C /// ARC conventions. bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) { ObjCMethodFamily family = method->getMethodFamily(); @@ -263,12 +266,20 @@ static void DiagnoseObjCImplementedDeprecations(Sema &S, const NamedDecl *ND, if (!ND) return; bool IsCategory = false; - AvailabilityResult Availability = ND->getAvailability(); + StringRef RealizedPlatform; + AvailabilityResult Availability = ND->getAvailability( + /*Message=*/nullptr, /*EnclosingVersion=*/VersionTuple(), + &RealizedPlatform); if (Availability != AR_Deprecated) { if (isa<ObjCMethodDecl>(ND)) { if (Availability != AR_Unavailable) return; - // Warn about implementing unavailable methods. + if (RealizedPlatform.empty()) + RealizedPlatform = S.Context.getTargetInfo().getPlatformName(); + // Warn about implementing unavailable methods, unless the unavailable + // is for an app extension. + if (RealizedPlatform.endswith("_app_extension")) + return; S.Diag(ImplLoc, diag::warn_unavailable_def); S.Diag(ND->getLocation(), diag::note_method_declared_at) << ND->getDeclName(); @@ -338,6 +349,13 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { if (!MDecl) return; + QualType ResultType = MDecl->getReturnType(); + if (!ResultType->isDependentType() && !ResultType->isVoidType() && + !MDecl->isInvalidDecl() && + RequireCompleteType(MDecl->getLocation(), ResultType, + diag::err_func_def_incomplete_result)) + MDecl->setInvalidDecl(); + // Allow all of Sema to see that we are entering a method definition. PushDeclContext(FnBodyScope, MDecl); PushFunctionScope(); @@ -930,16 +948,14 @@ static bool checkTypeParamListConsistency(Sema &S, return false; } -Decl *Sema:: -ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef<ParsedType> SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, AttributeList *AttrList) { +Decl *Sema::ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. @@ -1024,9 +1040,8 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, IDecl->setInvalidDecl(); } } - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + ProcessDeclAttributeList(TUScope, IDecl, AttrList); AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); @@ -1165,15 +1180,11 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( return res; } -Decl * -Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); @@ -1192,6 +1203,11 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PDecl = ObjCProtocolDecl::Create(Context, CurContext, ProtocolName, ProtocolLoc, AtProtoInterfaceLoc, /*PrevDecl=*/nullptr); + + // If we are using modules, add the decl to the context in order to + // serialize something meaningful. + if (getLangOpts().Modules) + PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } else { if (PrevDecl) { @@ -1211,9 +1227,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } - - if (AttrList) - ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + ProcessDeclAttributeList(TUScope, PDecl, AttrList); AddPragmaAttributes(TUScope, PDecl); // Merge attributes from previous declarations. @@ -1538,20 +1553,18 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( DS.SetRangeEnd(loc); // Form the declarator. - Declarator D(DS, Declarator::TypeNameContext); + Declarator D(DS, DeclaratorContext::TypeNameContext); // If we have a typedef of an Objective-C class type that is missing a '*', // add the '*'. if (type->getAs<ObjCInterfaceType>()) { SourceLocation starLoc = getLocForEndOfToken(loc); - ParsedAttributes parsedAttrs(attrFactory); D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation()), - parsedAttrs, starLoc); // Diagnose the missing '*'. @@ -1729,7 +1742,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ArrayRef<IdentifierLocPair> IdentList, - AttributeList *attrList) { + const ParsedAttributesView &attrList) { SmallVector<Decl *, 8> DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; @@ -1742,9 +1755,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, PushOnScopeChains(PDecl, TUScope); CheckObjCDeclScope(PDecl); - - if (attrList) - ProcessDeclAttributeList(TUScope, PDecl, attrList); + + ProcessDeclAttributeList(TUScope, PDecl, attrList); AddPragmaAttributes(TUScope, PDecl); if (PrevDecl) @@ -1756,17 +1768,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, return BuildDeclaratorGroup(DeclsInGroup); } -Decl *Sema:: -ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); @@ -1832,6 +1840,12 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, // FIXME: PushOnScopeChains? CurContext->addDecl(CDecl); + // Process the attributes before looking at protocols to ensure that the + // availability attribute is attached to the category to provide availability + // checking for protocol uses. + ProcessDeclAttributeList(TUScope, CDecl, AttrList); + AddPragmaAttributes(TUScope, CDecl); + if (NumProtoRefs) { diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs); @@ -1843,10 +1857,6 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, NumProtoRefs, Context); } - if (AttrList) - ProcessDeclAttributeList(TUScope, CDecl, AttrList); - AddPragmaAttributes(TUScope, CDecl); - CheckObjCDeclScope(CDecl); return ActOnObjCContainerStartDefinition(CDecl); } @@ -2162,17 +2172,9 @@ static void WarnUndefinedMethod(Sema &S, SourceLocation ImpLoc, unsigned DiagID, NamedDecl *NeededFor = nullptr) { // No point warning no definition of method which is 'unavailable'. - switch (method->getAvailability()) { - case AR_Available: - case AR_Deprecated: - break; - - // Don't warn about unavailable or not-yet-introduced methods. - case AR_NotYetIntroduced: - case AR_Unavailable: + if (method->getAvailability() == AR_Unavailable) return; - } - + // FIXME: For now ignore 'IncompleteImpl'. // Previously we grouped all unimplemented methods under a single // warning, but some users strongly voiced that they would prefer @@ -2717,7 +2719,7 @@ static void CheckProtocolMethodDefs(Sema &S, // This is because method will be implemented in the primary class // or one of its super class implementation. - // Ugly, but necessary. Method declared in protcol might have + // Ugly, but necessary. Method declared in protocol might have // have been synthesized due to a property declared in the class which // uses the protocol. if (ObjCMethodDecl *MethodInClass = @@ -3345,7 +3347,7 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, Previous->setNext(new (Mem) ObjCMethodList(Method)); } -/// \brief Read the contents of the method pool for a given selector from +/// Read the contents of the method pool for a given selector from /// external storage. void Sema::ReadMethodPool(Selector Sel) { assert(ExternalSource && "We need an external AST source"); @@ -3427,7 +3429,7 @@ static bool FilterMethodsByTypeBound(ObjCMethodDecl *Method, MethodInterface->isSuperClassOf(BoundInterface) || BoundInterface->isSuperClassOf(MethodInterface); } - llvm_unreachable("unknow method context"); + llvm_unreachable("unknown method context"); } /// We first select the type of the method: Instance or Factory, then collect @@ -3859,9 +3861,9 @@ Decl *Sema::ActOnAtEnd(Scope *S, SourceRange AtEnd, ArrayRef<Decl *> allMethods, assert(AtEnd.isValid() && "Invalid location for '@end'"); - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - Decl *ClassDecl = cast<Decl>(OCD); - + auto *OCD = cast<ObjCContainerDecl>(CurContext); + Decl *ClassDecl = OCD; + bool isInterfaceDeclKind = isa<ObjCInterfaceDecl>(ClassDecl) || isa<ObjCCategoryDecl>(ClassDecl) || isa<ObjCProtocolDecl>(ClassDecl); @@ -4084,7 +4086,7 @@ CvtQTToAstBitMask(ObjCDeclSpec::ObjCDeclQualifier PQTVal) { return (Decl::ObjCDeclQualifier) (unsigned) PQTVal; } -/// \brief Check whether the declared result type of the given Objective-C +/// Check whether the declared result type of the given Objective-C /// method declaration is compatible with the method's class. /// static Sema::ResultTypeCompatibilityKind @@ -4130,7 +4132,7 @@ class OverrideSearch { public: Sema &S; ObjCMethodDecl *Method; - llvm::SmallPtrSet<ObjCMethodDecl*, 4> Overridden; + llvm::SmallSetVector<ObjCMethodDecl*, 4> Overridden; bool Recursive; public: @@ -4167,7 +4169,7 @@ public: } } - typedef llvm::SmallPtrSetImpl<ObjCMethodDecl*>::iterator iterator; + typedef decltype(Overridden)::iterator iterator; iterator begin() const { return Overridden.begin(); } iterator end() const { return Overridden.end(); } @@ -4335,10 +4337,6 @@ void Sema::CheckObjCMethodOverrides(ObjCMethodDecl *ObjCMethod, // Then merge the declarations. mergeObjCMethodDecls(ObjCMethod, overridden); - } - - for (ObjCMethodDecl *overridden : overrides) { - CheckObjCMethodOverride(ObjCMethod, overridden); if (ObjCMethod->isImplicit() && overridden->isImplicit()) continue; // Conflicting properties are detected elsewhere. @@ -4502,25 +4500,21 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef, } Decl *Sema::ActOnMethodDeclaration( - Scope *S, - SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef<SourceLocation> SelectorLocs, - Selector Sel, + Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef<SourceLocation> SelectorLocs, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!CurContext->isObjCContainer()) { Diag(MethodLoc, diag::err_missing_method_context); return nullptr; } - ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); - Decl *ClassDecl = cast<Decl>(OCD); + Decl *ClassDecl = cast<ObjCContainerDecl>(CurContext); QualType resultDeclType; bool HasRelatedResultType = false; @@ -4621,8 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); - if (AttrList) - ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. @@ -4726,6 +4719,17 @@ Decl *Sema::ActOnMethodDeclaration( Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) checkObjCMethodX86VectorTypes(*this, ObjCMethod); + // + load method cannot have availability attributes. It get called on + // startup, so it has to have the availability of the deployment target. + if (const auto *attr = ObjCMethod->getAttr<AvailabilityAttr>()) { + if (ObjCMethod->isClassMethod() && + ObjCMethod->getSelector().getAsString() == "load") { + Diag(attr->getLocation(), diag::warn_availability_on_static_initializer) + << 0; + ObjCMethod->dropAttr<AvailabilityAttr>(); + } + } + ActOnDocumentableDecl(ObjCMethod); return ObjCMethod; @@ -4769,7 +4773,7 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, Context.DeepCollectObjCIvars(Class, true, Ivars); // For each ivar, create a fresh ObjCAtDefsFieldDecl. for (unsigned i = 0; i < Ivars.size(); i++) { - const FieldDecl* ID = cast<FieldDecl>(Ivars[i]); + const FieldDecl* ID = Ivars[i]; RecordDecl *Record = dyn_cast<RecordDecl>(TagD); Decl *FD = ObjCAtDefsFieldDecl::Create(Context, Record, /*FIXME: StartL=*/ID->getLocation(), @@ -4784,13 +4788,13 @@ void Sema::ActOnDefs(Scope *S, Decl *TagD, SourceLocation DeclStart, D != Decls.end(); ++D) { FieldDecl *FD = cast<FieldDecl>(*D); if (getLangOpts().CPlusPlus) - PushOnScopeChains(cast<FieldDecl>(FD), S); + PushOnScopeChains(FD, S); else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD)) Record->addDecl(FD); } } -/// \brief Build a type-check a new Objective-C exception variable declaration. +/// Build a type-check a new Objective-C exception variable declaration. VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, SourceLocation StartLoc, SourceLocation IdLoc, @@ -4811,12 +4815,17 @@ VarDecl *Sema::BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType T, // Don't do any further checking. } else if (T->isDependentType()) { // Okay: we don't know what this type will instantiate to. - } else if (!T->isObjCObjectPointerType()) { - Invalid = true; - Diag(IdLoc ,diag::err_catch_param_not_objc_type); } else if (T->isObjCQualifiedIdType()) { Invalid = true; Diag(IdLoc, diag::err_illegal_qualifiers_on_catch_parm); + } else if (T->isObjCIdType()) { + // Okay: we don't know what this type will instantiate to. + } else if (!T->isObjCObjectPointerType()) { + Invalid = true; + Diag(IdLoc, diag::err_catch_param_not_objc_type); + } else if (!T->getAs<ObjCObjectPointerType>()->getInterfaceType()) { + Invalid = true; + Diag(IdLoc, diag::err_catch_param_not_objc_type); } VarDecl *New = VarDecl::Create(Context, CurContext, StartLoc, IdLoc, Id, |