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