aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclObjC.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-05-27 18:47:56 +0000
commit5e20cdd81c44a443562a09007668ffdf76c455af (patch)
treedbbd4047878da71c1a706e26ce05b4e7791b14cc /lib/Sema/SemaDeclObjC.cpp
parentd5f23b0b7528b5c3caed1ba14f897cc4aaa9e3c3 (diff)
downloadsrc-5e20cdd81c44a443562a09007668ffdf76c455af.tar.gz
src-5e20cdd81c44a443562a09007668ffdf76c455af.zip
Vendor import of clang trunk r238337:vendor/clang/clang-trunk-r238337
Notes
Notes: svn path=/vendor/clang/dist/; revision=283627 svn path=/vendor/clang/clang-trunk-r238337/; revision=283628; tag=vendor/clang/clang-trunk-r238337
Diffstat (limited to 'lib/Sema/SemaDeclObjC.cpp')
-rw-r--r--lib/Sema/SemaDeclObjC.cpp128
1 files changed, 83 insertions, 45 deletions
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 7e3da941b339..38318791fd77 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/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;
}