Author: Anastasia Stulova Date: 2021-02-03T12:48:21Z New Revision: e635feb15a91e6eeb77876031be2811e63d542f3
URL: https://github.com/llvm/llvm-project/commit/e635feb15a91e6eeb77876031be2811e63d542f3 DIFF: https://github.com/llvm/llvm-project/commit/e635feb15a91e6eeb77876031be2811e63d542f3.diff LOG: [OpenCL] Fix address space in binding of initializer lists to referencs Prevent materializing temporaries in the address space of the references they are bind to. The temporaries should always be in the same address space - private for OpenCL. Tags: #clang Differential Revision: https://reviews.llvm.org/D95608 Added: Modified: clang/lib/Sema/SemaInit.cpp clang/test/CodeGenOpenCLCXX/addrspace-references.cl clang/test/SemaOpenCLCXX/address-space-references.cl Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index f4493d84238d..4e3547c5121f 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4289,17 +4289,36 @@ static void TryReferenceListInitialization(Sema &S, if (Sequence.step_begin() != Sequence.step_end()) Sequence.RewrapReferenceInitList(cv1T1, InitList); } - + // Perform address space compatibility check. + QualType cv1T1IgnoreAS = cv1T1; + if (T1Quals.hasAddressSpace()) { + Qualifiers T2Quals; + (void)S.Context.getUnqualifiedArrayType(InitList->getType(), T2Quals); + if (!T1Quals.isAddressSpaceSupersetOf(T2Quals)) { + Sequence.SetFailed( + InitializationSequence::FK_ReferenceInitDropsQualifiers); + return; + } + // Ignore address space of reference type at this point and perform address + // space conversion after the reference binding step. + cv1T1IgnoreAS = + S.Context.getQualifiedType(T1, T1Quals.withoutAddressSpace()); + } // Not reference-related. Create a temporary and bind to that. - InitializedEntity TempEntity = InitializedEntity::InitializeTemporary(cv1T1); + InitializedEntity TempEntity = + InitializedEntity::InitializeTemporary(cv1T1IgnoreAS); TryListInitialization(S, TempEntity, Kind, InitList, Sequence, TreatUnavailableAsInvalid); if (Sequence) { if (DestType->isRValueReferenceType() || - (T1Quals.hasConst() && !T1Quals.hasVolatile())) - Sequence.AddReferenceBindingStep(cv1T1, /*BindingTemporary=*/true); - else + (T1Quals.hasConst() && !T1Quals.hasVolatile())) { + Sequence.AddReferenceBindingStep(cv1T1IgnoreAS, + /*BindingTemporary=*/true); + if (T1Quals.hasAddressSpace()) + Sequence.AddQualificationConversionStep( + cv1T1, DestType->isRValueReferenceType() ? VK_XValue : VK_LValue); + } else Sequence.SetFailed( InitializationSequence::FK_NonConstLValueReferenceBindingToTemporary); } diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl index 056168684d2d..6d4bece1a624 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl @@ -1,8 +1,16 @@ -//RUN: %clang_cc1 %s -cl-std=clc++ -triple spir -emit-llvm -o - | FileCheck %s +//RUN: %clang_cc1 %s -cl-std=clc++ -triple spir -emit-llvm -o - -O0 | FileCheck %s + +typedef short short2 __attribute__((ext_vector_type(2))); int bar(const unsigned int &i); -// CHECK-LABEL: define{{.*}} spir_func void @_Z3foov() -void foo() { + +class C { +public: + void bar(const short2 &); +}; + +// CHECK-LABEL: define{{.*}} spir_func void @_Z6scalarv() +void scalar() { // The generic addr space reference parameter object will be bound // to a temporary value allocated in private addr space. We need an // addrspacecast before passing the value to the function. @@ -12,3 +20,14 @@ void foo() { // CHECK: call spir_func i32 @_Z3barRU3AS4Kj(i32 addrspace(4)* align 4 dereferenceable(4) [[REG]]) bar(1); } + +// Test list initialization +// CHECK-LABEL: define{{.*}} spir_func void @_Z4listv() +void list() { + C c1; +// CHECK: [[REF:%.*]] = alloca <2 x i16> +// CHECK: store <2 x i16> <i16 1, i16 2>, <2 x i16>* [[REF]] +// CHECK: [[REG:%[.a-z0-9]+]] = addrspacecast <2 x i16>* [[REF]] to <2 x i16> addrspace(4)* +// CHECK: call {{.*}}void @_ZNU3AS41C3barERU3AS4KDv2_s(%class.C addrspace(4)* {{.*}}, <2 x i16> addrspace(4)*{{.*}} [[REG]]) + c1.bar({1, 2}); +} diff --git a/clang/test/SemaOpenCLCXX/address-space-references.cl b/clang/test/SemaOpenCLCXX/address-space-references.cl index 66cd1c02e32f..05e789a7d4fd 100644 --- a/clang/test/SemaOpenCLCXX/address-space-references.cl +++ b/clang/test/SemaOpenCLCXX/address-space-references.cl @@ -10,8 +10,20 @@ int bar(const __global unsigned int &i); // expected-note{{passing argument to p // can't detect this case and therefore fails. int bar(const unsigned int &i); +typedef short short2 __attribute__((ext_vector_type(2))); +class C { +public: + void gen(const short2 &); + void glob(__global const short2 &); //expected-note{{passing argument to parameter here}} + void nested_list(const short2 (&)[2]); +}; + void foo() { bar(1); // expected-error{{binding reference of type 'const __global unsigned int' to value of type 'int' changes address space}} + C c; + c.gen({1, 2}); + c.glob({1, 2}); //expected-error{{binding reference of type 'const __global short2' (vector of 2 'short' values) to value of type 'void' changes address space}} + c.nested_list({{1, 2}, {3, 4}}); } // Test addr space conversion with nested pointers _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits