[clang] b660abc - [ObjC] Add a command line flag that disables recognition of objc_direct for testability

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 6 08:17:56 PDT 2021


Author: Erik Pilkington
Date: 2021-04-06T11:17:01-04:00
New Revision: b660abc80d0d0943c54e9440636ddfa89c2d626d

URL: https://github.com/llvm/llvm-project/commit/b660abc80d0d0943c54e9440636ddfa89c2d626d
DIFF: https://github.com/llvm/llvm-project/commit/b660abc80d0d0943c54e9440636ddfa89c2d626d.diff

LOG: [ObjC] Add a command line flag that disables recognition of objc_direct for testability

Programmers would like to be able to test direct methods by calling them from a
different linkage unit or mocking them, both of which are impossible. This
patch adds a flag that effectively disables the attribute, which will fix this
when enabled in testable builds. rdar://71190891

Differential revision: https://reviews.llvm.org/D95845

Added: 
    clang/test/CodeGenObjC/disable-direct-method.m
    clang/test/SemaObjC/disable-direct-method.m

Modified: 
    clang/include/clang/AST/DeclObjC.h
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Driver/Options.td
    clang/lib/AST/DeclObjC.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Sema/SemaDeclObjC.cpp
    clang/test/Driver/clang_f_opts.c

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index b1bce069920c..6bb9cdf67034 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -852,9 +852,7 @@ class ObjCPropertyDecl : public NamedDecl {
   bool isClassProperty() const {
     return PropertyAttributes & ObjCPropertyAttribute::kind_class;
   }
-  bool isDirectProperty() const {
-    return PropertyAttributes & ObjCPropertyAttribute::kind_direct;
-  }
+  bool isDirectProperty() const;
 
   ObjCPropertyQueryKind getQueryKind() const {
     return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :

diff  --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index 1560a1f38aeb..b29dae5e2076 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -298,6 +298,8 @@ LANGOPT(ObjCSubscriptingLegacyRuntime         , 1, 0, "Subscripting support in l
 BENIGN_LANGOPT(CompatibilityQualifiedIdBlockParamTypeChecking, 1, 0,
                "compatibility mode for type checking block parameters "
                "involving qualified id types")
+LANGOPT(ObjCDisableDirectMethodsForTesting, 1, 0,
+        "Disable recognition of objc_direct methods")
 LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled")
 LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map")
 ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode")

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 38977cc0b874..1a71d68ec4e2 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2225,6 +2225,12 @@ def fobjc_nonfragile_abi : Flag<["-"], "fobjc-nonfragile-abi">, Group<f_Group>;
 def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Group>;
 
 def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>;
+def fobjc_disable_direct_methods_for_testing :
+  Flag<["-"], "fobjc-disable-direct-methods-for-testing">,
+  Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"Ignore attribute objc_direct so that direct methods can be tested">,
+  MarshallingInfoFlag<LangOpts<"ObjCDisableDirectMethodsForTesting">>;
+
 def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>;
 def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, FlangOption, FC1Option]>,
   HelpText<"Parse OpenMP pragmas and generate parallel code.">;

diff  --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index 5f82fcec90e3..6e790f03b027 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -826,7 +826,8 @@ ObjCMethodDecl *ObjCMethodDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
 }
 
 bool ObjCMethodDecl::isDirectMethod() const {
-  return hasAttr<ObjCDirectAttr>();
+  return hasAttr<ObjCDirectAttr>() &&
+         !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
 }
 
 bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
@@ -2295,6 +2296,11 @@ QualType ObjCPropertyDecl::getUsageType(QualType objectType) const {
                                       ObjCSubstitutionContext::Property);
 }
 
+bool ObjCPropertyDecl::isDirectProperty() const {
+  return (PropertyAttributes & ObjCPropertyAttribute::kind_direct) &&
+         !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
+}
+
 //===----------------------------------------------------------------------===//
 // ObjCPropertyImplDecl
 //===----------------------------------------------------------------------===//

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 96a43656bf99..aaf6f83a0cfa 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3665,6 +3665,9 @@ static void RenderObjCOptions(const ToolChain &TC, const Driver &D,
       WeakArg->render(Args, CmdArgs);
     }
   }
