forked from OSchip/llvm-project
[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
This commit is contained in:
parent
844012940e
commit
b660abc80d
|
@ -852,9 +852,7 @@ public:
|
|||
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 :
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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.">;
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -4407,10 +4407,12 @@ private:
|
|||
|
||||
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 {
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -fobjc-disable-direct-methods-for-testing %s -o - | FileCheck %s
|
||||
|
||||
@interface Y
|
||||
@property (direct) int direct_property;
|
||||
@end
|
||||
@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_,
|
||||
|
||||
@interface X
|
||||
-(void)m __attribute__((objc_direct));
|
||||
@end
|
||||
|
||||
// CHECK-LABEL: define void @f
|
||||
void f(X *x) {
|
||||
[x m];
|
||||
|
||||
// CHECK: call void bitcast ({{.*}} @objc_msgSend to {{.*}})
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
@interface X
|
||||
-(void)direct_method DIRECT;
|
||||
@end
|
||||
|
||||
@implementation X
|
||||
-(void)direct_method DIRECT {}
|
||||
@end
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
DIRECT_MEMBERS
|
||||
@interface Y
|
||||
-(void)direct_method2;
|
||||
@end
|
||||
|
||||
@implementation Y
|
||||
-(void)direct_method2 {}
|
||||
@end
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface Z
|
||||
@property (direct) int direct_property;
|
||||
@end
|
||||
|
||||
@implementation Z @end
|
Loading…
Reference in New Issue