Revert "Add new attribute 'objc_suppress_protocol' to suppress protocol conformance for a class."

After implementing this patch, a few concerns about the language
feature itself emerged in my head that I had previously not considered.
I want to resolve those design concerns first before having
a half-designed language feature in the tree.

llvm-svn: 195328
This commit is contained in:
Ted Kremenek 2013-11-21 07:57:53 +00:00
parent fbc1adbaa7
commit a14c3119ac
6 changed files with 14 additions and 100 deletions

View File

@ -1142,17 +1142,14 @@ public:
// found, we search referenced protocols and class categories. // found, we search referenced protocols and class categories.
ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
bool shallowCategoryLookup= false, bool shallowCategoryLookup= false,
const ObjCCategoryDecl *C = 0, const ObjCCategoryDecl *C= 0) const;
const ObjCProtocolDecl *P = 0) const;
ObjCMethodDecl *lookupInstanceMethod(Selector Sel, ObjCMethodDecl *lookupInstanceMethod(Selector Sel,
bool shallowCategoryLookup = false, bool shallowCategoryLookup = false) const {
ObjCProtocolDecl *P = 0) const { return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup);
return lookupMethod(Sel, true/*isInstance*/, shallowCategoryLookup, 0, P);
} }
ObjCMethodDecl *lookupClassMethod(Selector Sel, ObjCMethodDecl *lookupClassMethod(Selector Sel,
bool shallowCategoryLookup = false, bool shallowCategoryLookup = false) const {
ObjCProtocolDecl *P = 0) const { return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup);
return lookupMethod(Sel, false/*isInstance*/, shallowCategoryLookup, 0, P);
} }
ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName);

View File

@ -613,12 +613,6 @@ def ObjCRootClass : InheritableAttr {
let Subjects = [ObjCInterface]; let Subjects = [ObjCInterface];
} }
def ObjCSuppressProtocol : InheritableAttr {
let Spellings = [GNU<"objc_suppress_protocol">];
let Subjects = [ObjCInterface];
let Args = [IdentifierArgument<"Protocol", 1>];
}
def Overloadable : Attr { def Overloadable : Attr {
let Spellings = [GNU<"overloadable">]; let Spellings = [GNU<"overloadable">];
} }

View File

