r265201 - [Objective-C] Introduce objc_runtime_visible attribute.

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 11 07:38:47 PDT 2016


On Fri, Apr 1, 2016 at 7:23 PM, Douglas Gregor via cfe-commits
<cfe-commits at lists.llvm.org> wrote:
> Author: dgregor
> Date: Fri Apr  1 18:23:52 2016
> New Revision: 265201

Sorry about the long delay before getting you this feedback (been a
bit hectic around here). One request: can you add some Sema tests that
the attribute properly diagnoses? Tests for the wrong attribute
subject, attribute with arguments, etc all fail would be appreciated
(so we don't accidentally regress its behavior in the future).

Thanks!

~Aaron

>
> URL: http://llvm.org/viewvc/llvm-project?rev=265201&view=rev
> Log:
> [Objective-C] Introduce objc_runtime_visible attribute.
>
> The objc_runtime_visible attribute deals with an odd corner case where
> a particular Objective-C class is known to the Objective-C runtime
> (and, therefore, accessible by name) but its symbol has been hidden
> for some reason. For such classes, teach CodeGen to use
> objc_lookUpClass to retrieve the Class object, rather than referencing
> the class symbol directly.
>
> Classes annotated with objc_runtime_visible have two major limitations
> that fall out from places where Objective-C metadata needs to refer to
> the class (or metaclass) symbol directly:
>
> * One cannot implement a subclass of an objc_runtime_visible class.
> * One cannot implement a category on an objc_runtime_visible class.
>
> Implements rdar://problem/25494092.
>
> Added:
>     cfe/trunk/test/CodeGenObjC/attr-objc-runtime-visible.m
>     cfe/trunk/test/SemaObjC/attr-objc-runtime-visible.m
> Modified:
>     cfe/trunk/include/clang/Basic/Attr.td
>     cfe/trunk/include/clang/Basic/AttrDocs.td
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/lib/CodeGen/CGObjCMac.cpp
>     cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>     cfe/trunk/lib/Sema/SemaDeclObjC.cpp
>
> Modified: cfe/trunk/include/clang/Basic/Attr.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/Attr.td (original)
> +++ cfe/trunk/include/clang/Basic/Attr.td Fri Apr  1 18:23:52 2016
> @@ -1241,6 +1241,12 @@ def ObjCRuntimeName : Attr {
>    let Documentation = [ObjCRuntimeNameDocs];
>  }
>
> +def ObjCRuntimeVisible : Attr {
> +  let Spellings = [GNU<"objc_runtime_visible">];
> +  let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
> +  let Documentation = [ObjCRuntimeVisibleDocs];
> +}
> +
>  def ObjCBoxable : Attr {
>    let Spellings = [GNU<"objc_boxable">];
>    let Subjects = SubjectList<[Record], ErrorDiag, "ExpectedStructOrUnion">;
>
> Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
> +++ cfe/trunk/include/clang/Basic/AttrDocs.td Fri Apr  1 18:23:52 2016
> @@ -612,6 +612,13 @@ can only be placed before an @protocol o
>      }];
>  }
>
> +def ObjCRuntimeVisibleDocs : Documentation {
> +    let Category = DocCatFunction;
> +    let Content = [{
> +This attribute specifies that the Objective-C class to which it applies is visible to the Objective-C runtime but not to the linker. Classes annotated with this attribute cannot be subclassed and cannot have categories defined for them.
> +    }];
> +}
> +
>  def ObjCBoxableDocs : Documentation {
>      let Category = DocCatFunction;
>      let Content = [{
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Apr  1 18:23:52 2016
> @@ -715,6 +715,12 @@ def err_objc_root_class_subclass : Error
>  def warn_objc_root_class_missing : Warning<
>    "class %0 defined without specifying a base class">,
>    InGroup<ObjCRootClass>;
> +def err_objc_runtime_visible_category : Error<
> +  "cannot implement a category for class %0 that is only visible via the "
> +  "Objective-C runtime">;
> +def err_objc_runtime_visible_subclass : Error<
> +  "cannot implement subclass %0 of a superclass %1 that is only visible via the "
> +  "Objective-C runtime">;
>  def note_objc_needs_superclass : Note<
>    "add a super class to fix this problem">;
>  def warn_dup_category_def : Warning<
>
> Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Fri Apr  1 18:23:52 2016
> @@ -349,6 +349,20 @@ public:
>      return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
>    }
>
> +  llvm::Constant *getLookUpClassFn() {
> +    CodeGen::CodeGenTypes &Types = CGM.getTypes();
> +    ASTContext &Ctx = CGM.getContext();
> +    // Class objc_lookUpClass (const char *)
> +    SmallVector<CanQualType,1> Params;
> +    Params.push_back(
> +      Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
> +    llvm::FunctionType *FTy =
> +        Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
> +                                Ctx.getCanonicalType(Ctx.getObjCClassType()),
> +                                Params));
> +    return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
> +  }
> +
>    /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
>    llvm::Constant *getGcReadWeakFn() {
>      // id objc_read_weak (id *)
> @@ -981,6 +995,12 @@ protected:
>    /// defined. The return value has type ProtocolPtrTy.
>    llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
>
> +  /// Return a reference to the given Class using runtime calls rather than
> +  /// by a symbol reference.
> +  llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
> +                                      const ObjCInterfaceDecl *ID,
> +                                      ObjCCommonTypesHelper &ObjCTypes);
> +
>  public:
>    /// CreateMetadataVar - Create a global variable with internal
>    /// linkage for use by the Objective-C runtime.
> @@ -2673,6 +2693,25 @@ llvm::Constant *CGObjCCommonMac::GetProt
>    return GetOrEmitProtocolRef(PD);
>  }
>
> +llvm::Value *CGObjCCommonMac::EmitClassRefViaRuntime(
> +               CodeGenFunction &CGF,
> +               const ObjCInterfaceDecl *ID,
> +               ObjCCommonTypesHelper &ObjCTypes) {
> +  llvm::Constant *lookUpClassFn = ObjCTypes.getLookUpClassFn();
> +
> +  llvm::Value *className =
> +      CGF.CGM.GetAddrOfConstantCString(ID->getObjCRuntimeNameAsString())
> +        .getPointer();
> +  ASTContext &ctx = CGF.CGM.getContext();
> +  className =
> +      CGF.Builder.CreateBitCast(className,
> +                                CGF.ConvertType(
> +                                  ctx.getPointerType(ctx.CharTy.withConst())));
> +  llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
> +  call->setDoesNotThrow();
> +  return call;
> +}
> +
>  /*
>  // Objective-C 1.0 extensions
>  struct _objc_protocol {
> @@ -4633,6 +4672,11 @@ llvm::Value *CGObjCMac::EmitClassRefFrom
>
>  llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
>                                       const ObjCInterfaceDecl *ID) {
> +  // If the class has the objc_runtime_visible attribute, we need to
> +  // use the Objective-C runtime to get the class.
> +  if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
> +    return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
> +
>    return EmitClassRefFromId(CGF, ID->getIdentifier());
>  }
>
> @@ -6874,6 +6918,11 @@ llvm::Value *CGObjCNonFragileABIMac::Emi
>
>  llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
>                                                    const ObjCInterfaceDecl *ID) {
> +  // If the class has the objc_runtime_visible attribute, we need to
> +  // use the Objective-C runtime to get the class.
> +  if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
> +    return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);
> +
>    return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID);
>  }
>
>
> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Apr  1 18:23:52 2016
> @@ -5548,6 +5548,9 @@ static void ProcessDeclAttribute(Sema &S
>    case AttributeList::AT_ObjCRuntimeName:
>      handleObjCRuntimeName(S, D, Attr);
>      break;
> +   case AttributeList::AT_ObjCRuntimeVisible:
> +    handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, Attr);
> +    break;
>    case AttributeList::AT_ObjCBoxable:
>      handleObjCBoxable(S, D, Attr);
>      break;
>
> Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=265201&r1=265200&r2=265201&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Fri Apr  1 18:23:52 2016
> @@ -1831,6 +1831,13 @@ Decl *Sema::ActOnStartCategoryImplementa
>    if (IDecl)
>      DiagnoseUseOfDecl(IDecl, ClassLoc);
>
> +  // If the interface has the objc_runtime_visible attribute, we
> +  // cannot implement a category for it.
> +  if (IDecl && IDecl->hasAttr<ObjCRuntimeVisibleAttr>()) {
> +    Diag(ClassLoc, diag::err_objc_runtime_visible_category)
> +      << IDecl->getDeclName();
> +  }
> +
>    /// Check that CatName, category name, is not used in another implementation.
>    if (CatIDecl) {
>      if (CatIDecl->getImplementation()) {
> @@ -1968,6 +1975,16 @@ Decl *Sema::ActOnStartClassImplementatio
>                                          dyn_cast<NamedDecl>(IDecl),
>                                          IMPDecl->getLocation(), 1);
>    }
> +
> +  // If the superclass has the objc_runtime_visible attribute, we
> +  // cannot implement a subclass of it.
> +  if (IDecl->getSuperClass() &&
> +      IDecl->getSuperClass()->hasAttr<ObjCRuntimeVisibleAttr>()) {
> +    Diag(ClassLoc, diag::err_objc_runtime_visible_subclass)
> +      << IDecl->getDeclName()
> +      << IDecl->getSuperClass()->getDeclName();
> +  }
> +
>    return ActOnObjCContainerStartDefinition(IMPDecl);
>  }
>
>
> Added: cfe/trunk/test/CodeGenObjC/attr-objc-runtime-visible.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/attr-objc-runtime-visible.m?rev=265201&view=auto
> ==============================================================================
> --- cfe/trunk/test/CodeGenObjC/attr-objc-runtime-visible.m (added)
> +++ cfe/trunk/test/CodeGenObjC/attr-objc-runtime-visible.m Fri Apr  1 18:23:52 2016
> @@ -0,0 +1,19 @@
> +// RUN: %clang_cc1 -triple x86_64-apple-darwin -fobjc-runtime=macosx-10.9.0 -emit-llvm %s -o - | FileCheck %s
> +
> +// RUN: %clang_cc1 -triple i386-apple-darwin -fobjc-runtime=macosx-fragile-10.9.0 -emit-llvm %s -o - | FileCheck %s
> +
> + at interface Root
> ++(Class)class;
> + at end
> +
> +__attribute__((objc_runtime_visible))
> +__attribute__((objc_runtime_name("MyRuntimeVisibleClass")))
> + at interface A : Root
> + at end
> +
> +// CHECK: [[CLASSNAME:@.*]] = private unnamed_addr constant [22 x i8] c"MyRuntimeVisibleClass
> +// CHECK: define i8* @getClass() #0 {
> +Class getClass(void) {
> +  // CHECK: call i8* @objc_lookUpClass(i8* getelementptr inbounds ([22 x i8], [22 x i8]* [[CLASSNAME]], i32 0, i32 0)) #2
> +  return [A class];
> +}
>
> Added: cfe/trunk/test/SemaObjC/attr-objc-runtime-visible.m
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/attr-objc-runtime-visible.m?rev=265201&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaObjC/attr-objc-runtime-visible.m (added)
> +++ cfe/trunk/test/SemaObjC/attr-objc-runtime-visible.m Fri Apr  1 18:23:52 2016
> @@ -0,0 +1,19 @@
> +// RUN: %clang_cc1 -verify -fsyntax-only  %s
> +
> +__attribute__((objc_runtime_visible))
> + at interface A
> + at end
> +
> + at interface A(X)
> + at end
> +
> + at implementation A(X) // expected-error{{cannot implement a category for class 'A' that is only visible via the Objective-C runtime}}
> + at end
> +
> + at interface B : A
> + at end
> +
> + at implementation B // expected-error{{cannot implement subclass 'B' of a superclass 'A' that is only visible via the Objective-C runtime}}
> + at end
> +
> +
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


More information about the cfe-commits mailing list