[clang] 642d2f0 - [OpenCL] Fix initialization of __constant constructors without arguments
Ole Strohm via cfe-commits
cfe-commits at lists.llvm.org
Tue May 18 03:07:13 PDT 2021
Author: Ole Strohm
Date: 2021-05-18T10:59:53+01:00
New Revision: 642d2f000b26821010793ea1ea6a38a6695fc864
URL: https://github.com/llvm/llvm-project/commit/642d2f000b26821010793ea1ea6a38a6695fc864
DIFF: https://github.com/llvm/llvm-project/commit/642d2f000b26821010793ea1ea6a38a6695fc864.diff
LOG: [OpenCL] Fix initialization of __constant constructors without arguments
This fixes the initialization of objects in the __constant
address space that occurs when declaring the object.
Fixes part of PR42566
Reviewed By: Anastasia
Differential Revision: https://reviews.llvm.org/D102248
Added:
clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
Modified:
clang/lib/Sema/SemaDecl.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index db267089be965..c4db147e7efde 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -12635,9 +12635,21 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (!Var->isInvalidDecl() &&
Var->getType().getAddressSpace() == LangAS::opencl_constant &&
Var->getStorageClass() != SC_Extern && !Var->getInit()) {
- Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
- Var->setInvalidDecl();
- return;
+ bool HasConstExprDefaultConstructor = false;
+ if (CXXRecordDecl *RD = Var->getType()->getAsCXXRecordDecl()) {
+ for (auto *Ctor : RD->ctors()) {
+ if (Ctor->isConstexpr() && Ctor->getNumParams() == 0 &&
+ Ctor->getMethodQualifiers().getAddressSpace() ==
+ LangAS::opencl_constant) {
+ HasConstExprDefaultConstructor = true;
+ }
+ }
+ }
+ if (!HasConstExprDefaultConstructor) {
+ Diag(Var->getLocation(), diag::err_opencl_constant_no_init);
+ Var->setInvalidDecl();
+ return;
+ }
}
if (!Var->isInvalidDecl() && RealDecl->hasAttr<LoaderUninitializedAttr>()) {
diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp b/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
new file mode 100644
index 0000000000000..5d81bc57603e7
--- /dev/null
+++ b/clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck %s
+
+// CHECK: %struct.X = type { i32 }
+
+// CHECK: @ci = dso_local addrspace(2) constant i32 0
+// CHECK: @gi = dso_local addrspace(1) global i32 0
+__constant int ci = 0;
+__global int gi = 0;
+
+struct X {
+ int x;
+
+ // Local variables are handled in local_addrspace_init.clcpp
+ // FIXME: __private and __generic constructors clash for __private variable
+ // X() /*__generic*/ = default;
+ X() __private : x(0) {}
+ X() __global : x(0) {}
+ constexpr X() __constant : x(0) {}
+ constexpr X(int x) __constant : x(x) {}
+};
+
+// CHECK: @cx1 = dso_local addrspace(2) constant %struct.X zeroinitializer
+// CHECK: @cx2 = dso_local addrspace(2) constant %struct.X { i32 1 }
+// CHECK: @gx = dso_local addrspace(1) global %struct.X zeroinitializer
+__constant X cx1;
+__constant X cx2(1);
+__global X gx;
+
+// CHECK: @_ZZ1kE3cx1 = internal addrspace(2) constant %struct.X zeroinitializer
+// CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
+
+kernel void k() {
+ // Check that the constructor for px is executed
+ // CHECK: %px = alloca %struct.X
+ // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
+ __private X px;
+
+ __constant X cx1;
+ __constant X cx2(1);
+ // CHECK-NEXT: ret void
+}
diff --git a/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
new file mode 100644
index 0000000000000..9154d579a9b4a
--- /dev/null
+++ b/clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+__constant int g1; // expected-error {{variable in constant address space must be initialized}}
+__constant int g2 = 0;
+
+struct X {
+ int x;
+ constexpr X() __constant : x(0) {}
+ constexpr X(int x) __constant : x(x) {}
+};
+
+//expected-note at +2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}}
+//expected-note at +1{{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to '__generic Y' for 1st argument}}
+struct Y {
+ int y;
+ Y() __generic = default; // expected-note{{candidate constructor not viable: requires 0 arguments, but 1 was provided}}
+};
+
+kernel void k() {
+ __constant X cx1;
+ __constant X cx2(1);
+ __local X lx;
+
+ __private Y py;
+ __constant Y cy1; // expected-error{{variable in constant address space must be initialized}}
+ __constant Y cy2(1); // expected-error{{no matching constructor for initialization of '__constant Y'}}
+}
+
+struct Z {
+ int z;
+ // The address space is deduced to be __generic if omitted
+ Z() = default; // expected-note{{previous definition is here}}
+ Z() __generic = default; // expected-error {{constructor cannot be redeclared}}
+
+ Z() __private = default;
+ Z() __local = default;
+ Z() __global = default;
+ // Can't default constexpr constructors
+ constexpr Z() __constant : z(0) {}
+};
+
+struct W {
+ int w;
+ constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+};
More information about the cfe-commits
mailing list