Files
clang-p2996/clang/test/CodeGenObjC/non-runtime-protocol.m
Nathan Lanza 14f6bfcb52 [clang] Implement objc_non_runtime_protocol to remove protocol metadata
Summary:
Motivated by the new objc_direct attribute, this change adds a new
attribute that remotes metadata from Protocols that the programmer knows
isn't going to be used at runtime. We simply have the frontend skip
generating any protocol metadata entries (e.g. OBJC_CLASS_NAME,
_OBJC_$_PROTOCOL_INSTANCE_METHDOS, _OBJC_PROTOCOL, etc) for a protocol
marked with `__attribute__((objc_non_runtime_protocol))`.

There are a few APIs used to retrieve a protocol at runtime.
`@protocol(SomeProtocol)` will now error out of the requested protocol
is marked with attribute. `objc_getProtocol` will return `NULL` which
is consistent with the behavior of a non-existing protocol.

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D75574
2020-10-02 17:35:50 -04:00

143 lines
5.5 KiB
Objective-C

// RUN: not %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DPROTOEXPR -o - 2>&1 \
// RUN: | FileCheck -check-prefix=PROTOEXPR %s
// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DREDUNDANCY -o - \
// RUN: | FileCheck -check-prefix=REDUNDANCY1 %s
// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DREDUNDANCY -o - \
// RUN: | FileCheck -check-prefix=REDUNDANCY2 %s
// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DBASE -o - \
// RUN: | FileCheck -check-prefix=NONFRAGILE %s
// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -DINHERITANCE -o - \
// RUN: | FileCheck -check-prefix=INHERITANCE %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 %s -DBASE -o - \
// RUN: | FileCheck -check-prefix=FRAGILE %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin -fobjc-runtime=macosx-fragile-10.5 %s -DINHERITANCE -o - \
// RUN: | FileCheck -check-prefix=FRAGILEINHERITANCE %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep %s -DBASE -o - \
// RUN: | FileCheck -check-prefix=GNU %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep %s -DINHERITANCE -o - \
// RUN: | FileCheck -check-prefix=GNUINHERITANCE %s
//
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep-2 %s -DBASE -o - \
// RUN: | FileCheck -check-prefix=GNU2 %s
// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu -fobjc-runtime=gnustep-2 %s -DINHERITANCE -o - \
// RUN: | FileCheck -check-prefix=GNU2INHERITANCE %s
__attribute__((objc_root_class))
@interface Root
@end
@implementation Root
@end
#ifdef REDUNDANCY
// REDUNDANCY1-NOT: _OBJC_CLASS_PROTOCOLS_$_Implementer{{.*}}_OBJC_PROTOCOL_$_B
// REDUNDANCY2: _OBJC_CLASS_PROTOCOLS_$_Implementer{{.*}}_OBJC_PROTOCOL_$_C{{.*}}_OBJC_PROTOCOL_$_A
@protocol C
@end
@protocol B <C>
@end
@protocol A <B>
@end
__attribute__((objc_non_runtime_protocol)) @protocol Alpha<A>
@end
__attribute__((objc_non_runtime_protocol)) @protocol Beta<B>
@end
@interface Implementer : Root <Alpha, Beta, C>
@end
@implementation Implementer
@end
#endif
#ifdef BASE
// Confirm that we're not emitting protocol information for the
// NONFRAGILE-NOT: OBJC_CLASS_NAME{{.*}}NonRuntimeProtocol
// NONFRAGILE-NOT: _OBJC_$_PROTOCOL_INSTANCE_METHODS_NonRuntimeProtocol
// NONFRAGILE-NOT: _OBJC_$_PROTOCOL_CLASS_METHODS_NonRuntimeProtocol
// NONFRAGILE-NOT: _OBJC_PROTOCOL_$_NonRuntimeProtocol
// NONFRAGILE-NOT: _OBJC_LABEL_PROTOCOL_$_NonRuntimeProtocol
// NONFRAGILE-NOT: _OBJC_CLASS_PROTOCOLS_$_NonRuntimeImplementer
// FRAGILE-NOT: OBJC_CLASS_NAME_.{{.*}}"Runtime\00"
// FRAGILE-NOT: OBJC_PROTOCOL_NonRuntime
// FRAGILE_NOT: OBJC_PROTOCOLS_NonRuntimeImplementer
// GNU-NOT: private unnamed_addr constant {{.*}} c"NonRuntimeProtocol\00"
// GNU-NOT: @.objc_protocol {{.*}}
// GNU2-NOT: private unnamed_addr constant {{.*}} c"NonRuntimeProtocol\00"
// GNU2-NOT: @.objc_protocol {{.*}}
__attribute__((objc_non_runtime_protocol))
@protocol NonRuntimeProtocol
- (void)doThing;
+ (void)doClassThing;
@end
// NONFRAGILE: @"_OBJC_METACLASS_RO_$_NonRuntimeImplementer" {{.*}} %struct._objc_protocol_list* null
// NONFRAGILE: @"_OBJC_CLASS_RO_$_NonRuntimeImplementer" {{.*}} %struct._objc_protocol_list* null
@interface NonRuntimeImplementer : Root <NonRuntimeProtocol>
- (void)doThing;
+ (void)doClassThing;
@end
@implementation NonRuntimeImplementer
- (void)doThing {
}
+ (void)doClassThing {
}
@end
#endif
#ifdef PROTOEXPR
__attribute__((objc_non_runtime_protocol))
@protocol NonRuntimeProtocol
@end
void use() {
// PROTOEXPR: cannot use a protocol declared 'objc_non_runtime_protocol' in a @protocol expression
Protocol *p = @protocol(NonRuntimeProtocol);
}
#endif
#ifdef INHERITANCE
// Confirm that we only emit references to the non-runtime protocols and
// properly walk the DAG to find the right protocols.
// INHERITANCE: OBJC_PROTOCOL_$_R2{{.*}}
// INHERITANCE: OBJC_PROTOCOL_$_R3{{.*}}
// INHERITANCE: @"_OBJC_CLASS_PROTOCOLS_$_Implementer" {{.*}}_OBJC_PROTOCOL_$_R2{{.*}}_OBJC_PROTOCOL_$_R3
// FRAGILEINHERITANCE: OBJC_PROTOCOL_R2
// FRAGILEINHERITANCE: OBJC_PROTOCOL_R3
// FRAGILEINHERITANCE: OBJC_CLASS_PROTOCOLS_Implementer{{.*}}OBJC_PROTOCOL_R2{{.*}}OBJC_PROTOCOL_R3
// GNUINHERITANCE-DAG: @[[Proto1:[0-9]]]{{.*}}c"R1\00"
// GNUINHERITANCE-DAG: [[P1Name:@.objc_protocol.[0-9]*]]{{.*}}@[[Proto1]]
// GNUINHERITANCE-DAG: @[[Proto2:[0-9]]]{{.*}}c"R2\00"
// GNUINHERITANCE-DAG: [[P2Name:@.objc_protocol.[0-9]+]]{{.*}}@[[Proto2]]
// GNUINHERITANCE-DAG: @[[Proto3:[0-9]]]{{.*}}c"R3\00"
// GNUINHERITANCE-DAG: [[P3Name:@.objc_protocol.[0-9]+]]{{.*}}@[[Proto3]]
// GNUINHERITANCE-DAG: @.objc_protocol_list{{.*}}
// GNUINHERITANCE: @.objc_protocol_list{{.*}}[[Proto3]]{{.*}}[[Proto2]]
// GNU2INHERITANCE-DAG: @[[Proto1:[0-9]]]{{.*}}c"R1\00"
// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R1{{.*}}@[[Proto1]]
// GNU2INHERITANCE-DAG: @[[Proto2:[0-9]]]{{.*}}c"R2\00"
// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R2{{.*}}@[[Proto2]]
// GNU2INHERITANCE-DAG: @[[Proto3:[0-9]]]{{.*}}c"R3\00"
// GNU2INHERITANCE-DAG: _OBJC_PROTOCOL_R3{{.*}}@[[Proto3]]
// GNU2INHERITANCE: @.objc_protocol_list{{.*}}_OBJC_PROTOCOL_R2{{.*}}_OBJC_PROTOCOL_R3
@protocol R1
@end
@protocol R2
@end
@protocol R3 <R1>
@end
__attribute__((objc_non_runtime_protocol)) @protocol N3
@end
__attribute__((objc_non_runtime_protocol)) @protocol N1<R3, R2, N3>
@end
__attribute__((objc_non_runtime_protocol)) @protocol N2<N1, R2>
@end
@interface Implementer : Root <N2, R2>
@end
@implementation Implementer
@end
#endif