Add new attribute 'objc_suppress_protocol' to suppress protocol conformance for a class.
The idea is to allow a class to stipulate that its methods (and those
of its parents) cannot be used for protocol conformance in a subclass.
A subclass is then explicitly required to re-implement those methods
of they are present in the class marked with this attribute.
Currently the attribute can only be applied to an @interface, and
not a category or class extension. This is by design. Unlike
protocol conformance, where a category can add explicit conformance
of a protocol to class, this anti-conformance really needs to be
observed uniformly by all clients of the class. That's because
the absence of the attribute implies more permissive checking of
protocol conformance.
This unfortunately required changing method lookup in ObjCInterfaceDecl
to take an optional protocol parameter. This should not slow down
method lookup in most cases, and is just used for protocol conformance.
llvm-svn: 195323
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index f44fb32..2a781b5 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -1664,7 +1664,8 @@
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!method->isPropertyAccessor() &&
!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
// has been declared in its primary class, superclass,
// or in one of their protocols, no need to issue the warning.
@@ -1676,7 +1677,8 @@
// uses the protocol.
if (ObjCMethodDecl *MethodInClass =
IDecl->lookupInstanceMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ true /*shallowCategoryLookup*/,
+ PDecl))
if (C || MethodInClass->isPropertyAccessor())
continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method;
@@ -1695,10 +1697,13 @@
ObjCMethodDecl *method = *I;
if (method->getImplementationControl() != ObjCMethodDecl::Optional &&
!ClsMap.count(method->getSelector()) &&
- (!Super || !Super->lookupClassMethod(method->getSelector()))) {
+ (!Super || !Super->lookupClassMethod(method->getSelector(),
+ /* shallowCategoryLookup */ false,
+ PDecl))) {
// See above comment for instance method lookups.
if (C && IDecl->lookupClassMethod(method->getSelector(),
- true /*shallowCategoryLookup*/))
+ true /*shallowCategoryLookup*/,
+ PDecl))
continue;
unsigned DIAG = diag::warn_unimplemented_protocol_method;
if (Diags.getDiagnosticLevel(DIAG, ImpLoc) !=