@ -457,11 +457,9 @@ ObjCInterfaceDecl::lookupNestedProtocol(IdentifierInfo *Name) {
/// When argument category "C" is specified, any implicit method found /// When argument category "C" is specified, any implicit method found
/// in this category is ignored. /// in this category is ignored.
ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel, ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
bool isInstance, bool isInstance,
bool shallowCategoryLookup, bool shallowCategoryLookup,
const ObjCCategoryDecl *C, const ObjCCategoryDecl *C) const {
const ObjCProtocolDecl *P) const
{
// FIXME: Should make sure no callers ever do this. // FIXME: Should make sure no callers ever do this.
if (!hasDefinition()) if (!hasDefinition())
return 0; return 0;
@ -472,23 +470,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupMethod(Selector Sel,
if (data().ExternallyCompleted) if (data().ExternallyCompleted)
LoadExternalDefinition(); LoadExternalDefinition();
while (ClassDecl) { while (ClassDecl != NULL) {
// If we are looking for a method that is part of protocol conformance,
// check if the class has been marked to suppress conformance
// of that protocol.
if (P && ClassDecl->hasAttrs()) {
const AttrVec &V = ClassDecl->getAttrs();
const IdentifierInfo *PI = P->getIdentifier();
for (AttrVec::const_iterator I = V.begin(), E = V.end(); I != E; ++I) {
if (const ObjCSuppressProtocolAttr *A =
dyn_cast<ObjCSuppressProtocolAttr>(*I)){
if (A->getProtocol() == PI) {
return 0;
}
}
}
}
if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance))) if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
return MethodDecl; return MethodDecl;

View File

@ -2134,30 +2134,6 @@ static void handleObjCRootClassAttr(Sema &S, Decl *D,
Attr.getAttributeSpellingListIndex())); Attr.getAttributeSpellingListIndex()));
} }
static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
IdentifierLoc *Parm = NULL;
if (Attr.getNumArgs() == 1) {
Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
}
if (!Parm) {
S.Diag(D->getLocStart(), diag::err_objc_attr_not_id) << Attr.getName() << 1;
return;
}
D->addAttr(::new (S.Context)
ObjCSuppressProtocolAttr(Attr.getRange(), S.Context, Parm->Ident,
Attr.getAttributeSpellingListIndex()));
}
static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D, static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
const AttributeList &Attr) { const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) { if (!isa<ObjCInterfaceDecl>(D)) {
@ -4714,10 +4690,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCRootClass: case AttributeList::AT_ObjCRootClass:
handleObjCRootClassAttr(S, D, Attr); handleObjCRootClassAttr(S, D, Attr);
break; break;
case AttributeList::AT_ObjCSuppressProtocol: case AttributeList::AT_ObjCRequiresPropertyDefs:
handleObjCSuppresProtocolAttr(S, D, Attr);
break;
case AttributeList::AT_ObjCRequiresPropertyDefs:
handleObjCRequiresPropertyDefsAttr (S, D, Attr); handleObjCRequiresPropertyDefsAttr (S, D, Attr);
break; break;
case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break; case AttributeList::AT_Unused: handleUnusedAttr (S, D, Attr); break;

View File

@ -1664,8 +1664,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
if (method->getImplementationControl() != ObjCMethodDecl::Optional && if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!method->isPropertyAccessor() && !method->isPropertyAccessor() &&
!InsMap.count(method->getSelector()) && !InsMap.count(method->getSelector()) &&
(!Super || !Super->lookupInstanceMethod(method->getSelector(), (!Super || !Super->lookupInstanceMethod(method->getSelector()))) {
false, PDecl))) {
// If a method is not implemented in the category implementation but // If a method is not implemented in the category implementation but
// has been declared in its primary class, superclass, // has been declared in its primary class, superclass,
// or in one of their protocols, no need to issue the warning. // or in one of their protocols, no need to issue the warning.
@ -1677,8 +1676,7 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
// uses the protocol. // uses the protocol.
if (ObjCMethodDecl *MethodInClass = if (ObjCMethodDecl *MethodInClass =
IDecl->lookupInstanceMethod(method->getSelector(), IDecl->lookupInstanceMethod(method->getSelector(),
true /*shallowCategoryLookup*/, true /*shallowCategoryLookup*/))
PDecl))
if (C || MethodInClass->isPropertyAccessor()) if (C || MethodInClass->isPropertyAccessor())
continue; continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method; unsigned DIAG = diag::warn_unimplemented_protocol_method;
@ -1697,13 +1695,10 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc,
ObjCMethodDecl *method = *I; ObjCMethodDecl *method = *I;
if (method->getImplementationControl() != ObjCMethodDecl::Optional && if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!ClsMap.count(method->getSelector()) && !ClsMap.count(method->getSelector()) &&
(!Super || !Super->lookupClassMethod(method->getSelector(), (!Super || !Super->lookupClassMethod(method->getSelector()))) {
/* shallowCategoryLookup */ false,
PDecl))) {
// See above comment for instance method lookups. // See above comment for instance method lookups.
if (C && IDecl->lookupClassMethod(method->getSelector(), if (C && IDecl->lookupClassMethod(method->getSelector(),
true /*shallowCategoryLookup*/, true /*shallowCategoryLookup*/))
PDecl))
continue; continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method; unsigned DIAG = diag::warn_unimplemented_protocol_method;
if (Diags.getDiagnosticLevel(DIAG, ImpLoc) != if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=

View File

@ -1,27 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -Wno-objc-root-class
@protocol FooProto
- (void) theBestOfTimes; // expected-note {{method 'theBestOfTimes' declared here}}
@end
__attribute__((objc_suppress_protocol(FooProto)))
@interface Bar
- (void) theBestOfTimes;
@end
@interface Bar2 : Bar
@end
@interface Baz : Bar2 <FooProto> // expected-note {{required for direct or indirect protocol 'FooProto'}}
@end
@interface Baz2 : Bar2 <FooProto>
- (void) theBestOfTimes;
@end
@implementation Baz // expected-warning {{method 'theBestOfTimes' in protocol not implemented}}
@end
@implementation Baz2 // no-warning
- (void) theBestOfTimes {}
@end