diff options
| author | Akira Hatanaka <ahatanaka@apple.com> | 2018-02-05 20:23:22 +0000 |
|---|---|---|
| committer | Akira Hatanaka <ahatanaka@apple.com> | 2018-02-05 20:23:22 +0000 |
| commit | 02914dc1278cf9b472e9cd4357d641b5dd3f5834 (patch) | |
| tree | ea2b88bc4177716dd38b8cacae2c87d7d90567ff /clang/test | |
| parent | 02f6845095ee1ea0e54824a650a8f4c5d0ffd156 (diff) | |
| download | bcm5719-llvm-02914dc1278cf9b472e9cd4357d641b5dd3f5834.tar.gz bcm5719-llvm-02914dc1278cf9b472e9cd4357d641b5dd3f5834.zip | |
Add support for attribute 'trivial_abi'.
The 'trivial_abi' attribute can be applied to a C++ class, struct, or
union. It makes special functions of the annotated class (the destructor
and copy/move constructors) to be trivial for the purpose of calls and,
as a result, enables the annotated class or containing classes to be
passed or returned using the C ABI for the underlying type.
When a type that is considered trivial for the purpose of calls despite
having a non-trivial destructor (which happens only when the class type
or one of its subobjects is a 'trivial_abi' class) is passed to a
function, the callee is responsible for destroying the object.
For more background, see the discussions that took place on the mailing
list:
http://lists.llvm.org/pipermail/cfe-dev/2017-November/055955.html
http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20180101/thread.html#214043
rdar://problem/35204524
Differential Revision: https://reviews.llvm.org/D41039
llvm-svn: 324269
Diffstat (limited to 'clang/test')
| -rw-r--r-- | clang/test/CodeGenCXX/trivial_abi.cpp | 239 | ||||
| -rw-r--r-- | clang/test/CodeGenObjCXX/trivial_abi.mm | 104 | ||||
| -rw-r--r-- | clang/test/Misc/pragma-attribute-supported-attributes-list.test | 3 | ||||
| -rw-r--r-- | clang/test/SemaObjCXX/attr-trivial-abi.mm | 93 |
4 files changed, 438 insertions, 1 deletions
diff --git a/clang/test/CodeGenCXX/trivial_abi.cpp b/clang/test/CodeGenCXX/trivial_abi.cpp new file mode 100644 index 00000000000..2cf07b22581 --- /dev/null +++ b/clang/test/CodeGenCXX/trivial_abi.cpp @@ -0,0 +1,239 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s + +// CHECK: %[[STRUCT_SMALL:.*]] = type { i32* } +// CHECK: %[[STRUCT_LARGE:.*]] = type { i32*, [128 x i32] } +// CHECK: %[[STRUCT_TRIVIAL:.*]] = type { i32 } +// CHECK: %[[STRUCT_NONTRIVIAL:.*]] = type { i32 } + +struct __attribute__((trivial_abi)) Small { + int *p; + Small(); + ~Small(); + Small(const Small &) noexcept; + Small &operator=(const Small &); +}; + +struct __attribute__((trivial_abi)) Large { + int *p; + int a[128]; + Large(); + ~Large(); + Large(const Large &) noexcept; + Large &operator=(const Large &); +}; + +struct Trivial { + int a; +}; + +struct NonTrivial { + NonTrivial(); + ~NonTrivial(); + int a; +}; + +struct HasTrivial { + Small s; + Trivial m; +}; + +struct HasNonTrivial { + Small s; + NonTrivial m; +}; + +// CHECK: define void @_Z14testParamSmall5Small(i64 %[[A_COERCE:.*]]) +// CHECK: %[[A:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[A]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i32* +// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[A]]) +// CHECK: ret void +// CHECK: } + +void testParamSmall(Small a) noexcept { +} + +// CHECK: define i64 @_Z15testReturnSmallv() +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[RETVAL]]) +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 +// CHECK: ret i64 %[[COERCE_VAL_PI]] +// CHECK: } + +Small testReturnSmall() { + Small t; + return t; +} + +// CHECK: define void @_Z14testCallSmall0v() +// CHECK: %[[T:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[T]]) +// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallC1ERKS_(%[[STRUCT_SMALL]]* %[[AGG_TMP]], %[[STRUCT_SMALL]]* dereferenceable(8) %[[T]]) +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 +// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 +// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) +// CHECK: %[[CALL2:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[T]]) +// CHECK: ret void +// CHECK: } + +void testCallSmall0() { + Small t; + testParamSmall(t); +} + +// CHECK: define void @_Z14testCallSmall1v() +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 +// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* +// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_DIVE1:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP]], i32 0, i32 0 +// CHECK: %[[V0:.*]] = load i32*, i32** %[[COERCE_DIVE1]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i32* %[[V0]] to i64 +// CHECK: call void @_Z14testParamSmall5Small(i64 %[[COERCE_VAL_PI]]) +// CHECK: ret void +// CHECK: } + +void testCallSmall1() { + testParamSmall(testReturnSmall()); +} + +// CHECK: define void @_Z16testIgnoredSmallv() +// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_SMALL:.*]], align 8 +// CHECK: %[[CALL:.*]] = call i64 @_Z15testReturnSmallv() +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_SMALL]], %[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[CALL]] to i32* +// CHECK: store i32* %[[COERCE_VAL_IP]], i32** %[[COERCE_DIVE]], align 8 +// CHECK: %[[CALL1:.*]] = call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP_ENSURED]]) +// CHECK: ret void +// CHECK: } + +void testIgnoredSmall() { + testReturnSmall(); +} + +// CHECK: define void @_Z14testParamLarge5Large(%[[STRUCT_LARGE:.*]]* %[[A:.*]]) +// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[A]]) +// CHECK: ret void +// CHECK: } + +void testParamLarge(Large a) noexcept { +} + +// CHECK: define void @_Z15testReturnLargev(%[[STRUCT_LARGE:.*]]* noalias sret %[[AGG_RESULT:.*]]) +// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_RESULT]]) +// CHECK: ret void +// CHECK: } + +Large testReturnLarge() { + Large t; + return t; +} + +// CHECK: define void @_Z14testCallLarge0v() +// CHECK: %[[T:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[T]]) +// CHECK: %[[CALL1:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeC1ERKS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* dereferenceable(520) %[[T]]) +// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) +// CHECK: %[[CALL2:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[T]]) +// CHECK: ret void +// CHECK: } + +void testCallLarge0() { + Large t; + testParamLarge(t); +} + +// CHECK: define void @_Z14testCallLarge1v() +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 +// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP]]) +// CHECK: call void @_Z14testParamLarge5Large(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) +// CHECK: ret void +// CHECK: } + +void testCallLarge1() { + testParamLarge(testReturnLarge()); +} + +// CHECK: define void @_Z16testIgnoredLargev() +// CHECK: %[[AGG_TMP_ENSURED:.*]] = alloca %[[STRUCT_LARGE:.*]], align 8 +// CHECK: call void @_Z15testReturnLargev(%[[STRUCT_LARGE]]* sret %[[AGG_TMP_ENSURED]]) +// CHECK: %[[CALL:.*]] = call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP_ENSURED]]) +// CHECK: ret void +// CHECK: } + +void testIgnoredLarge() { + testReturnLarge(); +} + +// CHECK: define i64 @_Z20testReturnHasTrivialv() +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_TRIVIAL:.*]], align 4 +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_TRIVIAL]], %[[STRUCT_TRIVIAL]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[V0:.*]] = load i32, i32* %[[COERCE_DIVE]], align 4 +// CHECK: %[[COERCE_VAL_II:.*]] = zext i32 %[[V0]] to i64 +// CHECK: ret i64 %[[COERCE_VAL_II]] +// CHECK: } + +Trivial testReturnHasTrivial() { + Trivial t; + return t; +} + +// CHECK: define void @_Z23testReturnHasNonTrivialv(%[[STRUCT_NONTRIVIAL:.*]]* noalias sret %[[AGG_RESULT:.*]]) +// CHECK: %[[CALL:.*]] = call %[[STRUCT_NONTRIVIAL]]* @_ZN10NonTrivialC1Ev(%[[STRUCT_NONTRIVIAL]]* %[[AGG_RESULT]]) +// CHECK: ret void +// CHECK: } + +NonTrivial testReturnHasNonTrivial() { + NonTrivial t; + return t; +} + +// CHECK: define void @_Z18testExceptionSmallv() +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_SMALL]], align 8 +// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) +// CHECK: invoke %[[STRUCT_SMALL]]* @_ZN5SmallC1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP1]]) + +// CHECK: call void @_Z20calleeExceptionSmall5SmallS_(i64 %{{.*}}, i64 %{{.*}}) +// CHECK-NEXT: ret void + +// CHECK: landingpad { i8*, i32 } +// CHECK: call %[[STRUCT_SMALL]]* @_ZN5SmallD1Ev(%[[STRUCT_SMALL]]* %[[AGG_TMP]]) +// CHECK: br + +// CHECK: resume { i8*, i32 } + +void calleeExceptionSmall(Small, Small); + +void testExceptionSmall() { + calleeExceptionSmall(Small(), Small()); +} + +// CHECK: define void @_Z18testExceptionLargev() +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_LARGE]], align 8 +// CHECK: %[[AGG_TMP1:.*]] = alloca %[[STRUCT_LARGE]], align 8 +// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) +// CHECK: invoke %[[STRUCT_LARGE]]* @_ZN5LargeC1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP1]]) + +// CHECK: call void @_Z20calleeExceptionLarge5LargeS_(%[[STRUCT_LARGE]]* %[[AGG_TMP]], %[[STRUCT_LARGE]]* %[[AGG_TMP1]]) +// CHECK-NEXT: ret void + +// CHECK: landingpad { i8*, i32 } +// CHECK: call %[[STRUCT_LARGE]]* @_ZN5LargeD1Ev(%[[STRUCT_LARGE]]* %[[AGG_TMP]]) +// CHECK: br + +// CHECK: resume { i8*, i32 } + +void calleeExceptionLarge(Large, Large); + +void testExceptionLarge() { + calleeExceptionLarge(Large(), Large()); +} diff --git a/clang/test/CodeGenObjCXX/trivial_abi.mm b/clang/test/CodeGenObjCXX/trivial_abi.mm new file mode 100644 index 00000000000..7d84338a4b0 --- /dev/null +++ b/clang/test/CodeGenObjCXX/trivial_abi.mm @@ -0,0 +1,104 @@ +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fobjc-arc -fobjc-weak -fobjc-runtime-has-weak -fclang-abi-compat=4.0 -emit-llvm -o - %s | FileCheck %s + +// CHECK: %[[STRUCT_STRONGWEAK:.*]] = type { i8*, i8* } +// CHECK: %[[STRUCT_STRONG:.*]] = type { i8* } +// CHECK: %[[STRUCT_S:.*]] = type { i8* } + +struct __attribute__((trivial_abi)) StrongWeak { + id fstrong; + __weak id fweak; +}; + +struct __attribute__((trivial_abi)) Strong { + id fstrong; +}; + +template<class T> +struct __attribute__((trivial_abi)) S { + T a; +}; + +// CHECK: define void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %{{.*}}) +// CHECK-NOT: call +// CHECK: ret void + +void testParamStrongWeak(StrongWeak a) { +} + +// CHECK: define void @_Z18testCallStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[A:.*]]) +// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8 +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONGWEAK]], align 8 +// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]]) +// CHECK: call void @_Z19testParamStrongWeak10StrongWeak(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]]) +// CHECK: %[[CALL1:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakD1Ev(%[[STRUCT_STRONGWEAK]]* %[[AGG_TMP]]) +// CHECK: ret void + +void testCallStrongWeak(StrongWeak *a) { + testParamStrongWeak(*a); +} + +// CHECK: define void @_Z20testReturnStrongWeakP10StrongWeak(%[[STRUCT_STRONGWEAK:.*]]* noalias sret %[[AGG_RESULT:.*]], %[[STRUCT_STRONGWEAK]]* %[[A:.*]]) +// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONGWEAK]]*, align 8 +// CHECK: store %[[STRUCT_STRONGWEAK]]* %[[A]], %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONGWEAK]]*, %[[STRUCT_STRONGWEAK]]** %[[A_ADDR]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONGWEAK]]* @_ZN10StrongWeakC1ERKS_(%[[STRUCT_STRONGWEAK]]* %[[AGG_RESULT]], %[[STRUCT_STRONGWEAK]]* dereferenceable(16) %[[V0]]) +// CHECK: ret void + +StrongWeak testReturnStrongWeak(StrongWeak *a) { + return *a; +} + +// CHECK: define void @_Z15testParamStrong6Strong(i64 %[[A_COERCE:.*]]) +// CHECK: %[[A:.*]] = alloca %[[STRUCT_STRONG]], align 8 +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[A]], i32 0, i32 0 +// CHECK: %[[COERCE_VAL_IP:.*]] = inttoptr i64 %[[A_COERCE]] to i8* +// CHECK: store i8* %[[COERCE_VAL_IP]], i8** %[[COERCE_DIVE]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev(%[[STRUCT_STRONG]]* %[[A]]) +// CHECK: ret void + +// CHECK: define linkonce_odr %[[STRUCT_STRONG]]* @_ZN6StrongD1Ev( + +void testParamStrong(Strong a) { +} + +// CHECK: define void @_Z14testCallStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]]) +// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8 +// CHECK: %[[AGG_TMP:.*]] = alloca %[[STRUCT_STRONG]], align 8 +// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[AGG_TMP]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]]) +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[AGG_TMP]], i32 0, i32 0 +// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64 +// CHECK: call void @_Z15testParamStrong6Strong(i64 %[[COERCE_VAL_PI]]) +// CHECK: ret void + +void testCallStrong(Strong *a) { + testParamStrong(*a); +} + +// CHECK: define i64 @_Z16testReturnStrongP6Strong(%[[STRUCT_STRONG]]* %[[A:.*]]) +// CHECK: entry: +// CHECK: %[[RETVAL:.*]] = alloca %[[STRUCT_STRONG]], align 8 +// CHECK: %[[A_ADDR:.*]] = alloca %[[STRUCT_STRONG]]*, align 8 +// CHECK: store %[[STRUCT_STRONG]]* %[[A]], %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8 +// CHECK: %[[V0:.*]] = load %[[STRUCT_STRONG]]*, %[[STRUCT_STRONG]]** %[[A_ADDR]], align 8 +// CHECK: %[[CALL:.*]] = call %[[STRUCT_STRONG]]* @_ZN6StrongC1ERKS_(%[[STRUCT_STRONG]]* %[[RETVAL]], %[[STRUCT_STRONG]]* dereferenceable(8) %[[V0]]) +// CHECK: %[[COERCE_DIVE:.*]] = getelementptr inbounds %[[STRUCT_STRONG]], %[[STRUCT_STRONG]]* %[[RETVAL]], i32 0, i32 0 +// CHECK: %[[V1:.*]] = load i8*, i8** %[[COERCE_DIVE]], align 8 +// CHECK: %[[COERCE_VAL_PI:.*]] = ptrtoint i8* %[[V1]] to i64 +// CHECK: ret i64 %[[COERCE_VAL_PI]] + +Strong testReturnStrong(Strong *a) { + return *a; +} + +// CHECK: define void @_Z21testParamWeakTemplate1SIU6__weakP11objc_objectE(%[[STRUCT_S]]* %{{.*}}) +// CHECK-NOT: call +// CHECK: ret void + +void testParamWeakTemplate(S<__weak id> a) { +} diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 1171a2d3709..1004459e9a1 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -2,7 +2,7 @@ // The number of supported attributes should never go down! -// CHECK: #pragma clang attribute supports 66 attributes: +// CHECK: #pragma clang attribute supports 67 attributes: // CHECK-NEXT: AMDGPUFlatWorkGroupSize (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumSGPR (SubjectMatchRule_function) // CHECK-NEXT: AMDGPUNumVGPR (SubjectMatchRule_function) @@ -66,6 +66,7 @@ // CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local) // CHECK-NEXT: Target (SubjectMatchRule_function) // CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member) +// CHECK-NEXT: TrivialABI (SubjectMatchRule_record) // CHECK-NEXT: WarnUnusedResult (SubjectMatchRule_objc_method, SubjectMatchRule_enum, SubjectMatchRule_record, SubjectMatchRule_hasType_functionType) // CHECK-NEXT: XRayInstrument (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: XRayLogArgs (SubjectMatchRule_function, SubjectMatchRule_objc_method) diff --git a/clang/test/SemaObjCXX/attr-trivial-abi.mm b/clang/test/SemaObjCXX/attr-trivial-abi.mm new file mode 100644 index 00000000000..c83a94dcd98 --- /dev/null +++ b/clang/test/SemaObjCXX/attr-trivial-abi.mm @@ -0,0 +1,93 @@ +// RUN: %clang_cc1 -std=c++11 -fobjc-runtime-has-weak -fobjc-weak -fobjc-arc -fsyntax-only -verify %s + +void __attribute__((trivial_abi)) foo(); // expected-warning {{'trivial_abi' attribute only applies to classes}} + +struct [[clang::trivial_abi]] S0 { + int a; +}; + +struct __attribute__((trivial_abi)) S1 { + int a; +}; + +struct __attribute__((trivial_abi)) S2 { // expected-warning {{'trivial_abi' cannot be applied to 'S2'}} + __weak id a; +}; + +struct __attribute__((trivial_abi)) S3 { // expected-warning {{'trivial_abi' cannot be applied to 'S3'}} + virtual void m(); +}; + +struct S4 { + int a; +}; + +struct __attribute__((trivial_abi)) S5 : public virtual S4 { // expected-warning {{'trivial_abi' cannot be applied to 'S5'}} +}; + +struct __attribute__((trivial_abi)) S9 : public S4 { +}; + +struct S6 { + __weak id a; +}; + +struct __attribute__((trivial_abi)) S12 { // expected-warning {{'trivial_abi' cannot be applied to 'S12'}} + __weak id a; +}; + +struct __attribute__((trivial_abi)) S13 { // expected-warning {{'trivial_abi' cannot be applied to 'S13'}} + __weak id a[2]; +}; + +struct __attribute__((trivial_abi)) S7 { // expected-warning {{'trivial_abi' cannot be applied to 'S7'}} + S6 a; +}; + +struct __attribute__((trivial_abi)) S11 { // expected-warning {{'trivial_abi' cannot be applied to 'S11'}} + S6 a[2]; +}; + +struct __attribute__((trivial_abi(1))) S8 { // expected-error {{'trivial_abi' attribute takes no arguments}} + int a; +}; + +// Do not warn when 'trivial_abi' is used to annotate a template class. +template<class T> +struct __attribute__((trivial_abi)) S10 { + T p; +}; + +S10<int *> p1; +S10<__weak id> p2; + +template<> +struct __attribute__((trivial_abi)) S10<id> { // expected-warning {{'trivial_abi' cannot be applied to 'S10<id>'}} + __weak id a; +}; + +template<class T> +struct S14 { + T a; + __weak id b; +}; + +template<class T> +struct __attribute__((trivial_abi)) S15 : S14<T> { +}; + +S15<int> s15; + +template<class T> +struct __attribute__((trivial_abi)) S16 { + S14<T> a; +}; + +S16<int> s16; + +template<class T> +struct __attribute__((trivial_abi)) S17 { // expected-warning {{'trivial_abi' cannot be applied to 'S17'}} + __weak id a; +}; + +S17<int> s17; |

