diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp | 128 |
1 files changed, 83 insertions, 45 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp index 7e3da94..3831879 100644 --- a/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp +++ b/contrib/llvm/tools/clang/lib/Sema/SemaDeclObjC.cpp @@ -448,6 +448,19 @@ class ObjCInterfaceValidatorCCC : public CorrectionCandidateCallback { } +static void diagnoseUseOfProtocols(Sema &TheSema, + ObjCContainerDecl *CD, + ObjCProtocolDecl *const *ProtoRefs, + unsigned NumProtoRefs, + const SourceLocation *ProtoLocs) { + assert(ProtoRefs); + // Diagnose availability in the context of the ObjC container. + Sema::ContextRAII SavedContext(TheSema, CD); + for (unsigned i = 0; i < NumProtoRefs; ++i) { + (void)TheSema.DiagnoseUseOfDecl(ProtoRefs[i], ProtoLocs[i]); + } +} + Decl *Sema:: ActOnStartClassInterface(SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, SourceLocation ClassLoc, @@ -535,6 +548,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, ObjCInterfaceDecl *SuperClassDecl = dyn_cast_or_null<ObjCInterfaceDecl>(PrevDecl); + // Diagnose availability in the context of the @interface. + ContextRAII SavedContext(*this, IDecl); // Diagnose classes that inherit from deprecated classes. if (SuperClassDecl) (void)DiagnoseUseOfDecl(SuperClassDecl, SuperLoc); @@ -591,6 +606,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, // Check then save referenced protocols. if (NumProtoRefs) { + diagnoseUseOfProtocols(*this, IDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); IDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); IDecl->setEndOfDefinitionLoc(EndProtoLoc); @@ -617,8 +634,7 @@ void Sema::ActOnTypedefedProtocols(SmallVectorImpl<Decl *> &ProtocolRefs, QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) if (const ObjCObjectType *OPT = T->getAs<ObjCObjectType>()) - for (auto *I : OPT->quals()) - ProtocolRefs.push_back(I); + ProtocolRefs.append(OPT->qual_begin(), OPT->qual_end()); } } @@ -752,6 +768,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, if (!err && NumProtoRefs ) { /// Check then save referenced protocols. + diagnoseUseOfProtocols(*this, PDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); PDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); } @@ -779,7 +797,7 @@ static bool NestedProtocolHasNoDefinition(ObjCProtocolDecl *PDecl, /// issues an error if they are not declared. It returns list of /// protocol declarations in its 'Protocols' argument. void -Sema::FindProtocolDeclaration(bool WarnOnDeclarations, +Sema::FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, const IdentifierLocPair *ProtocolId, unsigned NumProtocols, SmallVectorImpl<Decl *> &Protocols) { @@ -805,8 +823,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, // If this is a forward protocol declaration, get its definition. if (!PDecl->isThisDeclarationADefinition() && PDecl->getDefinition()) PDecl = PDecl->getDefinition(); - - (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + + // For an objc container, delay protocol reference checking until after we + // can set the objc decl as the availability context, otherwise check now. + if (!ForObjCContainer) { + (void)DiagnoseUseOfDecl(PDecl, ProtocolId[i].second); + } // If this is a forward declaration and we are supposed to warn in this // case, do it. @@ -935,7 +957,9 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, CurContext->addDecl(CDecl); if (NumProtoRefs) { - CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, + diagnoseUseOfProtocols(*this, CDecl, (ObjCProtocolDecl*const*)ProtoRefs, + NumProtoRefs, ProtoLocs); + CDecl->setProtocolList((ObjCProtocolDecl*const*)ProtoRefs, NumProtoRefs, ProtoLocs, Context); // Protocols in the class extension belong to the class. if (CDecl->IsClassExtension()) @@ -2241,8 +2265,14 @@ void Sema::addMethodToGlobalList(ObjCMethodList *List, if (getLangOpts().Modules && !getLangOpts().CurrentModule.empty()) continue; - if (!MatchTwoMethodDeclarations(Method, List->getMethod())) + if (!MatchTwoMethodDeclarations(Method, List->getMethod())) { + // Even if two method types do not match, we would like to say + // there is more than one declaration so unavailability/deprecated + // warning is not too noisy. + if (!Method->isDefined()) + List->setHasMoreThanOneDecl(true); continue; + } ObjCMethodDecl *PrevObjCMethod = List->getMethod(); @@ -2341,19 +2371,33 @@ bool Sema::CollectMultipleMethodsInGlobalPool( return Methods.size() > 1; } -bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, bool instance) { +bool Sema::AreMultipleMethodsInGlobalPool(Selector Sel, ObjCMethodDecl *BestMethod, + SourceRange R, + bool receiverIdOrClass) { GlobalMethodPool::iterator Pos = MethodPool.find(Sel); // Test for no method in the pool which should not trigger any warning by // caller. if (Pos == MethodPool.end()) return true; - ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; + ObjCMethodList &MethList = + BestMethod->isInstanceMethod() ? Pos->second.first : Pos->second.second; + + // Diagnose finding more than one method in global pool + SmallVector<ObjCMethodDecl *, 4> Methods; + Methods.push_back(BestMethod); + for (ObjCMethodList *ML = &MethList; ML; ML = ML->getNext()) + if (ObjCMethodDecl *M = ML->getMethod()) + if (!M->isHidden() && M != BestMethod && !M->hasAttr<UnavailableAttr>()) + Methods.push_back(M); + if (Methods.size() > 1) + DiagnoseMultipleMethodInGlobalPool(Methods, Sel, R, receiverIdOrClass); + return MethList.hasMoreThanOneDecl(); } ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, bool receiverIdOrClass, - bool warn, bool instance) { + bool instance) { if (ExternalSource) ReadMethodPool(Sel); @@ -2365,31 +2409,23 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, ObjCMethodList &MethList = instance ? Pos->second.first : Pos->second.second; SmallVector<ObjCMethodDecl *, 4> Methods; for (ObjCMethodList *M = &MethList; M; M = M->getNext()) { - if (M->getMethod() && !M->getMethod()->isHidden()) { - // If we're not supposed to warn about mismatches, we're done. - if (!warn) - return M->getMethod(); - - Methods.push_back(M->getMethod()); - } + if (M->getMethod() && !M->getMethod()->isHidden()) + return M->getMethod(); } + return nullptr; +} - // If there aren't any visible methods, we're done. - // FIXME: Recover if there are any known-but-hidden methods? - if (Methods.empty()) - return nullptr; - - if (Methods.size() == 1) - return Methods[0]; - +void Sema::DiagnoseMultipleMethodInGlobalPool(SmallVectorImpl<ObjCMethodDecl*> &Methods, + Selector Sel, SourceRange R, + bool receiverIdOrClass) { // We found multiple methods, so we may have to complain. bool issueDiagnostic = false, issueError = false; // We support a warning which complains about *any* difference in // method signature. bool strictSelectorMatch = - receiverIdOrClass && warn && - !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin()); + receiverIdOrClass && + !Diags.isIgnored(diag::warn_strict_multiple_method_decl, R.getBegin()); if (strictSelectorMatch) { for (unsigned I = 1, N = Methods.size(); I != N; ++I) { if (!MatchTwoMethodDeclarations(Methods[0], Methods[I], MMS_strict)) { @@ -2414,7 +2450,7 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, break; } } - + if (issueDiagnostic) { if (issueError) Diag(R.getBegin(), diag::err_arc_multiple_method_decl) << Sel << R; @@ -2422,16 +2458,15 @@ ObjCMethodDecl *Sema::LookupMethodInGlobalPool(Selector Sel, SourceRange R, Diag(R.getBegin(), diag::warn_strict_multiple_method_decl) << Sel << R; else Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R; - + Diag(Methods[0]->getLocStart(), issueError ? diag::note_possibility : diag::note_using) - << Methods[0]->getSourceRange(); + << Methods[0]->getSourceRange(); for (unsigned I = 1, N = Methods.size(); I != N; ++I) { Diag(Methods[I]->getLocStart(), diag::note_also_found) - << Methods[I]->getSourceRange(); - } + << Methods[I]->getSourceRange(); + } } - return Methods[0]; } ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { @@ -2442,12 +2477,16 @@ ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) { GlobalMethods &Methods = Pos->second; for (const ObjCMethodList *Method = &Methods.first; Method; Method = Method->getNext()) - if (Method->getMethod() && Method->getMethod()->isDefined()) + if (Method->getMethod() && + (Method->getMethod()->isDefined() || + Method->getMethod()->isPropertyAccessor())) return Method->getMethod(); for (const ObjCMethodList *Method = &Methods.second; Method; Method = Method->getNext()) - if (Method->getMethod() && Method->getMethod()->isDefined()) + if (Method->getMethod() && + (Method->getMethod()->isDefined() || + Method->getMethod()->isPropertyAccessor())) return Method->getMethod(); return nullptr; } @@ -2571,10 +2610,9 @@ Sema::ObjCContainerKind Sema::getObjCContainerKind() const { case Decl::ObjCProtocol: return Sema::OCK_Protocol; case Decl::ObjCCategory: - if (dyn_cast<ObjCCategoryDecl>(CurContext)->IsClassExtension()) + if (cast<ObjCCategoryDecl>(CurContext)->IsClassExtension()) return Sema::OCK_ClassExtension; - else - return Sema::OCK_Category; + return Sema::OCK_Category; case Decl::ObjCImplementation: return Sema::OCK_Implementation; case Decl::ObjCCategoryImpl: @@ -3286,7 +3324,7 @@ Decl *Sema::ActOnMethodDeclaration( case OMF_alloc: case OMF_new: - InferRelatedResultType = ObjCMethod->isClassMethod(); + InferRelatedResultType = ObjCMethod->isClassMethod(); break; case OMF_init: @@ -3297,7 +3335,8 @@ Decl *Sema::ActOnMethodDeclaration( break; } - if (InferRelatedResultType) + if (InferRelatedResultType && + !ObjCMethod->getReturnType()->isObjCIndependentClassType()) ObjCMethod->SetRelatedResultType(); } @@ -3487,12 +3526,11 @@ void Sema::DiagnoseUseOfUnimplementedSelectors() { if (ReferencedSelectors.empty() || !Context.AnyObjCImplementation()) return; - for (llvm::DenseMap<Selector, SourceLocation>::iterator S = - ReferencedSelectors.begin(), - E = ReferencedSelectors.end(); S != E; ++S) { - Selector Sel = (*S).first; + for (auto &SelectorAndLocation : ReferencedSelectors) { + Selector Sel = SelectorAndLocation.first; + SourceLocation Loc = SelectorAndLocation.second; if (!LookupImplementedMethodInGlobalPool(Sel)) - Diag((*S).second, diag::warn_unimplemented_selector) << Sel; + Diag(Loc, diag::warn_unimplemented_selector) << Sel; } return; } |