+
+  if (Args.hasArg(options::OPT_fobjc_disable_direct_methods_for_testing))
+    CmdArgs.push_back("-fobjc-disable-direct-methods-for-testing");
 }
 
 static void RenderDiagnosticsOptions(const Driver &D, const ArgList &Args,

diff  --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 60253a82e93a..e0f8c6e92d5a 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -4407,10 +4407,12 @@ class OverrideSearch {
 
 void Sema::CheckObjCMethodDirectOverrides(ObjCMethodDecl *method,
                                           ObjCMethodDecl *overridden) {
-  if (const auto *attr = overridden->getAttr<ObjCDirectAttr>()) {
+  if (overridden->isDirectMethod()) {
+    const auto *attr = overridden->getAttr<ObjCDirectAttr>();
     Diag(method->getLocation(), diag::err_objc_override_direct_method);
     Diag(attr->getLocation(), diag::note_previous_declaration);
-  } else if (const auto *attr = method->getAttr<ObjCDirectAttr>()) {
+  } else if (method->isDirectMethod()) {
+    const auto *attr = method->getAttr<ObjCDirectAttr>();
     Diag(attr->getLocation(), diag::err_objc_direct_on_override)
         << isa<ObjCProtocolDecl>(overridden->getDeclContext());
     Diag(overridden->getLocation(), diag::note_previous_declaration);
@@ -4856,7 +4858,8 @@ Decl *Sema::ActOnMethodDeclaration(
     // the canonical declaration.
     if (!ObjCMethod->isDirectMethod()) {
       const ObjCMethodDecl *CanonicalMD = ObjCMethod->getCanonicalDecl();
-      if (const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>()) {
+      if (CanonicalMD->isDirectMethod()) {
+        const auto *attr = CanonicalMD->getAttr<ObjCDirectAttr>();
         ObjCMethod->addAttr(
             ObjCDirectAttr::CreateImplicit(Context, attr->getLocation()));
       }
@@ -4901,14 +4904,16 @@ Decl *Sema::ActOnMethodDeclaration(
             Diag(IMD->getLocation(), diag::note_previous_declaration);
           };
 
-          if (const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>()) {
+          if (ObjCMethod->isDirectMethod()) {
+            const auto *attr = ObjCMethod->getAttr<ObjCDirectAttr>();
             if (ObjCMethod->getCanonicalDecl() != IMD) {
               diagContainerMismatch();
             } else if (!IMD->isDirectMethod()) {
               Diag(attr->getLocation(), diag::err_objc_direct_missing_on_decl);
               Diag(IMD->getLocation(), diag::note_previous_declaration);
             }
-          } else if (const auto *attr = IMD->getAttr<ObjCDirectAttr>()) {
+          } else if (IMD->isDirectMethod()) {
+            const auto *attr = IMD->getAttr<ObjCDirectAttr>();
             if (ObjCMethod->getCanonicalDecl() != IMD) {
               diagContainerMismatch();
             } else {

diff  --git a/clang/test/CodeGenObjC/disable-direct-method.m b/clang/test/CodeGenObjC/disable-direct-method.m
new file mode 100644
index 000000000000..fb5d5702fa30
--- /dev/null
+++ b/clang/test/CodeGenObjC/disable-direct-method.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -fobjc-disable-direct-methods-for-testing %s -o - | FileCheck %s
+
+ at interface Y
+ at property (direct) int direct_property;
+ at end
+ at implementation Y @end
+
+// CHECK: @OBJC_PROP_NAME_ATTR_ = private unnamed_addr constant [16 x i8] c"direct_property\00"
+// CHECK: @"_OBJC_$_PROP_LIST_Y" =
+// CHECK-SAME: @OBJC_PROP_NAME_ATTR_,
+
+ at interface X
+-(void)m __attribute__((objc_direct));
+ at end
+
+// CHECK-LABEL: define void @f
+void f(X *x) {
+  [x m];
+
+  // CHECK: call void bitcast ({{.*}} @objc_msgSend to {{.*}})
+}

diff  --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index 12369361f811..3ea9410adbea 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -576,3 +576,8 @@
 
 // RUN: %clang -### -S -fno-temp-file %s 2>&1 | FileCheck -check-prefix=CHECK-NO-TEMP-FILE %s
 // CHECK-NO-TEMP-FILE: "-fno-temp-file"
+
+// RUN: %clang -### -xobjective-c -fobjc-disable-direct-methods-for-testing %s 2>&1 | FileCheck -check-prefix=CHECK_DISABLE_DIRECT %s
+// RUN: %clang -### -xobjective-c %s 2>&1 | FileCheck -check-prefix=CHECK_NO_DISABLE_DIRECT %s
+// CHECK_DISABLE_DIRECT: -fobjc-disable-direct-methods-for-testing
+// CHECK_NO_DISABLE_DIRECT-NOT: -fobjc-disable-direct-methods-for-testing

diff  --git a/clang/test/SemaObjC/disable-direct-method.m b/clang/test/SemaObjC/disable-direct-method.m
new file mode 100644
index 000000000000..a6fdaba33551
--- /dev/null
+++ b/clang/test/SemaObjC/disable-direct-method.m
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -verify -fobjc-disable-direct-methods-for-testing %s
+
+// expected-no-diagnostics
+
+#define DIRECT __attribute__((objc_direct))
+#define DIRECT_MEMBERS __attribute__((objc_direct_members))
+
+__attribute__((objc_root_class))
+ at interface X
+-(void)direct_method DIRECT;
+ at end
+
+ at implementation X
+-(void)direct_method DIRECT {}
+ at end
+
+__attribute__((objc_root_class))
+DIRECT_MEMBERS
+ at interface Y
+-(void)direct_method2;
+ at end
+
+ at implementation Y
+-(void)direct_method2 {}
+ at end
+
+__attribute__((objc_root_class))
+ at interface Z
+ at property (direct) int direct_property;
+ at end
+
+ at implementation Z @end


        


More information about the cfe-commits mailing list