forked from OSchip/llvm-project
[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
This commit is contained in:
parent
20e1577d13
commit
642d2f000b
|
@ -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>()) {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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@+2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}}
|
||||
//expected-note@+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}}
|
||||
};
|
Loading…
Reference in New Issue