olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

This fixes the implicit initialization that uses constructors in the __constant 
address space without arguments.

It also adds several tests to make sure that constructors in other address 
spaces also work, since these have not yet been tested.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D102248

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -0,0 +1,44 @@
+// 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;
+  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;
+  constexpr Z() __constant : z(0) {}
+};
+
+struct W {
+  int w;
+  constexpr W() __constant = default; // expected-error {{defaulted definition 
of default constructor is not constexpr}}
+};
+
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -12638,9 +12638,21 @@
     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>()) 
{


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===================================================================
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -0,0 +1,44 @@
+// 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;
+  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;
+  constexpr Z() __constant : z(0) {}
+};
+
+struct W {
+  int w;
+  constexpr W() __constant = default; // expected-error {{defaulted definition of default constructor is not constexpr}}
+};
+
Index: clang/lib/Sema/SemaDecl.cpp
===================================================================
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -12638,9 +12638,21 @@
     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>()) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to