forked from OSchip/llvm-project
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:
parent
fbc1adbaa7
commit
a14c3119ac
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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">];
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) !=
|
||||||
|
|
|
@ -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
|
|
Loading…
Reference in New Issue