r196955 - Rename attribute 'objc_suppress_protocol_methods' to 'objc_protocol_requires_explicit_implementation'.
Aaron Ballman
aaron at aaronballman.com
Wed Dec 11 05:26:34 PST 2013
On Tue, Dec 10, 2013 at 2:43 PM, Ted Kremenek <kremenek at apple.com> wrote:
> Author: kremenek
> Date: Tue Dec 10 13:43:48 2013
> New Revision: 196955
>
> URL: http://llvm.org/viewvc/llvm-project?rev=196955&view=rev
> Log:
> Rename attribute 'objc_suppress_protocol_methods' to 'objc_protocol_requires_explicit_implementation'.
>
> That's a mouthful, and not necessarily the final name. This also
> reflects a semantic change where this attribute is now on the
> protocol itself instead of a class. This attribute will require
> that a protocol, when adopted by a class, is explicitly implemented
> by the class itself (instead of walking the super class chain).
>
> Note that this attribute is not "done". This should be considered
> a WIP.
>
> Modified:
> cfe/trunk/include/clang/AST/DeclObjC.h
> cfe/trunk/include/clang/Basic/Attr.td
> cfe/trunk/lib/AST/DeclObjC.cpp
> cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m
>
> Modified: cfe/trunk/include/clang/AST/DeclObjC.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclObjC.h (original)
> +++ cfe/trunk/include/clang/AST/DeclObjC.h Tue Dec 10 13:43:48 2013
> @@ -984,10 +984,6 @@ public:
> : superCls;
> }
>
> - /// \brief Returns true if this class is marked to suppress being
> - /// used to determine if a subclass conforms to a protocol.
> - bool shouldSuppressProtocol(const ObjCProtocolDecl *P) const;
> -
> /// \brief Iterator that walks over the list of categories, filtering out
> /// those that do not meet specific criteria.
> ///
> @@ -1206,8 +1202,7 @@ public:
> ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance,
> bool shallowCategoryLookup = false,
> bool followSuper = true,
> - const ObjCCategoryDecl *C = 0,
> - const ObjCProtocolDecl *P = 0) const;
> + const ObjCCategoryDecl *C = 0) const;
>
> /// Lookup an instance method for a given selector.
> ObjCMethodDecl *lookupInstanceMethod(Selector Sel) const {
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Tue Dec 10 13:43:48 2013
> @@ -695,10 +695,9 @@ def ObjCRootClass : InheritableAttr {
> let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
> }
>
> -def ObjCSuppressProtocol : InheritableAttr {
> - let Spellings = [GNU<"objc_suppress_protocol_methods">];
> - let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
> - let Args = [IdentifierArgument<"Protocol">];
> +def ObjCExplicitProtocolImpl : InheritableAttr {
> + let Spellings = [GNU<"objc_protocol_requires_explicit_implementation">];
> + let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
> }
>
> def ObjCDesignatedInitializer : Attr {
>
> Modified: cfe/trunk/lib/AST/DeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclObjC.cpp?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclObjC.cpp (original)
> +++ cfe/trunk/lib/AST/DeclObjC.cpp Tue Dec 10 13:43:48 2013
> @@ -256,18 +256,6 @@ ObjCContainerDecl::FindPropertyDeclarati
>
> void ObjCInterfaceDecl::anchor() { }
>
> -bool ObjCInterfaceDecl::shouldSuppressProtocol(const ObjCProtocolDecl *P) const{
> - if (!hasAttrs())
> - return false;
> - const IdentifierInfo *PI = P->getIdentifier();
> - for (specific_attr_iterator<ObjCSuppressProtocolAttr>
> - I = specific_attr_begin<ObjCSuppressProtocolAttr>(),
> - E = specific_attr_end<ObjCSuppressProtocolAttr>(); I != E; ++I)
> - if ((*I)->getProtocol() == PI)
> - return true;
> - return false;
> -}
> -
> /// FindPropertyVisibleInPrimaryClass - Finds declaration of the property
> /// with name 'PropertyId' in the primary class; including those in protocols
> /// (direct or indirect) used by the primary class.
> @@ -555,8 +543,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::looku
> bool isInstance,
> bool shallowCategoryLookup,
> bool followSuper,
> - const ObjCCategoryDecl *C,
> - const ObjCProtocolDecl *P) const
> + const ObjCCategoryDecl *C) const
> {
> // FIXME: Should make sure no callers ever do this.
> if (!hasDefinition())
> @@ -569,12 +556,6 @@ ObjCMethodDecl *ObjCInterfaceDecl::looku
> LoadExternalDefinition();
>
> while (ClassDecl) {
> - // If we are looking for a method that is part of protocol conformance,
> - // check if the superclass has been marked to suppress conformance
> - // of that protocol.
> - if (P && ClassDecl->shouldSuppressProtocol(P))
> - return 0;
> -
> if ((MethodDecl = ClassDecl->getMethod(Sel, isInstance)))
> return MethodDecl;
>
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Tue Dec 10 13:43:48 2013
> @@ -1740,16 +1740,9 @@ static void handleAttrWithMessage(Sema &
>
> static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
> const AttributeList &Attr) {
> - IdentifierLoc *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()));
> + ObjCExplicitProtocolImplAttr(Attr.getRange(), S.Context,
> + Attr.getAttributeSpellingListIndex()));
If you aren't adding further semantic checks, you could remove this
handler entirely and instead use the handleSimpleAttribute templatized
handler.
> }
>
> static bool checkAvailabilityAttr(Sema &S, SourceRange Range,
> @@ -4032,7 +4025,7 @@ static void ProcessDeclAttribute(Sema &S
> handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, Attr); break;
> case AttributeList::AT_ObjCRootClass:
> handleSimpleAttribute<ObjCRootClassAttr>(S, D, Attr); break;
> - case AttributeList::AT_ObjCSuppressProtocol:
> + case AttributeList::AT_ObjCExplicitProtocolImpl:
> handleObjCSuppresProtocolAttr(S, D, Attr);
> break;
> case AttributeList::AT_ObjCRequiresPropertyDefs:
>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Dec 10 13:43:48 2013
> @@ -1666,6 +1666,8 @@ void Sema::CheckProtocolMethodDefs(Sourc
> // the method was implemented by a base class or an inherited
> // protocol. This lookup is slow, but occurs rarely in correct code
> // and otherwise would terminate in a warning.
> + if (PDecl->hasAttr<ObjCExplicitProtocolImplAttr>())
> + Super = NULL;
>
> // check unimplemented instance methods.
> if (!NSIDecl)
> @@ -1679,8 +1681,7 @@ void Sema::CheckProtocolMethodDefs(Sourc
> true /* instance */,
> false /* shallowCategory */,
> true /* followsSuper */,
> - NULL /* category */,
> - PDecl /* protocol */))) {
> + NULL /* category */))) {
> // 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.
> @@ -1717,8 +1718,7 @@ void Sema::CheckProtocolMethodDefs(Sourc
> false /* class method */,
> false /* shallowCategoryLookup */,
> true /* followSuper */,
> - NULL /* category */,
> - PDecl /* protocol */))) {
> + NULL /* category */))) {
> // See above comment for instance method lookups.
> if (C && IDecl->lookupMethod(method->getSelector(),
> false /* class */,
>
> Modified: cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m?rev=196955&r1=196954&r2=196955&view=diff
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m (original)
> +++ cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m Tue Dec 10 13:43:48 2013
> @@ -1,79 +1,37 @@
> // RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fsyntax-only -verify %s -Wno-objc-root-class
>
> +// Mark this protocol as requiring all of its methods and properties
> +// to be explicitly implemented in the adopting class.
> +__attribute__((objc_protocol_requires_explicit_implementation))
> @protocol Protocol
> - (void) theBestOfTimes; // expected-note {{method 'theBestOfTimes' declared here}}
> - at property (readonly) id theWorstOfTimes; // expected-note {{property declared here}}
> + at property (readonly) id theWorstOfTimes;
> @end
>
> -// In this example, the root class provides all the methods for
> -// a protocol, and the immediate subclass adopts the attribute.
> -//
> -// The further subclasses should not have access to the root class's
> -// methods for checking protocol conformance.
> -//
> -// ClassC states protocol conformance, but does not redeclare the method.
> -// For this case we get a warning.
> -//
> -// ClassD states protocol conformance, but does redeclare the method.
> -// For this case we do not get a warning.
> -//
> -
> +// In this example, ClassA adopts the protocol. We won't
> +// provide the implementation here, but this protocol will
> +// be adopted later by a subclass.
> @interface ClassA <Protocol>
> - (void) theBestOfTimes;
> -//@property (readonly) id theWorstOfTimes;
> - at end
> -
> -__attribute__((objc_suppress_protocol_methods(Protocol))) @interface ClassB : ClassA @end
> -
> - at interface ClassC : ClassB <Protocol> @end // expected-note {{required for direct or indirect protocol 'Protocol'}}
> -
> - at interface ClassD : ClassB <Protocol>
> -- (void) theBestOfTimes;
> @property (readonly) id theWorstOfTimes;
> @end
>
> - at implementation ClassA // expected-warning {{auto property synthesis will not synthesize property declared in a protocol}}
> -- (void) theBestOfTimes {}
> +// This class subclasses ClassA (which adopts 'Protocol'),
> +// but does not provide the needed implementation.
> + at interface ClassB : ClassA <Protocol> // expected-note {{required for direct or indirect protocol 'Protocol'}}
> @end
>
> - at implementation ClassC @end // expected-warning {{method 'theBestOfTimes' in protocol not implemented}}
> -
> - at implementation ClassD // no-warning
> -- (void) theBestOfTimes {}
> + at implementation ClassB // expected-warning {{method 'theBestOfTimes' in protocol not implemented}}
> @end
>
> -// In this example, the class both conforms to the protocl and adopts
> -// the attribute. This illustrates that the attribute does not
> -// interfere with the protocol conformance checking for the class
> -// itself.
> -__attribute__((objc_suppress_protocol_methods(Protocol)))
> - at interface AdoptsAndConforms <Protocol>
> -- (void) theBestOfTimes;
> - at property (readonly) id theWorstOfTimes;
> - at end
> -
> - at implementation AdoptsAndConforms // no-warning
> -- (void) theBestOfTimes {}
> - at end
> -
> -// This attribute cannot be added to a class extension or category.
> - at interface ClassE
> --(void) theBestOfTimes;
> - at end
> +// Test that the attribute is used correctly.
> +__attribute__((objc_protocol_requires_explicit_implementation(1+2))) // expected-error {{attribute takes no arguments}}
> + at protocol AnotherProtocol @end
>
> -__attribute__((objc_supress_protocol(Protocol)))
> - at interface ClassE () @end // expected-error {{attributes may not be specified on a category}}
> +// Cannot put the attribute on classes or other non-protocol declarations.
> +__attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}}
> + at interface AnotherClass @end
>
> -__attribute__((objc_supress_protocol(Protocol)))
> - at interface ClassE (MyCat) @end // expected-error {{attributes may not be specified on a category}}
> +__attribute__((objc_protocol_requires_explicit_implementation)) // expected-error {{attribute only applies to Objective-C protocols}}
> +int x;
>
> -// The attribute requires one or more identifiers.
> -__attribute__((objc_suppress_protocol_methods())) // expected-error {{'objc_suppress_protocol_methods' attribute takes one argument}}
> - at interface ClassF @end
> -
> -// The attribute requires one or more identifiers.
> -__attribute__((objc_suppress_protocol_methods(ProtoA, ProtoB))) // expected-error {{use of undeclared identifier 'ProtoB'}}
> - at interface ClassG @end
> -__attribute__((objc_suppress_protocol_methods(1+2)))
> - at interface ClassH @end // expected-error {{parameter of 'objc_suppress_protocol_methods' attribute must be a single name of an Objective-C protocol}}
> -
> \ No newline at end of file
Should probably add the newline at the end of the test file.
~Aaron
More information about the cfe-commits
mailing list