[PATCH] D83665: [OpenCL] Fixed missing address space for templated copy constructor

2020-07-20 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm marked an inline comment as done.
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:3811
+  if(S.getLangOpts().OpenCL)
+ArgType = S.deduceOpenCLPointeeAddrSpace(ArgType);
   ArgType = S.Context.getLValueReferenceType(ArgType);

Anastasia wrote:
> I feel we can just add an address space explicitly since we are creating the 
> type here for a known use case. However, does Arg actually have an address 
> space? I am just unsure whether we should use generic address space or 
> concrete address space.
No, there are no known address spaces at this point for the test case I've got. 
But as far as I understand the function isn't only used for the case we look at 
here, but there may be case where the argument has an address space.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83665/new/

https://reviews.llvm.org/D83665



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83665: [OpenCL] Fixed missing address space for templated copy constructor

2020-07-21 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 279485.
olestrohm added a comment.

The code now directly adds the __generic address space to the pointee type.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83665/new/

https://reviews.llvm.org/D83665

Files:
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/test/SemaOpenCLCXX/address-space-templates.cl


Index: clang/test/SemaOpenCLCXX/address-space-templates.cl
===
--- clang/test/SemaOpenCLCXX/address-space-templates.cl
+++ clang/test/SemaOpenCLCXX/address-space-templates.cl
@@ -22,10 +22,28 @@
   __private T ii; // expected-error{{conflicting address space qualifiers are 
provided between types '__private T' and '__global int'}}
 }
 
+template  struct remove_reference { typedef _Tp type; };
+template  struct remove_reference<_Tp &>  { typedef _Tp type; };
+template  struct as_pointer {
+typedef typename remove_reference<_Tp>::type* type;
+};
+
+struct rep {
+  // CHECK |-CXXConstructorDecl {{.*}} rep 'void (const __generic rep 
&__private) __generic'
+  template::type>
+  rep(U&& v) {}
+};
+
+struct rep_outer : private rep {
+  rep_outer()
+: rep(0) {}
+};
+
 void bar() {
   S sintgl; // expected-note{{in instantiation of template 
class 'S' requested here}}
 
   foo1<__local int>(1); // expected-error{{no matching function for call to 
'foo1'}}
   foo2<__global int>(0);
   foo3<__global int>(); // expected-note{{in instantiation of function 
template specialization 'foo3<__global int>' requested here}}
+  rep_outer r;
 }
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3806,8 +3806,11 @@
 //   If P is a forwarding reference and the argument is an lvalue, the type
 //   "lvalue reference to A" is used in place of A for type deduction.
 if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
-Arg->isLValue())
+Arg->isLValue()) {
+  if (S.getLangOpts().OpenCL)
+ArgType = S.Context.getAddrSpaceQualType(ArgType, 
LangAS::opencl_generic);
   ArgType = S.Context.getLValueReferenceType(ArgType);
+}
   } else {
 // C++ [temp.deduct.call]p2:
 //   If P is not a reference type:


Index: clang/test/SemaOpenCLCXX/address-space-templates.cl
===
--- clang/test/SemaOpenCLCXX/address-space-templates.cl
+++ clang/test/SemaOpenCLCXX/address-space-templates.cl
@@ -22,10 +22,28 @@
   __private T ii; // expected-error{{conflicting address space qualifiers are provided between types '__private T' and '__global int'}}
 }
 
+template  struct remove_reference { typedef _Tp type; };
+template  struct remove_reference<_Tp &>  { typedef _Tp type; };
+template  struct as_pointer {
+typedef typename remove_reference<_Tp>::type* type;
+};
+
+struct rep {
+  // CHECK |-CXXConstructorDecl {{.*}} rep 'void (const __generic rep &__private) __generic'
+  template::type>
+  rep(U&& v) {}
+};
+
+struct rep_outer : private rep {
+  rep_outer()
+: rep(0) {}
+};
+
 void bar() {
   S sintgl; // expected-note{{in instantiation of template class 'S' requested here}}
 
   foo1<__local int>(1); // expected-error{{no matching function for call to 'foo1'}}
   foo2<__global int>(0);
   foo3<__global int>(); // expected-note{{in instantiation of function template specialization 'foo3<__global int>' requested here}}
+  rep_outer r;
 }
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3806,8 +3806,11 @@
 //   If P is a forwarding reference and the argument is an lvalue, the type
 //   "lvalue reference to A" is used in place of A for type deduction.
 if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
-Arg->isLValue())
+Arg->isLValue()) {
+  if (S.getLangOpts().OpenCL)
+ArgType = S.Context.getAddrSpaceQualType(ArgType, LangAS::opencl_generic);
   ArgType = S.Context.getLValueReferenceType(ArgType);
+}
   } else {
 // C++ [temp.deduct.call]p2:
 //   If P is not a reference type:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-07-03 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 275345.
olestrohm added a comment.

Added a guard in deduceOpenCLAddressSpace to stop it from deducing address 
space for dependent types, as requested.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82781/new/

https://reviews.llvm.org/D82781

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp


Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3630,7 +3630,7 @@
   // in every situation.
   // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
   if (SemaRef.getLangOpts().OpenCL)
- SemaRef.deduceOpenCLAddressSpace(Var);
+SemaRef.deduceOpenCLAddressSpace(Var);
 
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
@@ -4815,7 +4815,7 @@
   // reliable in every situation.
   // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
   if (getLangOpts().OpenCL)
- deduceOpenCLAddressSpace(VarSpec);
+deduceOpenCLAddressSpace(VarSpec);
 
   return VarSpec;
 }
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6287,6 +6287,8 @@
 void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
   if (Decl->getType().hasAddressSpace())
 return;
+  if (Decl->getType().isDependentType())
+return;
   if (VarDecl *Var = dyn_cast(Decl)) {
 QualType Type = Var->getType();
 if (Type->isSamplerT() || Type->isVoidType())


Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3630,7 +3630,7 @@
   // in every situation.
   // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
   if (SemaRef.getLangOpts().OpenCL)
- SemaRef.deduceOpenCLAddressSpace(Var);
+SemaRef.deduceOpenCLAddressSpace(Var);
 
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
@@ -4815,7 +4815,7 @@
   // reliable in every situation.
   // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
   if (getLangOpts().OpenCL)
- deduceOpenCLAddressSpace(VarSpec);
+deduceOpenCLAddressSpace(VarSpec);
 
   return VarSpec;
 }
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6287,6 +6287,8 @@
 void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
   if (Decl->getType().hasAddressSpace())
 return;
+  if (Decl->getType().isDependentType())
+return;
   if (VarDecl *Var = dyn_cast(Decl)) {
 QualType Type = Var->getType();
 if (Type->isSamplerT() || Type->isVoidType())
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-07-03 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 275351.
olestrohm added a comment.

Disregard the last comment, rolling back that diff for now.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82781/new/

https://reviews.llvm.org/D82781

Files:
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaOpenCLCXX/address-space-deduction.cl


Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,10 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global 
long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -111,4 +115,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,13 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in D, but the type in D may not be reliable
+  // in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (SemaRef.getLangOpts().OpenCL)
+ SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4810,13 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in PatternDecl, but this type may not be
+  // reliable in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (getLangOpts().OpenCL)
+ deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 


Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,10 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -111,4 +115,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,13 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in D, but the type in D may not be reliable
+  // in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (SemaRef.getLangOpts().OpenCL)
+ SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4810,13 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in PatternDecl, but this type may not be
+  // reliable in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (getLangOpts().OpenCL)
+ deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-07-03 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 275381.
olestrohm added a comment.

I have added a check in `deduceOpenCLAddressSpace()` to check if the type is 
dependent, and not deduce the address space if it is. This is a big change in 
the behaviour of address space deduction, meaning that template variables only 
receive address spaces when they are being specialized. This is good, but 
caused a lot of changes in the current test file, which has been included in 
this patch.

There also had to be added a check for dependent types in 
CheckVariableDeclarationType when checking whether global variables have the 
correct address space. With this new change dependent types don't necessarily 
have address spaces yet, and thus then lets it pass until the variable 
declaration of the specialized template variable is checked later.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82781/new/

https://reviews.llvm.org/D82781

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaOpenCLCXX/address-space-deduction.cl

Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,11 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: |-VarDecl {{.*}} foo1 'T' cinit
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -30,7 +35,7 @@
 
 template 
 struct x1 {
-//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &__private){{( __attribute__.*)?}} __generic'
   x1& operator=(const x1& xx) {
 y = xx.y;
@@ -41,7 +46,7 @@
 
 template 
 struct x2 {
-//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *__private){{( __attribute__.*)?}} __generic'
   void foo(x1* xx) {
 m[0] = *xx;
@@ -57,10 +62,10 @@
 template 
 class x3 : public T {
 public:
-  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
   x3(const x3 &t);
 };
-//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
 template 
 x3::x3(const x3 &t) {}
 
@@ -68,7 +73,8 @@
 T xxx(T *in1, T in2) {
   // This pointer can't be deduced to generic because addr space
   // will be taken from the template argument.
-  //CHECK: `-VarDecl {{.*}} '__private T *__private' cinit
+  //CHECK: `-VarDecl {{.*}} 'T *' cinit
+  //CHECK: `-VarDecl {{.*}} i '__private int *__private' cinit
   T *i = in1;
   T ii;
   __private T *ptr = ⅈ
@@ -111,4 +117,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,13 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in D, but the type in D may not be reliable
+  // in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (SemaRef.getLangOpts().OpenCL)
+SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4810,13 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in PatternDecl, but this type may not be
+  // reliable in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (getLangOpts().OpenCL)
+deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6287,6 +6287,8 @@
 void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
   if (Decl->getType().hasAddressSpace())
 return;
+  if (Decl->getType()->isDependentType())
+return;
   i

[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-07-08 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 276369.
olestrohm marked an inline comment as done.
olestrohm added a comment.

I've removed the comments calling for a fix because I no longer feel that this 
approach needs that. Given the code that already exists, and without changing 
too much of it, adding address space deduction in both cases seems like the 
right choice.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82781/new/

https://reviews.llvm.org/D82781

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaOpenCLCXX/address-space-deduction.cl

Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,11 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: |-VarDecl {{.*}} foo1 'T' cinit
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -30,7 +35,7 @@
 
 template 
 struct x1 {
-//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} operator= 'x1 &(const x1 &){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} operator= '__generic x1 &(const __generic x1 &__private){{( __attribute__.*)?}} __generic'
   x1& operator=(const x1& xx) {
 y = xx.y;
@@ -41,7 +46,7 @@
 
 template 
 struct x2 {
-//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXMethodDecl {{.*}} foo 'void (x1 *){{( __attribute__.*)?}} __generic'
 //CHECK: -CXXMethodDecl {{.*}} foo 'void (__generic x1 *__private){{( __attribute__.*)?}} __generic'
   void foo(x1* xx) {
 m[0] = *xx;
@@ -57,10 +62,10 @@
 template 
 class x3 : public T {
 public:
-  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+  //CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
   x3(const x3 &t);
 };
-//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &__private){{( __attribute__.*)?}} __generic'
+//CHECK: -CXXConstructorDecl {{.*}} x3 'void (const x3 &){{( __attribute__.*)?}} __generic'
 template 
 x3::x3(const x3 &t) {}
 
@@ -68,7 +73,8 @@
 T xxx(T *in1, T in2) {
   // This pointer can't be deduced to generic because addr space
   // will be taken from the template argument.
-  //CHECK: `-VarDecl {{.*}} '__private T *__private' cinit
+  //CHECK: `-VarDecl {{.*}} 'T *' cinit
+  //CHECK: `-VarDecl {{.*}} i '__private int *__private' cinit
   T *i = in1;
   T ii;
   __private T *ptr = ⅈ
@@ -111,4 +117,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,9 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  if (SemaRef.getLangOpts().OpenCL)
+SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4806,9 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  if (getLangOpts().OpenCL)
+deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6287,6 +6287,8 @@
 void Sema::deduceOpenCLAddressSpace(ValueDecl *Decl) {
   if (Decl->getType().hasAddressSpace())
 return;
+  if (Decl->getType()->isDependentType())
+return;
   if (VarDecl *Var = dyn_cast(Decl)) {
 QualType Type = Var->getType();
 if (Type->isSamplerT() || Type->isVoidType())
@@ -7856,6 +7858,7 @@
 if (NewVD->isFileVarDecl() || NewVD->isStaticLocal() ||
 NewVD->hasExternalStorage()) {
   if (!T->isSamplerT() &&
+  !T->isDependentType() &&
   !(T.getAddressSpace() == LangAS::opencl_constant ||
 (T.getAddressSpace() == LangAS::opencl_global &&
  (getLangOpts().OpenCLVersion == 200 ||
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D83665: [OpenCL] Fixed missing address space for templated copy constructor

2020-07-13 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, rjmccall.
olestrohm added a project: clang.
Herald added subscribers: cfe-commits, yaxunl.

When you have a templated constructor with an R-value reference the compiler 
implicitly creates a copy and move constructor through the template 
constructor, and the copy constructor created this way was missing an address 
space in the reference parameter. I've come up with this fix that deduces the 
address space for the reference parameter right before it's created, and a 
corresponding test.

The test is quite big, but rep_outer is necessary to force the compiler to 
create the copy constructor, and the two template structs are partly for 
readability.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83665

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaOpenCLCXX/address-space-templates.cl

Index: clang/test/SemaOpenCLCXX/address-space-templates.cl
===
--- clang/test/SemaOpenCLCXX/address-space-templates.cl
+++ clang/test/SemaOpenCLCXX/address-space-templates.cl
@@ -22,10 +22,28 @@
   __private T ii; // expected-error{{conflicting address space qualifiers are provided between types '__private T' and '__global int'}}
 }
 
+template  struct remove_reference { typedef _Tp type; };
+template  struct remove_reference<_Tp &>  { typedef _Tp type; };
+template  struct as_pointer {
+typedef typename remove_reference<_Tp>::type* type;
+};
+
+struct rep {
+	// CHECK |-CXXConstructorDecl {{.*}} rep 'void (const __generic rep &__private) __generic'
+	template::type>
+	rep(U&& v) {}
+};
+
+struct rep_outer : private rep {
+	rep_outer()
+		: rep(0) {}
+};
+
 void bar() {
   S sintgl; // expected-note{{in instantiation of template class 'S' requested here}}
 
   foo1<__local int>(1); // expected-error{{no matching function for call to 'foo1'}}
   foo2<__global int>(0);
   foo3<__global int>(); // expected-note{{in instantiation of function template specialization 'foo3<__global int>' requested here}}
+  rep_outer r;
 }
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -2036,13 +2036,13 @@
 }
 
 // Helper to deduce addr space of a pointee type in OpenCL mode.
-static QualType deduceOpenCLPointeeAddrSpace(Sema &S, QualType PointeeType) {
+QualType Sema::deduceOpenCLPointeeAddrSpace(QualType PointeeType) {
   if (!PointeeType->isUndeducedAutoType() && !PointeeType->isDependentType() &&
   !PointeeType->isSamplerT() &&
   !PointeeType.hasAddressSpace())
-PointeeType = S.getASTContext().getAddrSpaceQualType(
+PointeeType = getASTContext().getAddrSpaceQualType(
 PointeeType,
-S.getLangOpts().OpenCLCPlusPlus || S.getLangOpts().OpenCLVersion == 200
+getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion == 200
 ? LangAS::opencl_generic
 : LangAS::opencl_private);
   return PointeeType;
@@ -2085,7 +2085,7 @@
 T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ false);
 
   if (getLangOpts().OpenCL)
-T = deduceOpenCLPointeeAddrSpace(*this, T);
+T = deduceOpenCLPointeeAddrSpace(T);
 
   // Build the pointer type.
   return Context.getPointerType(T);
@@ -2148,7 +2148,7 @@
 T = inferARCLifetimeForPointee(*this, T, Loc, /*reference*/ true);
 
   if (getLangOpts().OpenCL)
-T = deduceOpenCLPointeeAddrSpace(*this, T);
+T = deduceOpenCLPointeeAddrSpace(T);
 
   // Handle restrict on references.
   if (LValueRef)
@@ -2862,7 +2862,7 @@
 return QualType();
 
   if (getLangOpts().OpenCL)
-T = deduceOpenCLPointeeAddrSpace(*this, T);
+T = deduceOpenCLPointeeAddrSpace(T);
 
   return Context.getBlockPointerType(T);
 }
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -3806,8 +3806,11 @@
 //   If P is a forwarding reference and the argument is an lvalue, the type
 //   "lvalue reference to A" is used in place of A for type deduction.
 if (isForwardingReference(QualType(ParamRefType, 0), FirstInnerIndex) &&
-Arg->isLValue())
+Arg->isLValue()) {
+  if(S.getLangOpts().OpenCL)
+ArgType = S.deduceOpenCLPointeeAddrSpace(ArgType);
   ArgType = S.Context.getLValueReferenceType(ArgType);
+}
   } else {
 // C++ [temp.deduct.call]p2:
 //   If P is not a reference type:
Index: clang/include/clang/Sema/Sema.h
===
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -9364,6 +9364,7 @@
   bool inferObjCARCLifetime(ValueDecl *decl);
 
   void deduceOpenCLAddressSpace(ValueDecl *decl);
+  QualType d

[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-06-29 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, rjmccall.
olestrohm added a project: clang.
Herald added a subscriber: yaxunl.

This patch fixes two instances of not deducing address spaces for global 
template variables.
I've added OpenCL address space deduction to the functions responsible for 
specializing template variable declarations,
and while this does give the correct address spaces, it is not optimal, as this 
same address space is deduced at least three times for a single variable.
It would be better if the correct type was correctly passed forward through the 
phases, which I've explained in the comments.
Since the variable is templated I'm not entirely certain if this is feasible or 
worthwhile compared to the simple solution of rededucing the address space 
several times.

I've also included this an example of this in the test for address space 
deductions


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D82781

Files:
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaOpenCLCXX/address-space-deduction.cl


Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,10 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global 
long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -111,4 +115,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,13 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in D, but the type in D may not be reliable
+  // in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (SemaRef.getLangOpts().OpenCL)
+ SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4810,13 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in PatternDecl, but this type may not be
+  // reliable in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (getLangOpts().OpenCL)
+ deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 


Index: clang/test/SemaOpenCLCXX/address-space-deduction.cl
===
--- clang/test/SemaOpenCLCXX/address-space-deduction.cl
+++ clang/test/SemaOpenCLCXX/address-space-deduction.cl
@@ -5,6 +5,10 @@
 //CHECK: |-VarDecl {{.*}} foo 'const __global int'
 constexpr int foo = 0;
 
+//CHECK: `-VarTemplateSpecializationDecl {{.*}} used foo1 '__global long':'__global long' cinit
+template 
+T foo1 = 0;
+
 class c {
 public:
   //CHECK: `-VarDecl {{.*}} foo2 'const __global int'
@@ -111,4 +115,5 @@
   t3(&x);
   t4(&p);
   t5(&p);
+  long f1 = foo1;
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3625,6 +3625,13 @@
   if (InsertPos)
 VarTemplate->AddSpecialization(Var, InsertPos);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in D, but the type in D may not be reliable
+  // in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (SemaRef.getLangOpts().OpenCL)
+ SemaRef.deduceOpenCLAddressSpace(Var);
+
   // Substitute the nested name specifier, if any.
   if (SubstQualifier(D, Var))
 return nullptr;
@@ -4803,6 +4810,13 @@
   // Instantiate the initializer.
   InstantiateVariableInitializer(VarSpec, PatternDecl, TemplateArgs);
 
+  // FIXME: This may not be the best approach, as the correct type (including
+  // address space) is available in PatternDecl, but this type may not be
+  // reliable in every situation.
+  // This approach was copied from TemplateDeclInstantiator::VisitVarDecl
+  if (getLangOpts().OpenCL)
+ deduceOpenCLAddressSpace(VarSpec);
+
   return VarSpec;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D82781: [OpenCL] Fix missing address space deduction in template variables

2020-06-30 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added a comment.

Essentially, in each pass the type for the variable starts off being extract 
from the SourceTypeInfo, but since the address space isn't specified, this type 
is then missing an address space.
Adding the address space deduction then reintroduces the address space to the 
type.

This is then done at least three times (pre-specialization, in the middle of 
specialization and when completing specialization), but since this is a 
template it may not be possible to correctly
deduce the type earlier in case the template type introduces an address space 
in template specialization?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D82781/new/

https://reviews.llvm.org/D82781



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D85429: [OpenCL] Allow for variadic macros in C++ for OpenCL

2020-08-06 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added a reviewer: Anastasia.
olestrohm added a project: clang.
Herald added subscribers: cfe-commits, yaxunl.
olestrohm requested review of this revision.

C++ for OpenCL intends to support variadic macros, a decision motivated by 
OpenCL 3.0. This patch simply skips the warning when compiling in C++ for 
OpenCL mode.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D85429

Files:
  clang/lib/Lex/PPDirectives.cpp


Index: clang/lib/Lex/PPDirectives.cpp
===
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2394,7 +2394,7 @@
  diag::ext_variadic_macro);
 
   // OpenCL v1.2 s6.9.e: variadic macros are not supported.
-  if (LangOpts.OpenCL) {
+  if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
   }
 


Index: clang/lib/Lex/PPDirectives.cpp
===
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2394,7 +2394,7 @@
  diag::ext_variadic_macro);
 
   // OpenCL v1.2 s6.9.e: variadic macros are not supported.
-  if (LangOpts.OpenCL) {
+  if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D85429: [OpenCL] Allow for variadic macros in C++ for OpenCL

2020-08-07 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 283909.
olestrohm added a comment.

I have amended the relevant test to validate this behaviour in C++ for OpenCL.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D85429/new/

https://reviews.llvm.org/D85429

Files:
  clang/lib/Lex/PPDirectives.cpp
  clang/test/Preprocessor/macro_variadic.cl


Index: clang/test/Preprocessor/macro_variadic.cl
===
--- clang/test/Preprocessor/macro_variadic.cl
+++ clang/test/Preprocessor/macro_variadic.cl
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -verify %s -cl-std=CL1.2
 // RUN: %clang_cc1 -verify %s -pedantic -DPEDANTIC -cl-std=CL1.2
+// RUN: %clang_cc1 -verify %s -cl-std=CLC++
+// RUN: %clang_cc1 -verify %s -pedantic -cl-std=CLC++
 
 
 #define NO_VAR_FUNC(...)  5
@@ -15,6 +17,11 @@
 
 void foo() {
   NO_VAR_FUNC(1, 2, 3);
-  VAR_FUNC(1, 2, 3); //expected-error{{implicit declaration of function 'func' 
is invalid in OpenCL}}
+  VAR_FUNC(1, 2, 3);
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-2{{implicit declaration of function 'func' is invalid in 
OpenCL}}
+#else
+// expected-error@-4{{use of undeclared identifier 'func'}}
+#endif
   VAR_PRINTF("%i", 1);
 }
Index: clang/lib/Lex/PPDirectives.cpp
===
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2394,7 +2394,7 @@
  diag::ext_variadic_macro);
 
   // OpenCL v1.2 s6.9.e: variadic macros are not supported.
-  if (LangOpts.OpenCL) {
+  if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
   }
 


Index: clang/test/Preprocessor/macro_variadic.cl
===
--- clang/test/Preprocessor/macro_variadic.cl
+++ clang/test/Preprocessor/macro_variadic.cl
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -verify %s -cl-std=CL1.2
 // RUN: %clang_cc1 -verify %s -pedantic -DPEDANTIC -cl-std=CL1.2
+// RUN: %clang_cc1 -verify %s -cl-std=CLC++
+// RUN: %clang_cc1 -verify %s -pedantic -cl-std=CLC++
 
 
 #define NO_VAR_FUNC(...)  5
@@ -15,6 +17,11 @@
 
 void foo() {
   NO_VAR_FUNC(1, 2, 3);
-  VAR_FUNC(1, 2, 3); //expected-error{{implicit declaration of function 'func' is invalid in OpenCL}}
+  VAR_FUNC(1, 2, 3);
+#if !__OPENCL_CPP_VERSION__
+// expected-error@-2{{implicit declaration of function 'func' is invalid in OpenCL}}
+#else
+// expected-error@-4{{use of undeclared identifier 'func'}}
+#endif
   VAR_PRINTF("%i", 1);
 }
Index: clang/lib/Lex/PPDirectives.cpp
===
--- clang/lib/Lex/PPDirectives.cpp
+++ clang/lib/Lex/PPDirectives.cpp
@@ -2394,7 +2394,7 @@
  diag::ext_variadic_macro);
 
   // OpenCL v1.2 s6.9.e: variadic macros are not supported.
-  if (LangOpts.OpenCL) {
+  if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus) {
 Diag(Tok, diag::ext_pp_opencl_variadic_macros);
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102248: [C++4OpenCL] Fix initialization of __constant constructors without arguments

2021-05-12 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp:36
+  Z() __local = default;
+  Z() __global = default;
+  constexpr Z() __constant : z(0) {}

Anastasia wrote:
> We seem to be missing the coverage with __constant and `= default`.
This is because of the struct W below, you can't default a constexpr 
constructor, but __constant constructors need to be constexpr. Though it is 
currently possible to create them, they just can't actually be used. Or maybe 
just combine Z and W?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102248/new/

https://reviews.llvm.org/D102248

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102248: [C++4OpenCL] Fix initialization of __constant constructors without arguments

2021-05-14 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 345436.
olestrohm added a comment.

Added a codegen test and clarified what some parts are testing.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102248/new/

https://reviews.llvm.org/D102248

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

Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ 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@+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}}
+};
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -0,0 +1,40 @@
+// 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, align 4
+// CHECK: @gi = dso_local addrspace(1) global i32 0, align 4
+__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, align 4
+// CHECK: @cx2 = dso_local addrspace(2) constant %struct.X { i32 1 }, align 4
+// CHECK: @gx = dso_local addrspace(1) global %struct.X zeroinitializer, align 4
+__constant X cx1;
+__constant X cx2(1);
+__global X gx;
+
+// CHECK: @_ZZ1kE3cx1 = internal addrspace(2) constant %struct.X zeroinitializer, align 4
+// CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }, align 4
+kernel void k() {
+  // Check that the constructor for px is executed
+  __private X px;
+  // CHECK: [[PX:%[.a-z0-9]+]] = alloca %struct.X, align 4
+  // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* nonnull dereferenceable(4) [[PX]]) #3
+
+  __constant X cx1;
+  __constant X cx2(1);
+  // CHECK-NEXT: ret void
+}
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 (

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors

2021-05-14 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 345442.
olestrohm added a comment.

Fixed the code style and added some comments to the tests.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+kernel void foo() {
+  // Testing conversions between vectors and vectors/scalars
+  long l1;
+  auto l_to_i2 = reinterpret_cast(l1);
+  int2 i2;
+  auto i2_to_l = reinterpret_cast(i2);
+  auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+  auto i2_to_i2 = reinterpret_cast(i2);
+
+  // Only integral types (and pointer/references) can be reinterpret casted to themselves.
+  // Currently this does not include any opencl types.
+  reserve_id_t r_id1;
+  auto r_id2 = reinterpret_cast(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,17 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef long long2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *in) {
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto l = reinterpret_cast(in[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto i2 = reinterpret_cast(l);
+
+  int4 i4;
+  //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
+  auto l2 = reinterpret_cast(i4);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7344,6 +7344,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) {
+  assert(DestTy->isVectorType() || SrcTy->isVectorType());
+
+  uint64_t SrcLen, DestLen;
+  QualType SrcEltTy, DestEltTy;
+  if (!breakDownVectorType(SrcTy, SrcLen, SrcEltTy))
+return false;
+  if (!breakDownVectorType(DestTy, DestLen, DestEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t SrcEltSize = Context.getTypeSize(SrcEltTy);
+  uint64_t DestEltSize = Context.getTypeSize(DestEltTy);
+
+  return (SrcLen * SrcEltSize == DestLen * DestEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7362,18 +7381,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2328,6 +2328,16 @@
   return TC_Success;
 }
 
+if (Self.LangOpts.OpenCL && !CStyle) {
+  if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+// FIXME: Allow for reinterpret cast between 3 and 4 element vectors
+if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+  Kind = CK_BitCast;
+  return TC_Success;
+}
+  }
+}
+

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors

2021-05-17 Thread Ole Strohm via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG66b112d624a5: [OpenCL] Fix reinterpret_cast of vectors 
(authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+kernel void foo() {
+  // Testing conversions between vectors and vectors/scalars
+  long l1;
+  auto l_to_i2 = reinterpret_cast(l1);
+  int2 i2;
+  auto i2_to_l = reinterpret_cast(i2);
+  auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+  auto i2_to_i2 = reinterpret_cast(i2);
+
+  // Only integral types (and pointer/references) can be reinterpret casted to themselves.
+  // Currently this does not include any opencl types.
+  reserve_id_t r_id1;
+  auto r_id2 = reinterpret_cast(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,17 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef long long2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *in) {
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto l = reinterpret_cast(in[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto i2 = reinterpret_cast(l);
+
+  int4 i4;
+  //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
+  auto l2 = reinterpret_cast(i4);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7341,6 +7341,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType SrcTy, QualType DestTy) {
+  assert(DestTy->isVectorType() || SrcTy->isVectorType());
+
+  uint64_t SrcLen, DestLen;
+  QualType SrcEltTy, DestEltTy;
+  if (!breakDownVectorType(SrcTy, SrcLen, SrcEltTy))
+return false;
+  if (!breakDownVectorType(DestTy, DestLen, DestEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t SrcEltSize = Context.getTypeSize(SrcEltTy);
+  uint64_t DestEltSize = Context.getTypeSize(DestEltTy);
+
+  return (SrcLen * SrcEltSize == DestLen * DestEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7359,18 +7378,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2335,6 +2335,16 @@
   return TC_Success;
 }
 
+if (Self.LangOpts.OpenCL && !CStyle) {
+  if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+// FIXME: Allow for reinterpret cast between 3 and 4 element vectors
+if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+  K

[PATCH] D102248: [C++4OpenCL] Fix initialization of __constant constructors without arguments

2021-05-17 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 345845.
olestrohm added a comment.

Relaxed the checks in the codegen test because of failures on platforms with 
slightly different IR being generated.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102248/new/

https://reviews.llvm.org/D102248

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

Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ 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@+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}}
+};
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ 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
+}
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()) {
___

[PATCH] D102248: [C++4OpenCL] Fix initialization of __constant constructors without arguments

2021-05-18 Thread Ole Strohm via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG642d2f000b26: [OpenCL] Fix initialization of __constant 
constructors without arguments (authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102248/new/

https://reviews.llvm.org/D102248

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

Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ 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@+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}}
+};
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- /dev/null
+++ 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
+}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -12635,9 +12635,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->is

[PATCH] D102689: [C++4OpenCL] Allow address space conversion in reinterpret_cast

2021-05-18 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, rjmccall.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

Allow converting between types with different address spaces.

This allows converting a `__private int` to a `__private int`, which is 
currently not possible.
It also allows converting a value to any other address space, which can make 
sense since
the actual bit representation of the values doesn't depend on the address space.

This is the solution I chose currently allows converting between any address 
space
because the address space of `SrcExpr` is erased before entering the function,
so allowing only converting when the address spaces is the same would require 
larger changes.

I'm not sure if this conversion should be allowed, though converting to the 
exact same type definitely should.

Fixes the first issue in PR49221


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D102689

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp


Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -13,6 +13,11 @@
   auto i2_to_i = reinterpret_cast(i2); // 
expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) 
to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
   // Only integral types (and pointer/references) can be reinterpret casted to 
themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2356,7 +2356,10 @@
 return TC_Failed;
   }
 
-  if (SrcType == DestType) {
+  if (SrcType == DestType ||
+  (Self.LangOpts.OpenCL &&
+Self.Context.removeAddrSpaceQualType(SrcType) ==
+  Self.Context.removeAddrSpaceQualType(DestType))) {
 // C++ 5.2.10p2 has a note that mentions that, subject to all other
 // restrictions, a cast to the same type is allowed so long as it does not
 // cast away constness. In C++98, the intent was not entirely clear here,


Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -13,6 +13,11 @@
   auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
   // Only integral types (and pointer/references) can be reinterpret casted to themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2356,7 +2356,10 @@
 return TC_Failed;
   }
 
-  if (SrcType == DestType) {
+  if (SrcType == DestType ||
+  (Self.LangOpts.OpenCL &&
+Self.Context.removeAddrSpaceQualType(SrcType) ==
+  Self.Context.removeAddrSpaceQualType(DestType))) {
 // C++ 5.2.10p2 has a note that mentions that, subject to all other
 // restrictions, a cast to the same type is allowed so long as it does not
 // cast away constness. In C++98, the intent was not entirely clear here,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102850: [C++4OpenCL] Allow address space conversion in reinterpret_cast

2021-05-20 Thread Ole Strohm via Phabricator via cfe-commits
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 prioritization of address spaces when choosing a constructor,
stopping them from being considered equally good, which made the construction
of types that could be constructed by more than one of the constructors.

It does this by preferring the most specific address space, which is decided by 
seeing
if one of the address spaces is a superset of the other, and preferring the 
other.

Fixes: PR50329


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D102850

Files:
  clang/lib/Sema/SemaOverload.cpp
  clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp


Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ = default;
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,16 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  if (S.getLangOpts().OpenCL) {
+if (const auto *CD1 = 
dyn_cast_or_null(Cand1.Function)) {
+  if (const auto *CD2 = 
dyn_cast_or_null(Cand2.Function)) {
+return Qualifiers::isAddressSpaceSupersetOf(
+CD2->getMethodQualifiers().getAddressSpace(),
+CD1->getMethodQualifiers().getAddressSpace());
+  }
+}
+  }
+
   return false;
 }
 


Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ = default;
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,16 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  if (S.getLangOpts().OpenCL) {
+if (const auto *CD1 = dyn_cast_or_null(Cand1.Function)) {
+  if (const auto *CD2 = dyn_cast_or_null(Cand2.Function)) {
+return Qualifiers::isAddressSpaceSupersetOf(
+CD2->getMethodQualifiers().getAddressSpace(),
+CD1->getMethodQualifiers().getAddressSpace());
+  }
+}
+  }
+
   return false;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-05-24 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:9870
 
+  if (S.getLangOpts().OpenCL) {
+if (const auto *CD1 = 
dyn_cast_or_null(Cand1.Function)) {

Anastasia wrote:
> I think we should remove the OpenCL check since it is not OpenCL specific 
> rule and you are using common helpers indeed!
> 
> I also wonder if this should be applied to all member functions not only 
> ctors since `isBetterOverloadCandidate` should be used for everything?
> 
> However it seems that other members are already handled somehow 
> https://godbolt.org/z/MrWKPKed7. Do you know where this handling comes from?
It's handled in SemaOverload.cpp:1 in 
`OverloadCandidateSet::BestViableFunction` which checks if the given function 
is viable or not. For member functions the address space they're defined in and 
the address space of the variable have to match. Therefore only one of them is 
valid at a time and they never get checked against each other in 
`isBetterOverloadCandidate`.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-05-24 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:9870
 
+  if (S.getLangOpts().OpenCL) {
+if (const auto *CD1 = 
dyn_cast_or_null(Cand1.Function)) {

Anastasia wrote:
> olestrohm wrote:
> > Anastasia wrote:
> > > I think we should remove the OpenCL check since it is not OpenCL specific 
> > > rule and you are using common helpers indeed!
> > > 
> > > I also wonder if this should be applied to all member functions not only 
> > > ctors since `isBetterOverloadCandidate` should be used for everything?
> > > 
> > > However it seems that other members are already handled somehow 
> > > https://godbolt.org/z/MrWKPKed7. Do you know where this handling comes 
> > > from?
> > It's handled in SemaOverload.cpp:1 in 
> > `OverloadCandidateSet::BestViableFunction` which checks if the given 
> > function is viable or not. For member functions the address space they're 
> > defined in and the address space of the variable have to match. Therefore 
> > only one of them is valid at a time and they never get checked against each 
> > other in `isBetterOverloadCandidate`.
> I am quite sure that for the example above both `__private` and `__generic 
> `overloads are viable. In fact, if you remove the `__private` overload the 
> `__generic` one gets picked.
> 
> So I think the logic should be checking for compatibility rather than the 
> exact match i.e. using `isAddressSpaceSupersetOf` although it might not be 
> calling that helper directly but through the other Qualifier logic.
Ah, I think I checked it wrong last time. Going through it again it's actually 
determined by `QualType::isMoreQualifiedThan` in the end. I'll look into it 
more.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-05-26 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 347872.
olestrohm added a comment.

Made the check more general, it's no longer OpenCL specific and no longer 
restricted to just constructors, since the check only requires them to be 
methods.

Also added more Sema tests, including using FileCheck to check that the 
constructors that should be used are actually used.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

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


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must 
be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} 
__generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //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 {
@@ -20,6 +28,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must 
be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,19 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  if (const auto *MD1 = dyn_cast_or_null(Cand1.Function)) {
+if (const auto *MD2 = dyn_cast_or_null(Cand2.Function)) {
+  LangAS AS1 = MD1->getMethodQualifiers().getAddressSpace();
+  LangAS AS2 = MD2->getMethodQualifiers().getAddressSpace();
+  if (AS1 != AS2) {
+if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+  return true;
+if (Qualifiers::isAddressSpaceSupersetOf(AS1, AS2))
+  return false;
+  }
+}
+  }
+
   return false;
 }
 


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note@+2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for 1st argument}

[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-05-26 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaOverload.cpp:9870
 
+  if (S.getLangOpts().OpenCL) {
+if (const auto *CD1 = 
dyn_cast_or_null(Cand1.Function)) {

Anastasia wrote:
> olestrohm wrote:
> > Anastasia wrote:
> > > olestrohm wrote:
> > > > Anastasia wrote:
> > > > > I think we should remove the OpenCL check since it is not OpenCL 
> > > > > specific rule and you are using common helpers indeed!
> > > > > 
> > > > > I also wonder if this should be applied to all member functions not 
> > > > > only ctors since `isBetterOverloadCandidate` should be used for 
> > > > > everything?
> > > > > 
> > > > > However it seems that other members are already handled somehow 
> > > > > https://godbolt.org/z/MrWKPKed7. Do you know where this handling 
> > > > > comes from?
> > > > It's handled in SemaOverload.cpp:1 in 
> > > > `OverloadCandidateSet::BestViableFunction` which checks if the given 
> > > > function is viable or not. For member functions the address space 
> > > > they're defined in and the address space of the variable have to match. 
> > > > Therefore only one of them is valid at a time and they never get 
> > > > checked against each other in `isBetterOverloadCandidate`.
> > > I am quite sure that for the example above both `__private` and 
> > > `__generic `overloads are viable. In fact, if you remove the `__private` 
> > > overload the `__generic` one gets picked.
> > > 
> > > So I think the logic should be checking for compatibility rather than the 
> > > exact match i.e. using `isAddressSpaceSupersetOf` although it might not 
> > > be calling that helper directly but through the other Qualifier logic.
> > Ah, I think I checked it wrong last time. Going through it again it's 
> > actually determined by `QualType::isMoreQualifiedThan` in the end. I'll 
> > look into it more.
> So did you happen to find where the address space ranking for the members is 
> currently happening for this test case https://godbolt.org/z/MrWKPKed7?
> 
> I just want to make sure we don't add any redundant checks... so if let's say 
> we already have a similar logic elsewhere it would be better if we attempt to 
> generalize it or move it entirely here if it's doable. In general, we should 
> try to use general qualifier logic if it works instead of specializing for 
> address spaces.
It's handled on line 9661 with a call to CompareImplicitConversionSequences, 
which then goes through a couple of checks and discovers that the return type 
of one of the functions is more specialized than the other. However this uses 
the Conversions part of the candidates, which the constructors don't have.

I did attempt to generalize this further than address spaces, but that caused 
some tests to fail, so I think it makes sense to only check address spaces here.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102689: [C++4OpenCL] Allow address space conversion in reinterpret_cast

2021-05-26 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 347922.
olestrohm added a comment.

I've cleaned up the check. The qualifiers of SrcType are removed prior to this 
function, so only DestType needs to have the address space removed.

reinterpret_cast only allows integral types, so structs are not an issue here, 
though pointers are.
However this change only allows converting between pointer types as long as 
they're the exact same, save for the outermost address space.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp


Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
 
+struct X {};
+
+__global int g = 0;
+__global int *__global g_ptr = &g;
+
 kernel void foo() {
   // Testing conversions between vectors and vectors/scalars
   long l1;
@@ -13,6 +18,17 @@
   auto i2_to_i = reinterpret_cast(i2); // 
expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) 
to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  // Testing reinterpret_cast with address spaces.
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
+  __private X x;
+  auto x2 = reinterpret_cast<__private X>(x); // 
expected-error{{reinterpret_cast from '__private X' to '__private X' is not 
allowed}}
+
+  auto ptr = reinterpret_cast<__global int* __private>(g_ptr);
+
   // Only integral types (and pointer/references) can be reinterpret casted to 
themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -11,6 +11,17 @@
   //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
   auto i2 = reinterpret_cast(l);
 
+  __private short s1;
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s2, align 2
+  auto s2 = reinterpret_cast<__private short>(s1);
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s3, align 2
+  auto s3 = reinterpret_cast(s1);
+  // CHECK: %{{[0-9]+}} = load i16, i16* %s1, align 2
+  // CHECK-NEXT: store i16 %{{[0-9]+}}, i16* %s4, align 2
+  auto s4 = reinterpret_cast<__global short>(s1);
+
   int4 i4;
   //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
   auto l2 = reinterpret_cast(i4);
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2356,7 +2356,7 @@
 return TC_Failed;
   }
 
-  if (SrcType == DestType) {
+  if (SrcType == Self.Context.removeAddrSpaceQualType(DestType)) {
 // C++ 5.2.10p2 has a note that mentions that, subject to all other
 // restrictions, a cast to the same type is allowed so long as it does not
 // cast away constness. In C++98, the intent was not entirely clear here,


Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
 
+struct X {};
+
+__global int g = 0;
+__global int *__global g_ptr = &g;
+
 kernel void foo() {
   // Testing conversions between vectors and vectors/scalars
   long l1;
@@ -13,6 +18,17 @@
   auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  // Testing reinterpret_cast with address spaces.
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
+  __private X x;
+  auto x2 = reinterpret_cast<__private X>(x); // expected-error{{reinterpret_cast from '__private X' to '__private X' is not allowed}}
+
+  auto ptr = reinterpret_cast<__global int* __private>(g_ptr);
+
   // Only integral types (and pointer/references) can be reinterpret casted to themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp

[PATCH] D103175: [C++4OpenCL] Fix ICE with invalid use of half

2021-05-26 Thread Ole Strohm via Phabricator via cfe-commits
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.

Because half is limited to the `cl_khr_fp16` extension being enabled, 
`DefaultLvalueConversion` can fail when it's not enabled.
Because of this the original assumption that it will never return an error is 
wrong.

This is fixed by checking for an error and returning early if there is one, 
instead of assuming that `DefaultLvalueConversion` is infallible.

Fixes: PR47976


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103175

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaOpenCLCXX/half.clcpp


Index: clang/test/SemaOpenCLCXX/half.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/half.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -verify -fsyntax-only
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : disable
+
+typedef half half2 __attribute__((ext_vector_type(2)));
+
+half f(half2 h2) { // expected-error{{declaring function return value of type 
'half' is not allowed ; did you forget * ?}}
+return h2.s0; // expected-error{{loading directly from pointer to type 
'__private half' requires cl_khr_fp16. Use vector data load builtin functions 
instead}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+half f(half2 h2) {
+return h2.s0;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4193,7 +4193,9 @@
   case ICK_Lvalue_To_Rvalue: {
 assert(From->getObjectKind() != OK_ObjCProperty);
 ExprResult FromRes = DefaultLvalueConversion(From);
-assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+if (FromRes.isInvalid())
+  return ExprError();
+
 From = FromRes.get();
 FromType = From->getType();
 break;


Index: clang/test/SemaOpenCLCXX/half.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/half.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -verify -fsyntax-only
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : disable
+
+typedef half half2 __attribute__((ext_vector_type(2)));
+
+half f(half2 h2) { // expected-error{{declaring function return value of type 'half' is not allowed ; did you forget * ?}}
+return h2.s0; // expected-error{{loading directly from pointer to type '__private half' requires cl_khr_fp16. Use vector data load builtin functions instead}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+half f(half2 h2) {
+return h2.s0;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4193,7 +4193,9 @@
   case ICK_Lvalue_To_Rvalue: {
 assert(From->getObjectKind() != OK_ObjCProperty);
 ExprResult FromRes = DefaultLvalueConversion(From);
-assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+if (FromRes.isInvalid())
+  return ExprError();
+
 From = FromRes.get();
 FromType = From->getType();
 break;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103252: [C++4OpenCL] Fix missing address space on implicit move assignment operator

2021-05-27 Thread Ole Strohm via Phabricator via cfe-commits
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 missing address space on `this` in the implicit move assignment 
operator.
The function called here is an abstraction around the lines that have been 
removed, and also sets the address space correctly.
This is copied from CopyConstructor, CopyAssignment and MoveConstructor, all of 
which use this new function, and now
MoveAssignment is has been aligned to use the same method.

I also added a new test file to check the output AST. If there's a better place 
for this test I will move it there.

Fixes: PR50259


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103252

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/SemaOpenCLCXX/addrspace-assignment.clcpp


Index: clang/test/SemaOpenCLCXX/addrspace-assignment.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-assignment.clcpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -ast-dump -pedantic -verify | FileCheck %s
+
+
+// CHECK: CXXConstructorDecl {{.*}} implicit {{.*}} Implicit 'void (const 
__generic Implicit &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit {{.*}} Implicit 'void (__generic 
Implicit &&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit {{.*}} operator= '__generic Implicit 
&(const __generic Implicit &) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit {{.*}} operator= '__generic Implicit 
&(__generic Implicit &&) __generic'
+// expected-note@+2{{candidate function (the implicit copy assignment 
operator) not viable: no known conversion from 'int' to 'const __generic 
Implicit' for 1st argument}}
+// expected-note@+1{{candidate function (the implicit move assignment 
operator) not viable: no known conversion from 'int' to '__generic Implicit' 
for 1st argument}}
+struct Implicit {};
+
+void f() {
+Implicit i;
+i = 10; // expected-error{{no viable overloaded '='}}
+}
+
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14299,10 +14299,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,


Index: clang/test/SemaOpenCLCXX/addrspace-assignment.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-assignment.clcpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -ast-dump -pedantic -verify | FileCheck %s
+
+
+// CHECK: CXXConstructorDecl {{.*}} implicit {{.*}} Implicit 'void (const __generic Implicit &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit {{.*}} Implicit 'void (__generic Implicit &&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit {{.*}} operator= '__generic Implicit &(const __generic Implicit &) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit {{.*}} operator= '__generic Implicit &(__generic Implicit &&) __generic'
+// expected-note@+2{{candidate function (the implicit copy assignment operator) not viable: no known conversion from 'int' to 'const __generic Implicit' for 1st argument}}
+// expected-note@+1{{candidate function (the implicit move assignment operator) not viable: no known conversion from 'int' to '__generic Implicit' for 1st argument}}
+struct Implicit {};
+
+void f() {
+Implicit i;
+i = 10; // expected-error{{no viable overloaded '='}}
+}
+
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14299,10 +14299,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102689: [C++4OpenCL] Allow address space conversion in reinterpret_cast

2021-06-01 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaCast.cpp:2359
 
-  if (SrcType == DestType) {
+  if (SrcType == Self.Context.removeAddrSpaceQualType(DestType)) {
 // C++ 5.2.10p2 has a note that mentions that, subject to all other

rjmccall wrote:
> I think the upshot of the conversation Richard and I just had is that there's 
> a bug here for all qualifiers; that is, `reinterpret_cast(5)` 
> should be allowed.  Probably the right thing to do is to strip qualifiers 
> from DestType in the CastOperation constructor when the type is not a class 
> or an array.  Richard, do you agree?  This isn't strictly implied by the C++ 
> wording since the semantic analysis of the cast is logically prior to the 
> introduction of a qualifier pr-value expression.
Ah, I see, I did indeed misunderstand the conversation above. I see now that 
with what Richard mentioned with `If a prvalue initially has the type “cv T”, 
where T is a cv-unqualified non-class, non-array type, the type of the 
expression is adjusted to T prior to any further analysis.` it makes sense to 
strip qualifiers for those cases. I also checked out gcc to compare to another 
implementation, and it does work there, so this behaviour doesn't seem 
unreasonable.

I'll rework this to strip all qualifiers somewhere in the CastOperation 
constructor as you suggested then.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103175: [C++4OpenCL] Fix ICE with invalid use of half

2021-06-01 Thread Ole Strohm via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG94b0aec0f5c6: [OpenCL] Fix ICE with invalid use of half 
(authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103175/new/

https://reviews.llvm.org/D103175

Files:
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaOpenCLCXX/half.clcpp


Index: clang/test/SemaOpenCLCXX/half.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/half.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -verify -fsyntax-only
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : disable
+
+typedef half half2 __attribute__((ext_vector_type(2)));
+
+half f(half2 h2) { // expected-error{{declaring function return value of type 
'half' is not allowed ; did you forget * ?}}
+return h2.s0; // expected-error{{loading directly from pointer to type 
'__private half' requires cl_khr_fp16. Use vector data load builtin functions 
instead}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+half f(half2 h2) {
+return h2.s0;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4193,7 +4193,9 @@
   case ICK_Lvalue_To_Rvalue: {
 assert(From->getObjectKind() != OK_ObjCProperty);
 ExprResult FromRes = DefaultLvalueConversion(From);
-assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+if (FromRes.isInvalid())
+  return ExprError();
+
 From = FromRes.get();
 FromType = From->getType();
 break;


Index: clang/test/SemaOpenCLCXX/half.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/half.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -verify -fsyntax-only
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : disable
+
+typedef half half2 __attribute__((ext_vector_type(2)));
+
+half f(half2 h2) { // expected-error{{declaring function return value of type 'half' is not allowed ; did you forget * ?}}
+return h2.s0; // expected-error{{loading directly from pointer to type '__private half' requires cl_khr_fp16. Use vector data load builtin functions instead}}
+}
+
+#pragma OPENCL EXTENSION cl_khr_fp16 : enable
+
+half f(half2 h2) {
+return h2.s0;
+}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -4193,7 +4193,9 @@
   case ICK_Lvalue_To_Rvalue: {
 assert(From->getObjectKind() != OK_ObjCProperty);
 ExprResult FromRes = DefaultLvalueConversion(From);
-assert(!FromRes.isInvalid() && "Can't perform deduced conversion?!");
+if (FromRes.isInvalid())
+  return ExprError();
+
 From = FromRes.get();
 FromType = From->getType();
 break;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103252: [C++4OpenCL] Fix missing address space on implicit move assignment operator

2021-06-01 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 348969.
olestrohm added a comment.

Cleaned up the test by renaming the struct and making the test compile.

The test has also been moved to `clang/test/AST` as suggested, since it really
just makes sure that the generated AST contains the correct implicit methods.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103252/new/

https://reviews.llvm.org/D103252

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/AST/ast-dump-implicit-members.clcpp


Index: clang/test/AST/ast-dump-implicit-members.clcpp
===
--- /dev/null
+++ clang/test/AST/ast-dump-implicit-members.clcpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -ast-dump -ast-dump-filter S | FileCheck 
-strict-whitespace %s
+
+struct S {};
+
+void f() {
+S i;
+i = i;
+}
+
+// CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () 
__generic noexcept'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (const 
__generic S &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (__generic S 
&&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit used constexpr operator= '__generic S 
&(const __generic S &) __generic noexcept'
+// CHECK: CXXMethodDecl {{.*}} implicit constexpr operator= '__generic S 
&(__generic S &&) __generic'
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14299,10 +14299,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,


Index: clang/test/AST/ast-dump-implicit-members.clcpp
===
--- /dev/null
+++ clang/test/AST/ast-dump-implicit-members.clcpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -ast-dump -ast-dump-filter S | FileCheck -strict-whitespace %s
+
+struct S {};
+
+void f() {
+S i;
+i = i;
+}
+
+// CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () __generic noexcept'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (const __generic S &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (__generic S &&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit used constexpr operator= '__generic S &(const __generic S &) __generic noexcept'
+// CHECK: CXXMethodDecl {{.*}} implicit constexpr operator= '__generic S &(__generic S &&) __generic'
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14299,10 +14299,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109609: [C++4OpenCL] Add support for multiple address spaced destructors

2021-09-17 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 373218.
olestrohm added a comment.

I made the implicit destructor always be created in __generic address space.

I couldn't manage to properly figure a case that would trigger 
`LookupSpecialMember`,
so I couldn't figure out how or if address spaces are handled there.

re: @keryell 
This might work, though I have no idea how that `SomeAPIReturningAddrSpace` 
would work, since at this point the variable would likely be cast to be in 
__generic addrspace.
Also I'm not sure how that would interact with deleted destructors.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109609/new/

https://reviews.llvm.org/D109609

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/DeclCXX.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp

Index: clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+// CHECK: CXXDestructorDecl {{.*}} used ~ExactDtor 'void () __private noexcept'
+struct ExactDtor {
+ ~ExactDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~OverloadedDtor 'void () __generic'
+// CHECK: CXXDestructorDecl {{.*}} used ~OverloadedDtor 'void () __private noexcept'
+struct OverloadedDtor {
+ ~OverloadedDtor() __generic;
+ ~OverloadedDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~ImplicitDtor 'void () __global'
+// CHECK: CXXDestructorDecl {{.*}} implicit used ~ImplicitDtor 'void () __generic noexcept'
+struct ImplicitDtor {
+~ImplicitDtor() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~Templated 'void () __generic noexcept'
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~Templated 'void () __global'
+template 
+struct Templated {
+~Templated() __generic;
+~Templated() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __private noexcept'
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __global noexcept'
+struct BothUsed {
+~BothUsed() __private;
+~BothUsed() __global;
+};
+
+__global BothUsed g_inheriting;
+
+kernel void k() {
+__private ExactDtor exact;
+__private OverloadedDtor overloaded;
+__private ImplicitDtor implicit;
+__private Templated templated;
+__private BothUsed inheriting;
+}
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -3054,13 +3054,10 @@
   Functions.append(Operators.begin(), Operators.end());
 }
 
-Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD,
-   CXXSpecialMember SM,
-   bool ConstArg,
-   bool VolatileArg,
-   bool RValueThis,
-   bool ConstThis,
-   bool VolatileThis) {
+Sema::SpecialMemberOverloadResult
+Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMember SM, bool ConstArg,
+  bool VolatileArg, bool RValueThis, bool ConstThis,
+  bool VolatileThis, LangAS AS) {
   assert(CanDeclareSpecialMemberFunction(RD) &&
  "doing special member lookup into record that isn't fully complete");
   RD = RD->getDefinition();
@@ -3082,6 +3079,7 @@
   ID.AddInteger(RValueThis);
   ID.AddInteger(ConstThis);
   ID.AddInteger(VolatileThis);
+  ID.AddInteger((unsigned)AS);
 
   void *InsertPoint;
   SpecialMemberOverloadResultEntry *Result =
@@ -3096,12 +3094,12 @@
   SpecialMemberCache.InsertNode(Result, InsertPoint);
 
   if (SM == CXXDestructor) {
-if (RD->needsImplicitDestructor()) {
+if (RD->needsImplicitDestructor(AS)) {
   runWithSufficientStackSpace(RD->getLocation(), [&] {
 DeclareImplicitDestructor(RD);
   });
 }
-CXXDestructorDecl *DD = RD->getDestructor();
+CXXDestructorDecl *DD = RD->getDestructor(AS);
 Result->setMethod(DD);
 Result->setKind(DD && !DD->isDeleted()
 ? SpecialMemberOverloadResult::Success
@@ -3362,10 +3360,11 @@
 /// CXXRecordDecl::getDestructor().
 ///
 /// \returns The destructor for this class.
-CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class, LangAS AS) {
   return cast(LookupSpecialMember(Class, CXXDestructor,
- false, false, false,
- 

[PATCH] D109609: [C++4OpenCL] Add support for multiple address spaced destructors

2021-09-17 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm marked 2 inline comments as done.
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaLookup.cpp:3082
   ID.AddInteger(VolatileThis);
+  ID.AddInteger((unsigned)AS);
 

Anastasia wrote:
> Btw ctors and assignments don't seem to need this but they seem to work fine 
> though... 
> 
> 
> For example here the right assignment overload with `__local` address space 
> is selected
> https://godbolt.org/z/aYKj4W6rc
> or ctor overload with `__global` is selected here correctly:
> https://godbolt.org/z/1frheezE5
> 
> So it seems like there is some other logic to handle address spaces for 
> special members elsewhere? Although it is very strange and rather confusing.
Yes, it seems other special members are handled somewhere else according to my 
preliminary investigations, so that might explain why address spaces where 
never introduced into this function.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109609/new/

https://reviews.llvm.org/D109609

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109609: [C++4OpenCL] Add support for multiple address spaced destructors

2021-09-17 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 373225.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109609/new/

https://reviews.llvm.org/D109609

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/DeclCXX.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp

Index: clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+// CHECK: CXXDestructorDecl {{.*}} used ~ExactDtor 'void () __private noexcept'
+struct ExactDtor {
+ ~ExactDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~OverloadedDtor 'void () __generic'
+// CHECK: CXXDestructorDecl {{.*}} used ~OverloadedDtor 'void () __private noexcept'
+struct OverloadedDtor {
+ ~OverloadedDtor() __generic;
+ ~OverloadedDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~ImplicitDtor 'void () __global'
+// CHECK: CXXDestructorDecl {{.*}} implicit used ~ImplicitDtor 'void () __generic noexcept'
+struct ImplicitDtor {
+~ImplicitDtor() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~Templated 'void () __generic noexcept'
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~Templated 'void () __global'
+template 
+struct Templated {
+~Templated() __generic;
+~Templated() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __private noexcept'
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __global noexcept'
+struct BothUsed {
+~BothUsed() __private;
+~BothUsed() __global;
+};
+
+__global BothUsed g_inheriting;
+
+kernel void k() {
+__private ExactDtor exact;
+__private OverloadedDtor overloaded;
+__private ImplicitDtor implicit;
+__private Templated templated;
+__private BothUsed inheriting;
+}
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -3054,13 +3054,10 @@
   Functions.append(Operators.begin(), Operators.end());
 }
 
-Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD,
-   CXXSpecialMember SM,
-   bool ConstArg,
-   bool VolatileArg,
-   bool RValueThis,
-   bool ConstThis,
-   bool VolatileThis) {
+Sema::SpecialMemberOverloadResult
+Sema::LookupSpecialMember(CXXRecordDecl *RD, CXXSpecialMember SM, bool ConstArg,
+  bool VolatileArg, bool RValueThis, bool ConstThis,
+  bool VolatileThis, LangAS ASThis) {
   assert(CanDeclareSpecialMemberFunction(RD) &&
  "doing special member lookup into record that isn't fully complete");
   RD = RD->getDefinition();
@@ -3082,6 +3079,7 @@
   ID.AddInteger(RValueThis);
   ID.AddInteger(ConstThis);
   ID.AddInteger(VolatileThis);
+  ID.AddInteger((unsigned)ASThis);
 
   void *InsertPoint;
   SpecialMemberOverloadResultEntry *Result =
@@ -3096,12 +3094,12 @@
   SpecialMemberCache.InsertNode(Result, InsertPoint);
 
   if (SM == CXXDestructor) {
-if (RD->needsImplicitDestructor()) {
+if (RD->needsImplicitDestructor(ASThis)) {
   runWithSufficientStackSpace(RD->getLocation(), [&] {
 DeclareImplicitDestructor(RD);
   });
 }
-CXXDestructorDecl *DD = RD->getDestructor();
+CXXDestructorDecl *DD = RD->getDestructor(ASThis);
 Result->setMethod(DD);
 Result->setKind(DD && !DD->isDeleted()
 ? SpecialMemberOverloadResult::Success
@@ -3362,10 +3360,11 @@
 /// CXXRecordDecl::getDestructor().
 ///
 /// \returns The destructor for this class.
-CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class) {
+CXXDestructorDecl *Sema::LookupDestructor(CXXRecordDecl *Class, LangAS AS) {
   return cast(LookupSpecialMember(Class, CXXDestructor,
- false, false, false,
- false, false).getMethod());
+ false, false, false, false,
+ false, AS)
+ .getMethod());
 }
 
 /// LookupLiteralOperator - Determine which literal operator should be used for
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/Se

[PATCH] D103252: [C++4OpenCL] Fix missing address space on implicit move assignment operator

2021-06-07 Thread Ole Strohm via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG438cf5577e72: [OpenCL] Fix missing addrspace on implicit 
move assignment operator (authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103252/new/

https://reviews.llvm.org/D103252

Files:
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/test/AST/ast-dump-implicit-members.clcpp


Index: clang/test/AST/ast-dump-implicit-members.clcpp
===
--- /dev/null
+++ clang/test/AST/ast-dump-implicit-members.clcpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -ast-dump -ast-dump-filter S | FileCheck 
-strict-whitespace %s
+
+struct S {};
+
+void f() {
+S i;
+i = i;
+}
+
+// CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () 
__generic noexcept'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (const 
__generic S &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (__generic S 
&&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit used constexpr operator= '__generic S 
&(const __generic S &) __generic noexcept'
+// CHECK: CXXMethodDecl {{.*}} implicit constexpr operator= '__generic S 
&(__generic S &&) __generic'
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14344,10 +14344,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,


Index: clang/test/AST/ast-dump-implicit-members.clcpp
===
--- /dev/null
+++ clang/test/AST/ast-dump-implicit-members.clcpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 %s -ast-dump -ast-dump-filter S | FileCheck -strict-whitespace %s
+
+struct S {};
+
+void f() {
+S i;
+i = i;
+}
+
+// CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () __generic noexcept'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (const __generic S &) __generic'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (__generic S &&) __generic'
+// CHECK: CXXMethodDecl {{.*}} implicit used constexpr operator= '__generic S &(const __generic S &) __generic noexcept'
+// CHECK: CXXMethodDecl {{.*}} implicit constexpr operator= '__generic S &(__generic S &&) __generic'
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -14344,10 +14344,7 @@
 /* Diagnose */ false);
   }
 
-  // Build an exception specification pointing back at this member.
-  FunctionProtoType::ExtProtoInfo EPI =
-  getImplicitMethodEPI(*this, MoveAssignment);
-  MoveAssignment->setType(Context.getFunctionType(RetType, ArgType, EPI));
+  setupImplicitSpecialMemberType(MoveAssignment, RetType, ArgType);
 
   // Add the parameter to the operator.
   ParmVarDecl *FromParam = ParmVarDecl::Create(Context, MoveAssignment,
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102689: [C++] Ignore top-level qualifiers in casts

2021-06-08 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 350560.
olestrohm retitled this revision from "[C++4OpenCL] Allow address space 
conversion in reinterpret_cast" to "[C++] Ignore top-level qualifiers in casts".
olestrohm edited the summary of this revision.
olestrohm added a comment.

I've added a check in the constructor for CastOperator that removes qualifiers 
for non-class, non-array types.
I had to add a check for ObjectiveC, since they seem to use qualifiers for a 
lot of language features,
but maybe a better solution would be to remove specific qualifiers instead?

This actually didn't cause that many changes in behaviour or error messages, 
maybe because the other casts
already have checks for this, but there was one change in a C++ test that looks 
a little strange after this patch,
but maybe that's alright.

Hopefully this is makes sense, but do suggest changes to the approach if you 
think there is a better one.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaCXX/reinterpret-cast.cpp
  clang/test/SemaCXX/warn-reinterpret-base-class.cpp
  clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
 
+struct X {};
+
+__global int g = 0;
+__global int *__global g_ptr = &g;
+
 kernel void foo() {
   // Testing conversions between vectors and vectors/scalars
   long l1;
@@ -13,6 +18,18 @@
   auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  // Testing reinterpret_cast with address spaces.
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
+  __private X x;
+  auto x2 = reinterpret_cast<__private X>(x); // expected-error{{reinterpret_cast from '__private X' to '__private X' is not allowed}}
+
+  auto ptr = reinterpret_cast<__global int* __private>(g_ptr);
+  (void)reinterpret_cast<__private int* __private>(g_ptr); // expected-error{{reinterpret_cast from '__global int *' to '__private int *' is not allowed}}
+
   // Only integral types (and pointer/references) can be reinterpret casted to themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
@@ -22,7 +22,7 @@
 void test_temp(__global int *par) {
   T *var1 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
   __private T *var2 = addrspace_cast<__private T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
-  T var3 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int' is not allowed}}
+  T var3 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to 'int' is not allowed}}
 }
 
 void bar() {
Index: clang/test/SemaCXX/warn-reinterpret-base-class.cpp
===
--- clang/test/SemaCXX/warn-reinterpret-base-class.cpp
+++ clang/test/SemaCXX/warn-reinterpret-base-class.cpp
@@ -298,7 +298,7 @@
 #endif
   (void)reinterpret_cast(a);
 
-  // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
+  // expected-warning@+2 {{'reinterpret_cast' to class 'K' (aka 'const F *') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
   // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}}
   (void)reinterpret_cast(e);
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast"
Index: clang/test/SemaCXX/reinterpret-cast.cpp
===
--- clang/test/SemaCXX/reinterpret-cast.cpp
+++ clang/test/SemaCXX/reinterpret-cast.cpp
@@ -25,6 +25,9 @@
   const int structure::*psi = 0;
   (void)reinterpret_cast(psi);
 
+  const int ci = 0;
+  (void)reinterpret_cast(i);
+
   structure s;
   (void)reinterpret_cast(s); // expected-error {{reinterpret_cast from 'structure' to 'structu

[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-06-08 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 350561.
olestrohm added a comment.

I've reverted to using Constructors and prioritizing based on which constructor 
is the most qualified.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

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


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must 
be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} 
__generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} 
__global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //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 {
@@ -20,6 +28,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must 
be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,19 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  const auto *CD1 = dyn_cast_or_null(Cand1.Function);
+  const auto *CD2 = dyn_cast_or_null(Cand2.Function);
+  if (CD1 && CD2) {
+QualType TT1 = CD1->getThisObjectType();
+QualType TT2 = CD2->getThisObjectType();
+if (TT1.getUnqualifiedType() == TT2.getUnqualifiedType() && TT1 != TT2) {
+  if (TT2.isAtLeastAsQualifiedAs(TT1))
+return true;
+  if (TT1.isAtLeastAsQualifiedAs(TT2))
+return false;
+}
+  }
+
   return false;
 }
 


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,22 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK: -CXXConstructorDecl {{.*}} X 'void (){{( __attribute__.*)?}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __private'
+  X() __private : x(0) {}
+//CHECK: -CXXConstructorDecl {{.*}} used X 'void (){{( __attribute__.*)?}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //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 {
@@ -20,6 +28,7 @@
   __constant X cx1;

[PATCH] D102689: [C++] Ignore top-level qualifiers in casts

2021-06-09 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/test/SemaCXX/warn-reinterpret-base-class.cpp:301
 
-  // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F 
*volatile') from its base at non-zero offset 'E *' behaves differently from 
'static_cast'}}
+  // expected-warning@+2 {{'reinterpret_cast' to class 'K' (aka 'const F *') 
from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
   // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly 
while downcasting}}

Anastasia wrote:
> I wonder if there is a way to track the original type for the diagnostic? Or 
> maybe it is intuitive enough considering the quoted spec wording...
This actually already happens with the source type too.
const short s = 0;
reinterpret_cast(s);

gives the error "reinterpret_cast from 'short' to 'int' is not allowed", so 
while this is definitely worse, it's a general problem with reinterpret_cast.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103962: [C++4OpenCL] Fix qualifiers check on binding references to temporaries

2021-06-09 Thread Ole Strohm via Phabricator via cfe-commits
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.

Fixing the qualifiers check from PR49733.

It would be great to add some test, to increase the coverage, and because the 
erroneous check doesn't seem to trigger in any tests.
However I couldn't come up with a case that did trigger it, so it may be that 
it can't happen, or at least is very unlikely.

Fixes: PR49733


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103962

Files:
  clang/lib/Sema/SemaInit.cpp


Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -5063,9 +5063,9 @@
   //than, cv2; otherwise, the program is ill-formed.
   unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
   unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
-  if ((RefRelationship == Sema::Ref_Related &&
-   (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
-  !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+  if (RefRelationship == Sema::Ref_Related &&
+  ((T1CVRQuals | T2CVRQuals) != T1CVRQuals ||
+   !T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
 
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
 return;
   }


Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -5063,9 +5063,9 @@
   //than, cv2; otherwise, the program is ill-formed.
   unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
   unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
-  if ((RefRelationship == Sema::Ref_Related &&
-   (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
-  !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+  if (RefRelationship == Sema::Ref_Related &&
+  ((T1CVRQuals | T2CVRQuals) != T1CVRQuals ||
+   !T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
 Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
 return;
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D103252: [C++4OpenCL] Fix missing address space on implicit move assignment operator

2021-06-10 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/test/AST/ast-dump-implicit-members.clcpp:10
+
+// CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () 
__generic noexcept'
+// CHECK: CXXConstructorDecl {{.*}} implicit constexpr S 'void (const 
__generic S &) __generic'

abhinavgaba wrote:
> Could you please relax these checks? The test fails with `-triple 
> i386-pc-win32`  with errors like this:
> ```
> ast-dump-implicit-members.clcpp:10:11: error: CHECK: expected string not 
> found in input
> // CHECK: CXXConstructorDecl {{.*}} implicit used constexpr S 'void () 
> __generic noexcept'
>   ^
> :1:1: note: scanning from here
> Dumping __NSConstantString:
> ^
> :16:18: note: possible intended match here
> |-CXXConstructorDecl 0x10b6c718  col:8 implicit used constexpr S 'void 
> () __attribute__((thiscall)) __generic noexcept' inline default trivial
>  ^
> ```
Hi, sorry for this.
I have relaxed the tests in rGac677e69bdfc, so hopefully that should fix it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103252/new/

https://reviews.llvm.org/D103252

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-06-10 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 351165.
olestrohm added a comment.

Added a comment explaining what the check is meant for.

Also added a `CHECK-NOT: used` to properly test that the __generic constructor 
is not used.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

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


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,24 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must 
be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK:  CXXConstructorDecl
+//CHECK-NOT:  used
+//CHECK-SAME: X 'void (){{.*}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __private'
+  X() __private : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //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 {
@@ -20,6 +30,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must 
be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,23 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  // Method overloading is handled above, so this only handles
+  // constructors with address spaces.
+  // This only handles address spaces since C++ has no other
+  // qualifier that can be used with constructors.
+  const auto *CD1 = dyn_cast_or_null(Cand1.Function);
+  const auto *CD2 = dyn_cast_or_null(Cand2.Function);
+  if (CD1 && CD2) {
+LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace();
+LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace();
+if (AS1 != AS2) {
+  if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+return true;
+  if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+return false;
+}
+  }
+
   return false;
 }
 


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,24 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK:  CXXConstructorDecl
+//CHECK-NOT:  used
+//CHECK-SAME: X 'void (){{.*}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __private'
+  X() __private : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note@+2{{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const __generic Y' for

[PATCH] D102850: [C++4OpenCL] Fix overloading resolution of addrspace constructors

2021-06-11 Thread Ole Strohm via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb102e6880ab0: [OpenCL] Fix overloading resolution of 
addrspace constructors (authored by olestrohm).

Changed prior to commit:
  https://reviews.llvm.org/D102850?vs=351165&id=351388#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102850/new/

https://reviews.llvm.org/D102850

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


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,24 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must 
be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK:  CXXConstructorDecl
+//CHECK-NOT:  used
+//CHECK-SAME: X 'void (){{.*}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __private'
+  X() __private : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //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 {
@@ -20,6 +30,7 @@
   __constant X cx1;
   __constant X cx2(1);
   __local X lx;
+  __private X x;
 
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must 
be initialized}}
Index: clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/CodeGenOpenCLCXX/addrspace-constructors.clcpp
@@ -11,8 +11,7 @@
   int x;
 
   // Local variables are handled in local_addrspace_init.clcpp
-  // FIXME: __private and __generic constructors clash for __private variable
-  // X() /*__generic*/ = default;
+  X() /*__generic*/ : x(0) {}
   X() __private : x(0) {}
   X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
@@ -30,7 +29,7 @@
 // CHECK: @_ZZ1kE3cx2 = internal addrspace(2) constant %struct.X { i32 1 }
 
 kernel void k() {
-  // Check that the constructor for px is executed
+  // Check that the constructor for px calls the __private constructor.
   // CHECK: %px = alloca %struct.X
   // CHECK-NEXT: call spir_func void @_ZN1XC1Ev(%struct.X* {{.*}}%px)
   __private X px;
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -9867,6 +9867,23 @@
S.IdentifyCUDAPreference(Caller, Cand2.Function);
   }
 
+  // General member function overloading is handled above, so this only handles
+  // constructors with address spaces.
+  // This only handles address spaces since C++ has no other
+  // qualifier that can be used with constructors.
+  const auto *CD1 = dyn_cast_or_null(Cand1.Function);
+  const auto *CD2 = dyn_cast_or_null(Cand2.Function);
+  if (CD1 && CD2) {
+LangAS AS1 = CD1->getMethodQualifiers().getAddressSpace();
+LangAS AS2 = CD2->getMethodQualifiers().getAddressSpace();
+if (AS1 != AS2) {
+  if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+return true;
+  if (Qualifiers::isAddressSpaceSupersetOf(AS2, AS1))
+return false;
+}
+  }
+
   return false;
 }
 


Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -1,14 +1,24 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -ast-dump -verify | FileCheck %s
 
 __constant int g1; // expected-error {{variable in constant address space must be initialized}}
 __constant int g2 = 0;
 
 struct X {
   int x;
+//CHECK:  CXXConstructorDecl
+//CHECK-NOT:  used
+//CHECK-SAME: X 'void (){{.*}} __generic'
+  X() /*__generic*/ : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __private'
+  X() __private : x(0) {}
+//CHECK: CXXConstructorDecl {{.*}} used X 'void (){{.*}} __global'
+  X() __global : x(0) {}
   constexpr X() __constant : x(0) {}
   constexpr X(int x) __constant : x(x) {}
 };
 
+__global X gx;
+
 //expected-note@+2{{candidate cons

[PATCH] D107553: [C++4OpenCL] Initialize temporaries in the private address space

2021-08-05 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, rjmccall.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

This patch fixes initializing temporaries, which are currently initialized 
without an address space, meaning that no constructor can ever be applicable.
This is also working towards putting temporaries in the private address space.

Fixes the second issue in PR43296.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D107553

Files:
  clang/include/clang/Sema/Initialization.h
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
  clang/test/SemaOpenCLCXX/temporaries.clcpp


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = X();
+
   __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'}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1454,7 +1454,8 @@
  "List initialization must have initializer list as expression.");
   SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
 
-  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
+  InitializedEntity Entity =
+  InitializedEntity::InitializeTemporary(Context, TInfo);
   InitializationKind Kind =
   Exprs.size()
   ? ListInitialization
@@ -5293,7 +5294,8 @@
 S, Sema::ExpressionEvaluationContext::Unevaluated);
 Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0]));
+InitializedEntity To(
+InitializedEntity::InitializeTemporary(S.Context, Args[0]));
 InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc,
  RParenLoc));
 InitializationSequence Init(S, To, InitKind, ArgExprs);
Index: clang/include/clang/Sema/Initialization.h
===
--- clang/include/clang/Sema/Initialization.h
+++ clang/include/clang/Sema/Initialization.h
@@ -335,8 +335,13 @@
   }
 
   /// Create the initialization entity for a temporary.
-  static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
-return InitializeTemporary(TypeInfo, TypeInfo->getType());
+  static InitializedEntity InitializeTemporary(ASTContext &Context,
+   TypeSourceInfo *TypeInfo) {
+QualType Type = TypeInfo->getType();
+if (Context.getLangOpts().OpenCL && !Type.hasAddressSpace())
+  Type = Context.getAddrSpaceQualType(Type, LangAS::opencl_private);
+
+return InitializeTemporary(TypeInfo, Type);
   }
 
   /// Create the initialization entity for a temporary.


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = 

[PATCH] D107553: [C++4OpenCL] Initialize temporaries in the private address space

2021-08-19 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 367455.
olestrohm added a comment.

I made the check into an assert as suggested.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107553/new/

https://reviews.llvm.org/D107553

Files:
  clang/include/clang/Sema/Initialization.h
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
  clang/test/SemaOpenCLCXX/temporaries.clcpp


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = X();
+
   __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'}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1454,7 +1454,8 @@
  "List initialization must have initializer list as expression.");
   SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
 
-  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
+  InitializedEntity Entity =
+  InitializedEntity::InitializeTemporary(Context, TInfo);
   InitializationKind Kind =
   Exprs.size()
   ? ListInitialization
@@ -5293,7 +5294,8 @@
 S, Sema::ExpressionEvaluationContext::Unevaluated);
 Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0]));
+InitializedEntity To(
+InitializedEntity::InitializeTemporary(S.Context, Args[0]));
 InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc,
  RParenLoc));
 InitializationSequence Init(S, To, InitKind, ArgExprs);
Index: clang/include/clang/Sema/Initialization.h
===
--- clang/include/clang/Sema/Initialization.h
+++ clang/include/clang/Sema/Initialization.h
@@ -335,8 +335,15 @@
   }
 
   /// Create the initialization entity for a temporary.
-  static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
-return InitializeTemporary(TypeInfo, TypeInfo->getType());
+  static InitializedEntity InitializeTemporary(ASTContext &Context,
+   TypeSourceInfo *TypeInfo) {
+QualType Type = TypeInfo->getType();
+if (Context.getLangOpts().OpenCLCPlusPlus) {
+  assert(!Type.hasAddressSpace() && "Temporary already has address 
space!");
+  Type = Context.getAddrSpaceQualType(Type, LangAS::opencl_private);
+}
+
+return InitializeTemporary(TypeInfo, Type);
   }
 
   /// Create the initialization entity for a temporary.


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = X();
+
   __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'}}
Index: clang/lib/Sema/SemaExprCXX.cpp
=

[PATCH] D103962: [C++4OpenCL] Fix qualifiers check on binding references to temporaries

2021-06-29 Thread Ole Strohm via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG78d309ce197c: [OpenCL] Fix qualifiers check on binding 
references to temporaries (authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D103962/new/

https://reviews.llvm.org/D103962

Files:
  clang/lib/Sema/SemaInit.cpp


Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -5065,9 +5065,9 @@
   //than, cv2; otherwise, the program is ill-formed.
   unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
   unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
-  if ((RefRelationship == Sema::Ref_Related &&
-   (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
-  !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+  if (RefRelationship == Sema::Ref_Related &&
+  ((T1CVRQuals | T2CVRQuals) != T1CVRQuals ||
+   !T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
 
Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
 return;
   }


Index: clang/lib/Sema/SemaInit.cpp
===
--- clang/lib/Sema/SemaInit.cpp
+++ clang/lib/Sema/SemaInit.cpp
@@ -5065,9 +5065,9 @@
   //than, cv2; otherwise, the program is ill-formed.
   unsigned T1CVRQuals = T1Quals.getCVRQualifiers();
   unsigned T2CVRQuals = T2Quals.getCVRQualifiers();
-  if ((RefRelationship == Sema::Ref_Related &&
-   (T1CVRQuals | T2CVRQuals) != T1CVRQuals) ||
-  !T1Quals.isAddressSpaceSupersetOf(T2Quals)) {
+  if (RefRelationship == Sema::Ref_Related &&
+  ((T1CVRQuals | T2CVRQuals) != T1CVRQuals ||
+   !T1Quals.isAddressSpaceSupersetOf(T2Quals))) {
 Sequence.SetFailed(InitializationSequence::FK_ReferenceInitDropsQualifiers);
 return;
   }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D102689: [C++] Ignore top-level qualifiers in casts

2021-07-05 Thread Ole Strohm via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG85255a04e572: [C++][Sema] Ignore top-level qualifiers in 
casts (authored by olestrohm).

Changed prior to commit:
  https://reviews.llvm.org/D102689?vs=350560&id=356472#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D102689/new/

https://reviews.llvm.org/D102689

Files:
  clang/lib/Sema/SemaCast.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaCXX/reinterpret-cast.cpp
  clang/test/SemaCXX/warn-reinterpret-base-class.cpp
  clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -4,6 +4,11 @@
 typedef int int3 __attribute__((ext_vector_type(3)));
 typedef int int4 __attribute__((ext_vector_type(4)));
 
+struct X {};
+
+__global int g = 0;
+__global int *__global g_ptr = &g;
+
 kernel void foo() {
   // Testing conversions between vectors and vectors/scalars
   long l1;
@@ -13,6 +18,18 @@
   auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
   auto i2_to_i2 = reinterpret_cast(i2);
 
+  // Testing reinterpret_cast with address spaces.
+  __private short s;
+  auto s2 = reinterpret_cast<__private short>(s);
+  auto s3 = reinterpret_cast(s);
+  auto s4 = reinterpret_cast<__global short>(s);
+
+  __private X x;
+  auto x2 = reinterpret_cast<__private X>(x); // expected-error{{reinterpret_cast from '__private X' to '__private X' is not allowed}}
+
+  auto ptr = reinterpret_cast<__global int* __private>(g_ptr);
+  (void)reinterpret_cast<__private int* __private>(g_ptr); // expected-error{{reinterpret_cast from '__global int *' to '__private int *' is not allowed}}
+
   // Only integral types (and pointer/references) can be reinterpret casted to themselves.
   // Currently this does not include any opencl types.
   reserve_id_t r_id1;
Index: clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace_cast.clcpp
@@ -22,7 +22,7 @@
 void test_temp(__global int *par) {
   T *var1 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
   __private T *var2 = addrspace_cast<__private T *>(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int *' converts between mismatching address spaces}}
-  T var3 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to '__private int' is not allowed}}
+  T var3 = addrspace_cast(par); //expected-error{{addrspace_cast from '__global int *__private' to 'int' is not allowed}}
 }
 
 void bar() {
Index: clang/test/SemaCXX/warn-reinterpret-base-class.cpp
===
--- clang/test/SemaCXX/warn-reinterpret-base-class.cpp
+++ clang/test/SemaCXX/warn-reinterpret-base-class.cpp
@@ -298,7 +298,7 @@
 #endif
   (void)reinterpret_cast(a);
 
-  // expected-warning@+2 {{'reinterpret_cast' to class 'L' (aka 'const F *volatile') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
+  // expected-warning@+2 {{'reinterpret_cast' to class 'K' (aka 'const F *') from its base at non-zero offset 'E *' behaves differently from 'static_cast'}}
   // expected-note@+1 {{use 'static_cast' to adjust the pointer correctly while downcasting}}
   (void)reinterpret_cast(e);
   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:9-[[@LINE-1]]:25}:"static_cast"
Index: clang/test/SemaCXX/reinterpret-cast.cpp
===
--- clang/test/SemaCXX/reinterpret-cast.cpp
+++ clang/test/SemaCXX/reinterpret-cast.cpp
@@ -25,6 +25,9 @@
   const int structure::*psi = 0;
   (void)reinterpret_cast(psi);
 
+  const int ci = 0;
+  (void)reinterpret_cast(i);
+
   structure s;
   (void)reinterpret_cast(s); // expected-error {{reinterpret_cast from 'structure' to 'structure' is not allowed}}
 
@@ -68,6 +71,16 @@
   (void)reinterpret_cast(ip);
   // Valid: T*** -> T2 const* const* const*
   (void)reinterpret_cast(ipppc);
+
+  // C++ [expr.type]/8.2.2:
+  //   If a pr-value initially has the type cv-T, where T is a
+  //   cv-unqualified non-class, non-array type, the type of the
+  //   expression is adjusted to T prior to any further analysis.
+  int i = 0;
+  // Valid: T -> T (top level const is ignored)
+  (void)reinterpret_cast(i);
+  // Valid: T* -> T* (top level const is ignored)
+  (void)reinterpret_cast(ip);
 }
 
 void f

[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-22 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added a comment.

The only ones that change (in the test cases at least) are as follows:
Here Old is with the current change, and New is with the call to 
`diagnoseOpenCLTypes` at parsing removed.

In `event_t.cl`, `event_t glb_evt;` in program scope has this difference:

  Old:
the '__private event_t' type cannot be used to declare a program scope 
variable
  New:
program scope variable must reside in constant address space

In `template-opencl-types.clcpp`, `__local event_t e;` inside a function has 
this difference:

  Old:
the event_t type can only be used with __private address space qualifier
  New:
non-kernel function variable cannot be declared in local address space

The first on explains that `event_t` can't be used in program scope at all, 
which is better I think.
However the second error actually gets slightly better.

I think these errors are primarily emitted between the two checks, so I don't 
know if it's easy to put the check somewhere that gives better results.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100860/new/

https://reviews.llvm.org/D100860

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-23 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 339976.
olestrohm added a comment.

I noticed that I could move the new check above the diagnostic for program 
scope variables, and the check during parsing can then be removed, while 
maintaining good diagnostics.

This does change the diagnostic for `event_t` mentioned above, however it's not 
a bad diagnostic, and actually matches what happens in non-kernel functions, so 
I think it's okay.
I would prefer the previous diagnostic for `event_t`, but that originates in 
the other branch of the same if statement as the program scope diagnostic, so 
it's not easy to separate them out and then insert the new check between them.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100860/new/

https://reviews.llvm.org/D100860

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCL/clk_event_t.cl
  clang/test/SemaOpenCL/event_t.cl
  clang/test/SemaOpenCL/sampler_t.cl
  clang/test/SemaOpenCLCXX/template-opencl-types.clcpp

Index: clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template
+T global_variable; // expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+clk_event_t global_event; // expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+template
+void templ() {
+  T loc;
+  // expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  // expected-error@-2{{declaring variable of type '__private half' is not allowed}}
+  // expected-error@-3{{the event_t type can only be used with __private address space qualifier}}
+}
+
+void foo() {
+  templ(); // expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ(); // expected-note{{in instantiation of function template specialization 'templ' requested here}}
+  templ<__local event_t>(); // expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}}
+
+  image1d_t img; // expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  half h; // expected-error{{declaring variable of type '__private half' is not allowed}}
+  __local event_t e; // expected-error{{the event_t type can only be used with __private address space qualifier}}
+
+  (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+}
Index: clang/test/SemaOpenCL/sampler_t.cl
===
--- clang/test/SemaOpenCL/sampler_t.cl
+++ clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@
 sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
 
 sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}}
-#ifdef CHECK_SAMPLER_VALUE
-// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
-#endif
 
 const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
 const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
Index: clang/test/SemaOpenCL/event_t.cl
===
--- clang/test/SemaOpenCL/event_t.cl
+++ clang/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
 
-event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}}
+event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}}
 
 constant struct evt_s {
   event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
@@ -10,7 +10,7 @@
 
 void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}}
   event_t e;
-  constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}}
+  constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}}
   foo(e);
   foo(0);
   foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}}
Index: clang/test/SemaOpenCL/clk_event_t.cl
===
--- clang/test/SemaOpenCL/clk_event_t.cl
+++ clang/test/S

[PATCH] D101168: [C++4OpenCL] Add clang extension for unsafe kernel parameters

2021-04-23 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, kerbowa, jfb, yaxunl, nhaehnle, jvesely, 
jholewinski.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

This feature allows using non-portable types as kernel parameters. This allows 
bypassing the portability guarantees from the restrictions specified
in C++ for OpenCL v1.0 s2.4 
.

Currently this only disables the restrictions related to layout, as a 
programmer using the same compiler for host and device should get the same 
representation.
This could be extended to other things (like `size_t`) if desired in the 
future, but I think it's unlikely that someone would want that.

Previous discussion about the extension in 
https://bugs.llvm.org/show_bug.cgi?id=50081


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101168

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Misc/amdgcn.languageOptsOpenCL.cl
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_allow_unsafe_kernel_parameters: enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif
Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_allow_unsafe_kernel_parameters
+#error "Missing __cl_c

[PATCH] D101168: [C++4OpenCL] Add clang extension for unsafe kernel parameters

2021-04-27 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaDecl.cpp:8651
 static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
+  if (PT->isDependentType())
+return InvalidKernelParam;

Anastasia wrote:
> I would rather add an assert for this because we should not ever reach this 
> function for the dependent types?
The function is actually called on dependent types


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101168/new/

https://reviews.llvm.org/D101168

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D101168: [C++4OpenCL] Add clang extension for unsafe kernel parameters

2021-04-27 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 340796.
olestrohm added a comment.

Improved the description and example per the feedback.

The check for dependent type is needed. If it is not included the diagnostic 
will get triggered when the extension is disabled, but not when it's enabled.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101168/new/

https://reviews.llvm.org/D101168

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Misc/amdgcn.languageOptsOpenCL.cl
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif
Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl
===
--- clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -28,6 +28,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters 

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors and types with address spaces

2021-04-29 Thread Ole Strohm via Phabricator via cfe-commits
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 two issues with reinterpret_cast in C++ for OpenCL and adds tests to 
make sure they both pass without errors, and generate the correct code.

Reinterpret_cast can only convert a type to itself if it is an integral type 
(or pointer or reference or vectors), so I didn't include any exceptions for 
opencl types.
Not even float can be converted to itself, so I don't think it makes sense to 
allow this for any opencl types unlesss you think some of them fit the integral 
restriction.

Fixes: https://bugs.llvm.org/show_bug.cgi?id=47977 and 
https://bugs.llvm.org/show_bug.cgi?id=49221


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+kernel void foo() {
+  long x;
+  auto x2 = reinterpret_cast(x);
+  int2 y;
+  auto y2 = reinterpret_cast(y);
+  auto y3 = reinterpret_cast(y); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+
+  __private int i;
+  auto i2 = reinterpret_cast<__private int>(i);
+  auto i3 = reinterpret_cast(i);
+
+  reserve_id_t z;
+  auto z2 = reinterpret_cast(z); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *vec) {
+  //CHECK: load i32, i32* %x, align 4
+  //CHECK: store i32 %{{[0-9]+}}, i32* %y, align 4
+  int x;
+  auto y = reinterpret_cast<__private int>(x);
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto lv = reinterpret_cast(vec[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto vec0 = reinterpret_cast(lv);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7358,6 +7358,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType srcTy, QualType destTy) {
+  assert(destTy->isVectorType() || srcTy->isVectorType());
+
+  uint64_t srcLen, destLen;
+  QualType srcEltTy, destEltTy;
+  if (!breakDownVectorType(srcTy, srcLen, srcEltTy))
+return false;
+  if (!breakDownVectorType(destTy, destLen, destEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+  uint64_t destEltSize = Context.getTypeSize(destEltTy);
+
+  return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7376,18 +7395,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2328,6 +2328,15 @@
   return TC_Success;
 }
 
+if (Self.Lang

[PATCH] D101168: [C++4OpenCL] Add clang extension for non-portable kernel parameters

2021-04-29 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 341526.
olestrohm set the repository for this revision to rG LLVM Github Monorepo.
olestrohm added a comment.

Added a link to the C++ for OpenCL specification and cleaned up the text 
according to the requests.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101168/new/

https://reviews.llvm.org/D101168

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Misc/amdgcn.languageOptsOpenCL.cl
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif
Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl
===
--- clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -28,6 +28,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_paramete

[PATCH] D101168: [C++4OpenCL] Add clang extension for non-portable kernel parameters

2021-04-30 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 341831.
olestrohm added a comment.

Fixed merge error


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101168/new/

https://reviews.llvm.org/D101168

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Sema/SemaDecl.cpp
  clang/test/Misc/amdgcn.languageOptsOpenCL.cl
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -1,4 +1,9 @@
-// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only -triple spir-unknown-unknown -DUNSAFEKERNELPARAMETER
+
+#ifdef UNSAFEKERNELPARAMETER
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+#endif
 
 struct C {
   kernel void m(); //expected-error{{kernel functions cannot be class members}}
@@ -24,8 +29,10 @@
 kernel void int_p_r(__global int *__global &in);
 kernel void int_p_p_r(__global int *__global *__global &in);
 
-// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
 kernel void k_atomic_v(atomic_int in);
+#ifndef UNSAFEKERNELPARAMETER
+// expected-error@-2{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+#endif
 kernel void k_atomic_p(__global atomic_int *in);
 kernel void k_atomic_r(__global atomic_int &in);
 
@@ -56,7 +63,10 @@
   StandardLayout(int a, int b) : a(a), b(b) {}
 };
 
-kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_v(StandardLayout in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+#endif
 kernel void standard_p(__global StandardLayout *in) {}
 kernel void standard_p_p(__global StandardLayout *__global *in) {}
 kernel void standard_r(__global StandardLayout &in) {}
@@ -67,7 +77,19 @@
   int b;
 };
 
-kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
-kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_v(Trivial in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p(__global Trivial *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_p_p(__global Trivial *__global *in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+#endif
+kernel void trivial_r(__global Trivial &in) {}
+#ifndef UNSAFEKERNELPARAMETER
+//expected-error@-2{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
+#endif
Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -34,6 +34,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl
===
--- clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -28,6 +28,11 @@
 #endif
 #pragma OPENCL EXTENSION __cl_clang_variadic_functions : enable
 
+#ifndef __cl_clang_non_portable_kernel_parameters
+#error "Missing __cl_clang_non_portable_kernel_parameters define"
+#endif
+#pragma OPENCL EXTENSION __cl_clang_non_portable_kernel_parameters : enable
+
 #ifdef cl_khr_fp16
 #error "Incorrect cl_khr_fp16 define"
 #endif
Index: clang/test/Misc/amdgcn.la

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors and types with address spaces

2021-04-30 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 341844.
olestrohm added a comment.

Fixed formatting.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+kernel void foo() {
+  long x;
+  auto x2 = reinterpret_cast(x);
+  int2 y;
+  auto y2 = reinterpret_cast(y);
+  auto y3 = reinterpret_cast(y); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+
+  __private int i;
+  auto i2 = reinterpret_cast<__private int>(i);
+  auto i3 = reinterpret_cast(i);
+
+  reserve_id_t z;
+  auto z2 = reinterpret_cast(z); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,15 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *vec) {
+  //CHECK: load i32, i32* %x, align 4
+  //CHECK: store i32 %{{[0-9]+}}, i32* %y, align 4
+  int x;
+  auto y = reinterpret_cast<__private int>(x);
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto lv = reinterpret_cast(vec[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto vec0 = reinterpret_cast(lv);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7344,6 +7344,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType srcTy, QualType destTy) {
+  assert(destTy->isVectorType() || srcTy->isVectorType());
+
+  uint64_t srcLen, destLen;
+  QualType srcEltTy, destEltTy;
+  if (!breakDownVectorType(srcTy, srcLen, srcEltTy))
+return false;
+  if (!breakDownVectorType(destTy, destLen, destEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+  uint64_t destEltSize = Context.getTypeSize(destEltTy);
+
+  return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7362,18 +7381,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2328,6 +2328,15 @@
   return TC_Success;
 }
 
+if (Self.LangOpts.OpenCL && !CStyle) {
+  if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+  Kind = CK_BitCast;
+  return TC_Success;
+}
+  }
+}
+
 // Otherwise, pick a reasonable diagnostic.
 if (!destIsVector)
   msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
@@ -2339,7 +2348,10 @@
 return TC_Failed;
   }
 
-  if (SrcType == DestType) {
+  if (SrcType == DestType ||
+  (Self.LangOpts.OpenCL &&
+   Self.Context.removeAddrSpaceQualType(SrcType) ==
+   Self.Context.removeAddrSpaceQualType(DestType))) {
 // C++ 5.2.10p2 has a note that mentions that, subject 

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors and types with address spaces

2021-04-30 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp:1
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+

Anastasia wrote:
> Btw I assume your patch also allows reinterpret_cast between vectors? What 
> happens if we cast b/w vector of 3 elements and vector of 4 elements?
Yes, this is essentially the same as line 10, as int is treated as a 1 element 
vector, but I can add some more test cases that shows this more specifically.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors

2021-05-07 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 343647.
olestrohm retitled this revision from "[C++4OpenCL] Fix reinterpret_cast of 
vectors and types with address spaces" to "[C++4OpenCL] Fix reinterpret_cast of 
vectors".
olestrohm set the repository for this revision to rG LLVM Github Monorepo.
olestrohm added a comment.

Removed the address space related changes. This revision now only allows for 
reinterpret_cast between vectors of the same size.

Also added tests for two variables that are definitely both vectors.

This now only fixes: https://bugs.llvm.org/show_bug.cgi?id=47977


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+kernel void foo() {
+  long l1;
+  auto l_to_i2 = reinterpret_cast(l1);
+  int2 i2;
+  auto i2_to_l = reinterpret_cast(i2);
+  auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+
+  int4 i4;
+  auto i4_to_i3 = reinterpret_cast(i4); // expected-error{{reinterpret_cast from vector 'int4' (vector of 4 'int' values) to vector 'int3' (vector of 3 'int' values) of different size}}
+
+  reserve_id_t r_id1;
+  auto r_id2 = reinterpret_cast(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,17 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef long long2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *in) {
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto l = reinterpret_cast(in[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto i2 = reinterpret_cast(l);
+
+  int4 i4;
+  //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
+  auto l2 = reinterpret_cast(i4);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7344,6 +7344,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType srcTy, QualType destTy) {
+  assert(destTy->isVectorType() || srcTy->isVectorType());
+
+  uint64_t srcLen, destLen;
+  QualType srcEltTy, destEltTy;
+  if (!breakDownVectorType(srcTy, srcLen, srcEltTy))
+return false;
+  if (!breakDownVectorType(destTy, destLen, destEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+  uint64_t destEltSize = Context.getTypeSize(destEltTy);
+
+  return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7362,18 +7381,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cp

[PATCH] D101519: [C++4OpenCL] Fix reinterpret_cast of vectors

2021-05-11 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 344408.
olestrohm added a comment.

I tried to add a special case for 3 and 4 element vectors, but that caused 
issues in codgen, so I've left it as a FIXME for now.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D101519/new/

https://reviews.llvm.org/D101519

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaCast.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
  clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp

Index: clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/reinterpret-cast.clcpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int3 __attribute__((ext_vector_type(3)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+kernel void foo() {
+  long l1;
+  auto l_to_i2 = reinterpret_cast(l1);
+  int2 i2;
+  auto i2_to_l = reinterpret_cast(i2);
+  auto i2_to_i = reinterpret_cast(i2); // expected-error{{reinterpret_cast from vector 'int2' (vector of 2 'int' values) to scalar 'int' of different size}}
+
+  reserve_id_t r_id1;
+  auto r_id2 = reinterpret_cast(r_id1); // expected-error{{reinterpret_cast from 'reserve_id_t' to 'reserve_id_t' is not allowed}}
+}
Index: clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
===
--- /dev/null
+++ clang/test/CodeGenOpenCLCXX/reinterpret_cast.clcpp
@@ -0,0 +1,17 @@
+//RUN: %clang_cc1 %s -triple spir -emit-llvm -O0 -o - | FileCheck %s
+
+typedef int int2 __attribute__((ext_vector_type(2)));
+typedef int int4 __attribute__((ext_vector_type(4)));
+typedef long long2 __attribute__((ext_vector_type(2)));
+
+//CHECK-LABEL: define{{.*}} spir_func void @_Z3barPU3AS1Dv2_i
+void bar(global int2 *in) {
+  //CHECK: bitcast <2 x i32> %{{[0-9]+}} to i64
+  auto l = reinterpret_cast(in[0]);
+  //CHECK: bitcast i64 %{{[0-9]+}} to <2 x i32>
+  auto i2 = reinterpret_cast(l);
+
+  int4 i4;
+  //CHECK: bitcast <4 x i32> %{{[0-9]+}} to <2 x i64>
+  auto l2 = reinterpret_cast(i4);
+}
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -7344,6 +7344,25 @@
  matSrcType->getNumColumns() == matDestType->getNumColumns();
 }
 
+bool Sema::areVectorTypesSameSize(QualType srcTy, QualType destTy) {
+  assert(destTy->isVectorType() || srcTy->isVectorType());
+
+  uint64_t srcLen, destLen;
+  QualType srcEltTy, destEltTy;
+  if (!breakDownVectorType(srcTy, srcLen, srcEltTy))
+return false;
+  if (!breakDownVectorType(destTy, destLen, destEltTy))
+return false;
+
+  // ASTContext::getTypeSize will return the size rounded up to a
+  // power of 2, so instead of using that, we need to use the raw
+  // element size multiplied by the element count.
+  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
+  uint64_t destEltSize = Context.getTypeSize(destEltTy);
+
+  return (srcLen * srcEltSize == destLen * destEltSize);
+}
+
 /// Are the two types lax-compatible vector types?  That is, given
 /// that one of them is a vector, do they have equal storage sizes,
 /// where the storage size is the number of elements times the element
@@ -7362,18 +7381,7 @@
   if (srcTy->isScalarType() && destTy->isExtVectorType()) return false;
   if (destTy->isScalarType() && srcTy->isExtVectorType()) return false;
 
-  uint64_t srcLen, destLen;
-  QualType srcEltTy, destEltTy;
-  if (!breakDownVectorType(srcTy, srcLen, srcEltTy)) return false;
-  if (!breakDownVectorType(destTy, destLen, destEltTy)) return false;
-
-  // ASTContext::getTypeSize will return the size rounded up to a
-  // power of 2, so instead of using that, we need to use the raw
-  // element size multiplied by the element count.
-  uint64_t srcEltSize = Context.getTypeSize(srcEltTy);
-  uint64_t destEltSize = Context.getTypeSize(destEltTy);
-
-  return (srcLen * srcEltSize == destLen * destEltSize);
+  return areVectorTypesSameSize(srcTy, destTy);
 }
 
 /// Is this a legal conversion between two types, one of which is
Index: clang/lib/Sema/SemaCast.cpp
===
--- clang/lib/Sema/SemaCast.cpp
+++ clang/lib/Sema/SemaCast.cpp
@@ -2328,6 +2328,16 @@
   return TC_Success;
 }
 
+if (Self.LangOpts.OpenCL && !CStyle) {
+  if (DestType->isExtVectorType() || SrcType->isExtVectorType()) {
+// FIXME: Allow for reinterpret cast between 3 and 4 element vectors
+if (Self.areVectorTypesSameSize(SrcType, DestType)) {
+  Kind = CK_BitCast;
+  return TC_Success;
+}
+  }
+}
+
 // Otherwise, pick a reasonable diagnostic.
 if (!destIsVector)
   msg = diag::err_bad_cxx_cast_vector_to_scalar_different_size;
Index: clang/include/clang/Sema/Sema.h

[PATCH] D102248: [C++4OpenCL] Fix initialization of __constant constructors without arguments

2021-05-11 Thread Ole Strohm via Phabricator via cfe-commits
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()) 
{


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}}
+

[PATCH] D100471: [C++4OpenCL] Add extra diagnostics for kernel argument types

2021-04-14 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, jfb, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

Adds extra error diagnostics when using unsupported types in kernel arguments.

This fixes https://bugs.llvm.org/show_bug.cgi?id=48099


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100471

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp


Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -5,6 +5,7 @@
 };
 
 template 
+//expected-error@+1{{'T' cannot be used as the type of a kernel parameter}}
 kernel void templ(T par) { //expected-error{{kernel functions cannot be used 
in a template declaration, instantiation or specialization}}
 }
 
@@ -15,3 +16,29 @@
 kernel void foo(int); //expected-note{{previous declaration is here}}
 
 kernel void foo(float); //expected-error{{conflicting types for 'foo'}}
+
+struct POD {
+  int a;
+  int b;
+};
+
+kernel void pod_v(POD in) {}
+kernel void pod_p(__global POD*__private in) {}
+
+struct StandardLayout {
+  int a;
+  int b;
+  StandardLayout(int a, int b) : a(a), b(b) {}
+};
+
+kernel void standard_v(StandardLayout in) {} //expected-error{{'__private 
StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_p(__global StandardLayout*__private in) {}
+
+struct Trivial {
+  int a;
+private:
+  int b;
+};
+
+kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' 
cannot be used as the type of a kernel parameter}}
+kernel void trivial_p(__global Trivial*__private in) {} 
//expected-error{{'__global Trivial *__private' cannot be used as the type of a 
kernel parameter}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -8665,6 +8665,14 @@
 
   return PtrPtrKernelParam;
 }
+
+   // C++ for OpenCL v1.0 s2.4:
+   // Moreover the types used in parameters of the kernel functions must 
be:
+   // Standard layout types for pointer parameters. The same applies to
+   // reference if an implementation supports them in kernel parameters.
+if (!PointeeType->isAtomicType() && !PointeeType->isVoidType() && 
!PointeeType->isStandardLayoutType())
+ return InvalidKernelParam;
+
 return PtrKernelParam;
   }
 
@@ -8689,9 +8697,6 @@
   PT->isHalfType())
 return InvalidKernelParam;
 
-  if (PT->isRecordType())
-return RecordKernelParam;
-
   // Look into an array argument to check if it has a forbidden type.
   if (PT->isArrayType()) {
 const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
@@ -8701,6 +8706,16 @@
 return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
   }
 
+  // C++ for OpenCL v1.0 s2.4:
+  // Moreover the types used in parameters of the kernel functions must be:
+  // Trivial and standard-layout types C++17 [basic.types] (plain old data 
types)
+  // for parameters passed by value;
+  if (!PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
+return InvalidKernelParam;
+
+  if (PT->isRecordType())
+return RecordKernelParam;
+
   return ValidKernelParam;
 }
 


Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -5,6 +5,7 @@
 };
 
 template 
+//expected-error@+1{{'T' cannot be used as the type of a kernel parameter}}
 kernel void templ(T par) { //expected-error{{kernel functions cannot be used in a template declaration, instantiation or specialization}}
 }
 
@@ -15,3 +16,29 @@
 kernel void foo(int); //expected-note{{previous declaration is here}}
 
 kernel void foo(float); //expected-error{{conflicting types for 'foo'}}
+
+struct POD {
+  int a;
+  int b;
+};
+
+kernel void pod_v(POD in) {}
+kernel void pod_p(__global POD*__private in) {}
+
+struct StandardLayout {
+  int a;
+  int b;
+  StandardLayout(int a, int b) : a(a), b(b) {}
+};
+
+kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_p(__global StandardLayout*__private in) {}
+
+struct Trivial {
+  int a;
+private:
+  int b;
+};
+
+kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+kernel void trivial_p(__global Trivial*__private in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- c

[PATCH] D100471: [C++4OpenCL] Add extra diagnostics for kernel argument types

2021-04-14 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 337450.
olestrohm added a comment.

Added more exhaustive tests, as well as fixed the diagnostic to allow reference 
types.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100471/new/

https://reviews.llvm.org/D100471

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -5,6 +5,7 @@
 };
 
 template 
+//expected-error@+1{{'T' cannot be used as the type of a kernel parameter}}
 kernel void templ(T par) { //expected-error{{kernel functions cannot be used in a template declaration, instantiation or specialization}}
 }
 
@@ -15,3 +16,51 @@
 kernel void foo(int); //expected-note{{previous declaration is here}}
 
 kernel void foo(float); //expected-error{{conflicting types for 'foo'}}
+
+kernel void int_v(int in);
+kernel void int_p(__global int *in);
+kernel void int_r(__global int &in);
+kernel void int_p_p(__global int *__global *in);
+kernel void int_p_r(__global int *__global &in);
+kernel void int_p_p_r(__global int *__global *__global &in);
+
+// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+kernel void k_atomic_v(atomic_int in);
+kernel void k_atomic_p(__global atomic_int *in);
+kernel void k_atomic_r(__global atomic_int &in);
+
+kernel void k_pipe(read_only pipe int in, write_only pipe int out);
+kernel void k_sampler(sampler_t in);
+kernel void k_void(__global void *in);
+
+struct POD {
+  int a;
+  int b;
+};
+
+kernel void pod_v(POD in) {}
+kernel void pod_p(__global POD *in) {}
+kernel void pod_p_p(__global POD *__global *in) {}
+kernel void pod_r(__global POD &in) {}
+
+struct StandardLayout {
+  int a;
+  int b;
+  StandardLayout(int a, int b) : a(a), b(b) {}
+};
+
+kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_p(__global StandardLayout *in) {}
+kernel void standard_p_p(__global StandardLayout *__global *in) {}
+kernel void standard_r(__global StandardLayout &in) {}
+
+struct Trivial {
+  int a;
+private:
+  int b;
+};
+
+kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -8648,7 +8648,7 @@
 }
 
 static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
-  if (PT->isPointerType()) {
+  if (PT->isPointerType() || PT->isReferenceType()) {
 QualType PointeeType = PT->getPointeeType();
 if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
 PointeeType.getAddressSpace() == LangAS::opencl_private ||
@@ -8665,6 +8665,15 @@
 
   return PtrPtrKernelParam;
 }
+
+// C++ for OpenCL v1.0 s2.4:
+// Moreover the types used in parameters of the kernel functions must be:
+// Standard layout types for pointer parameters. The same applies to
+// reference if an implementation supports them in kernel parameters.
+if (!PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+!PointeeType->isStandardLayoutType())
+  return InvalidKernelParam;
+
 return PtrKernelParam;
   }
 
@@ -8689,9 +8698,6 @@
   PT->isHalfType())
 return InvalidKernelParam;
 
-  if (PT->isRecordType())
-return RecordKernelParam;
-
   // Look into an array argument to check if it has a forbidden type.
   if (PT->isArrayType()) {
 const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
@@ -8701,6 +8707,16 @@
 return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
   }
 
+  // C++ for OpenCL v1.0 s2.4:
+  // Moreover the types used in parameters of the kernel functions must be:
+  // Trivial and standard-layout types C++17 [basic.types] (plain old data
+  // types) for parameters passed by value;
+  if (!PT->isOpenCLSpecificType() && !PT.isPODType(S.Context))
+return InvalidKernelParam;
+
+  if (PT->isRecordType())
+return RecordKernelParam;
+
   return ValidKernelParam;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-com

[PATCH] D100471: [C++4OpenCL] Add extra diagnostics for kernel argument types

2021-04-15 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm added inline comments.



Comment at: clang/lib/Sema/SemaDecl.cpp:8673
+// reference if an implementation supports them in kernel parameters.
+if (!PointeeType->isAtomicType() && !PointeeType->isVoidType() &&
+!PointeeType->isStandardLayoutType())

Anastasia wrote:
> svenvh wrote:
> > I am wondering if this should be made conditional on C++ mode?  Or is there 
> > no possible way that this new `return InvalidKernelParam` can be triggered 
> > from OpenCL C mode?
> I think it shouldn't because C types are POD types which is a superset of 
> standard layout types.
> 
I believe these rules are correct, but just in case they are not, I will make 
it conditional on C++ mode to not accidentally break OpenCL C.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100471/new/

https://reviews.llvm.org/D100471

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D100471: [C++4OpenCL] Add extra diagnostics for kernel argument types

2021-04-16 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 338032.
olestrohm set the repository for this revision to rG LLVM Github Monorepo.
olestrohm added a comment.

Restricted the checks to C++ for OpenCL and added another test for OpenCL 
vector types.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100471/new/

https://reviews.llvm.org/D100471

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCLCXX/invalid-kernel.clcpp

Index: clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
===
--- clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
+++ clang/test/SemaOpenCLCXX/invalid-kernel.clcpp
@@ -5,6 +5,7 @@
 };
 
 template 
+//expected-error@+1{{'T' cannot be used as the type of a kernel parameter}}
 kernel void templ(T par) { //expected-error{{kernel functions cannot be used in a template declaration, instantiation or specialization}}
 }
 
@@ -15,3 +16,58 @@
 kernel void foo(int); //expected-note{{previous declaration is here}}
 
 kernel void foo(float); //expected-error{{conflicting types for 'foo'}}
+
+kernel void int_v(int in);
+kernel void int_p(__global int *in);
+kernel void int_r(__global int &in);
+kernel void int_p_p(__global int *__global *in);
+kernel void int_p_r(__global int *__global &in);
+kernel void int_p_p_r(__global int *__global *__global &in);
+
+// expected-error@+1{{'__private atomic_int' (aka '__private _Atomic(int)') cannot be used as the type of a kernel parameter}}
+kernel void k_atomic_v(atomic_int in);
+kernel void k_atomic_p(__global atomic_int *in);
+kernel void k_atomic_r(__global atomic_int &in);
+
+kernel void k_pipe(read_only pipe int in, write_only pipe int out);
+kernel void k_sampler(sampler_t in);
+kernel void k_void(__global void *in);
+
+typedef int int4 __attribute__((ext_vector_type(4)));
+
+kernel void int4_v(int4 in);
+kernel void int4_p(__global int4 *in);
+kernel void int4_p_p(__global int4 *__global *in);
+kernel void int4_r(__global int4 &in);
+
+struct POD {
+  int a;
+  int b;
+};
+
+kernel void pod_v(POD in) {}
+kernel void pod_p(__global POD *in) {}
+kernel void pod_p_p(__global POD *__global *in) {}
+kernel void pod_r(__global POD &in) {}
+
+struct StandardLayout {
+  int a;
+  int b;
+  StandardLayout(int a, int b) : a(a), b(b) {}
+};
+
+kernel void standard_v(StandardLayout in) {} //expected-error{{'__private StandardLayout' cannot be used as the type of a kernel parameter}}
+kernel void standard_p(__global StandardLayout *in) {}
+kernel void standard_p_p(__global StandardLayout *__global *in) {}
+kernel void standard_r(__global StandardLayout &in) {}
+
+struct Trivial {
+  int a;
+private:
+  int b;
+};
+
+kernel void trivial_v(Trivial in) {} //expected-error{{'__private Trivial' cannot be used as the type of a kernel parameter}}
+kernel void trivial_p(__global Trivial *in) {} //expected-error{{'__global Trivial *__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_p_p(__global Trivial *__global *in) {} //expected-error{{'__global Trivial *__global *__private' cannot be used as the type of a kernel parameter}}
+kernel void trivial_r(__global Trivial &in) {} //expected-error{{'__global Trivial &__private' cannot be used as the type of a kernel parameter}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -8648,7 +8648,7 @@
 }
 
 static OpenCLParamType getOpenCLKernelParameterType(Sema &S, QualType PT) {
-  if (PT->isPointerType()) {
+  if (PT->isPointerType() || PT->isReferenceType()) {
 QualType PointeeType = PT->getPointeeType();
 if (PointeeType.getAddressSpace() == LangAS::opencl_generic ||
 PointeeType.getAddressSpace() == LangAS::opencl_private ||
@@ -8665,6 +8665,15 @@
 
   return PtrPtrKernelParam;
 }
+
+// C++ for OpenCL v1.0 s2.4:
+// Moreover the types used in parameters of the kernel functions must be:
+// Standard layout types for pointer parameters. The same applies to
+// reference if an implementation supports them in kernel parameters.
+if (S.getLangOpts().OpenCLCPlusPlus && !PointeeType->isAtomicType() &&
+!PointeeType->isVoidType() && !PointeeType->isStandardLayoutType())
+  return InvalidKernelParam;
+
 return PtrKernelParam;
   }
 
@@ -8689,9 +8698,6 @@
   PT->isHalfType())
 return InvalidKernelParam;
 
-  if (PT->isRecordType())
-return RecordKernelParam;
-
   // Look into an array argument to check if it has a forbidden type.
   if (PT->isArrayType()) {
 const Type *UnderlyingTy = PT->getPointeeOrArrayElementType();
@@ -8701,6 +8707,17 @@
 return getOpenCLKernelParameterType(S, QualType(UnderlyingTy, 0));
   }
 
+  // C++ for OpenCL v1.0 s2.4:
+  // Moreover the types used in parameters of the kernel functions must be:
+  // Trivial and standard-layout types C++17 [basic.types] (plain old data
+  // types) for par

[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-20 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh.
Herald added subscribers: ldrumm, wenlei, yaxunl.
olestrohm requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

For templates diagnosis must be done after specialization instead of during 
parsing.

I've left the check during parsing as well, because it provides slightly better 
error messages, though some are lost now that NewVD is set as invalid, instead 
of just setting D invalid.

This fixes: https://bugs.llvm.org/show_bug.cgi?id=48887


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D100860

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCL/event_t.cl
  clang/test/SemaOpenCL/sampler_t.cl
  clang/test/SemaOpenCLCXX/template-diagnostics.clcpp

Index: clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template
+T global_variable; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+clk_event_t global_event; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+template
+void templ() {
+  T loc;
+  //expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  //expected-error@-2{{declaring variable of type '__private half' is not allowed}}
+  //expected-error@-3{{non-kernel function variable cannot be declared in local address space}}
+}
+
+void foo() {
+  templ(); //expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ(); //expected-note{{in instantiation of function template specialization 'templ' requested here}}
+  templ<__local event_t>(); //expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}}
+
+  image1d_t img; //expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  half h; //expected-error{{declaring variable of type '__private half' is not allowed}}
+  __local event_t e; //expected-error{{the event_t type can only be used with __private address space qualifier}}
+
+  (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+
+  static __global clk_event_t local_static;
+}
Index: clang/test/SemaOpenCL/sampler_t.cl
===
--- clang/test/SemaOpenCL/sampler_t.cl
+++ clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@
 sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
 
 sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}}
-#ifdef CHECK_SAMPLER_VALUE
-// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
-#endif
 
 const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
 const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
Index: clang/test/SemaOpenCL/event_t.cl
===
--- clang/test/SemaOpenCL/event_t.cl
+++ clang/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
 
-event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}}
+event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}}
 
 constant struct evt_s {
   event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
@@ -10,7 +10,7 @@
 
 void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}}
   event_t e;
-  constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}}
+  constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}}
   foo(e);
   foo(0);
   foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}}
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6724,31 +6724,34 @@
 
   llvm_unreachable("Unknown type of decl!");
 }
+
 /// Returns true if there hasn't been any invalid type d

[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-21 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 339175.
olestrohm added a comment.

Inlined the `thread_local` check and moved `static clk_event_t` into the 
appropriate test.
I did not move the `thread_local` check since NewVD had the wrong value for 
`TSCS`, so D was required.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100860/new/

https://reviews.llvm.org/D100860

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCL/clk_event_t.cl
  clang/test/SemaOpenCL/event_t.cl
  clang/test/SemaOpenCL/sampler_t.cl
  clang/test/SemaOpenCLCXX/template-diagnostics.clcpp

Index: clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template
+T global_variable; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+clk_event_t global_event; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+template
+void templ() {
+  T loc;
+  //expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  //expected-error@-2{{declaring variable of type '__private half' is not allowed}}
+  //expected-error@-3{{non-kernel function variable cannot be declared in local address space}}
+}
+
+void foo() {
+  templ(); //expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ(); //expected-note{{in instantiation of function template specialization 'templ' requested here}}
+  templ<__local event_t>(); //expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}}
+
+  image1d_t img; //expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  half h; //expected-error{{declaring variable of type '__private half' is not allowed}}
+  __local event_t e; //expected-error{{the event_t type can only be used with __private address space qualifier}}
+
+  (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+}
Index: clang/test/SemaOpenCL/sampler_t.cl
===
--- clang/test/SemaOpenCL/sampler_t.cl
+++ clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@
 sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
 
 sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}}
-#ifdef CHECK_SAMPLER_VALUE
-// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
-#endif
 
 const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
 const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
Index: clang/test/SemaOpenCL/event_t.cl
===
--- clang/test/SemaOpenCL/event_t.cl
+++ clang/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
 
-event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}}
+event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}}
 
 constant struct evt_s {
   event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
@@ -10,7 +10,7 @@
 
 void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}}
   event_t e;
-  constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}}
+  constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}}
   foo(e);
   foo(0);
   foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}}
Index: clang/test/SemaOpenCL/clk_event_t.cl
===
--- clang/test/SemaOpenCL/clk_event_t.cl
+++ clang/test/SemaOpenCL/clk_event_t.cl
@@ -12,6 +12,9 @@
   clk_event_t ce2;
   clk_event_t ce3 = CLK_NULL_EVENT;
 
+  // FIXME: Not obvious if this should give an error as if it was in program scope.
+  static clk_event_t ce4;
+
   if (e == ce1) { // expected-error {{invalid operands to binary expression ('__private event_t' and '__private clk_event_t')}}
 return 9;
   }
Index: clang/lib/Sema/SemaDecl.cpp
==

[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-21 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 339197.
olestrohm added a comment.

Ran git-clang-format.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100860/new/

https://reviews.llvm.org/D100860

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCL/clk_event_t.cl
  clang/test/SemaOpenCL/event_t.cl
  clang/test/SemaOpenCL/sampler_t.cl
  clang/test/SemaOpenCLCXX/template-diagnostics.clcpp

Index: clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/template-diagnostics.clcpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template
+T global_variable; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+clk_event_t global_event; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+template
+void templ() {
+  T loc;
+  //expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  //expected-error@-2{{declaring variable of type '__private half' is not allowed}}
+  //expected-error@-3{{non-kernel function variable cannot be declared in local address space}}
+}
+
+void foo() {
+  templ(); //expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ(); //expected-note{{in instantiation of function template specialization 'templ' requested here}}
+  templ<__local event_t>(); //expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}}
+
+  image1d_t img; //expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  half h; //expected-error{{declaring variable of type '__private half' is not allowed}}
+  __local event_t e; //expected-error{{the event_t type can only be used with __private address space qualifier}}
+
+  (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+}
Index: clang/test/SemaOpenCL/sampler_t.cl
===
--- clang/test/SemaOpenCL/sampler_t.cl
+++ clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@
 sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
 
 sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}}
-#ifdef CHECK_SAMPLER_VALUE
-// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
-#endif
 
 const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
 const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
Index: clang/test/SemaOpenCL/event_t.cl
===
--- clang/test/SemaOpenCL/event_t.cl
+++ clang/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
 
-event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}}
+event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}}
 
 constant struct evt_s {
   event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
@@ -10,7 +10,7 @@
 
 void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}}
   event_t e;
-  constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}}
+  constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}}
   foo(e);
   foo(0);
   foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}}
Index: clang/test/SemaOpenCL/clk_event_t.cl
===
--- clang/test/SemaOpenCL/clk_event_t.cl
+++ clang/test/SemaOpenCL/clk_event_t.cl
@@ -12,6 +12,9 @@
   clk_event_t ce2;
   clk_event_t ce3 = CLK_NULL_EVENT;
 
+  // FIXME: Not obvious if this should give an error as if it was in program scope.
+  static clk_event_t ce4;
+
   if (e == ce1) { // expected-error {{invalid operands to binary expression ('__private event_t' and '__private clk_event_t')}}
 return 9;
   }
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6724,17 +6724,20 @@
 
   llvm_unreachable("Unknown type 

[PATCH] D100860: [C++4OpenCL] Add missing OpenCL specific diagnostics in templates

2021-04-21 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm updated this revision to Diff 339251.
olestrohm added a comment.

Renamed test as suggested.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D100860/new/

https://reviews.llvm.org/D100860

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaOpenCL/clk_event_t.cl
  clang/test/SemaOpenCL/event_t.cl
  clang/test/SemaOpenCL/sampler_t.cl
  clang/test/SemaOpenCLCXX/template-opencl-types.clcpp

Index: clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template
+T global_variable; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+clk_event_t global_event; //expected-error{{the '__global clk_event_t' type cannot be used to declare a program scope variable}}
+
+template
+void templ() {
+  T loc;
+  //expected-error@-1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  //expected-error@-2{{declaring variable of type '__private half' is not allowed}}
+  //expected-error@-3{{non-kernel function variable cannot be declared in local address space}}
+}
+
+void foo() {
+  templ(); //expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ(); //expected-note{{in instantiation of function template specialization 'templ' requested here}}
+  templ<__local event_t>(); //expected-note{{in instantiation of function template specialization 'templ<__local event_t>' requested here}}
+
+  image1d_t img; //expected-error{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  half h; //expected-error{{declaring variable of type '__private half' is not allowed}}
+  __local event_t e; //expected-error{{the event_t type can only be used with __private address space qualifier}}
+
+  (void) global_variable; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+}
Index: clang/test/SemaOpenCL/sampler_t.cl
===
--- clang/test/SemaOpenCL/sampler_t.cl
+++ clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@
 sampler_t bad(void); //expected-error{{declaring function return value of type 'sampler_t' is not allowed}}
 
 sampler_t global_nonconst_smp = 0; // expected-error {{global sampler requires a const or constant address space qualifier}}
-#ifdef CHECK_SAMPLER_VALUE
-// expected-warning@-2{{sampler initializer has invalid Filter Mode bits}}
-#endif
 
 const sampler_t glb_smp10 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
 const constant sampler_t glb_smp11 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR;
Index: clang/test/SemaOpenCL/event_t.cl
===
--- clang/test/SemaOpenCL/event_t.cl
+++ clang/test/SemaOpenCL/event_t.cl
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only
 
-event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}} expected-error{{program scope variable must reside in constant address space}}
+event_t glb_evt; // expected-error {{the '__private event_t' type cannot be used to declare a program scope variable}}
 
 constant struct evt_s {
   event_t evt; // expected-error {{the 'event_t' type cannot be used to declare a structure or union field}}
@@ -10,7 +10,7 @@
 
 void kernel ker(event_t argevt) { // expected-error {{'__private event_t' cannot be used as the type of a kernel parameter}}
   event_t e;
-  constant event_t const_evt; // expected-error {{the event_t type can only be used with __private address space qualifier}} expected-error{{variable in constant address space must be initialized}}
+  constant event_t const_evt; // expected-error{{the '__constant event_t' type cannot be used to declare a program scope variable}}
   foo(e);
   foo(0);
   foo(5); // expected-error {{passing 'int' to parameter of incompatible type 'event_t'}}
Index: clang/test/SemaOpenCL/clk_event_t.cl
===
--- clang/test/SemaOpenCL/clk_event_t.cl
+++ clang/test/SemaOpenCL/clk_event_t.cl
@@ -12,6 +12,9 @@
   clk_event_t ce2;
   clk_event_t ce3 = CLK_NULL_EVENT;
 
+  // FIXME: Not obvious if this should give an error as if it was in program scope.
+  static clk_event_t ce4;
+
   if (e == ce1) { // expected-error {{invalid operands to binary expression ('__private event_t' and '__private clk_event_t')}}
 return 9;
   }
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -6724,17 +6724,20 @@
 
   llvm_unreachable("Unkno

[PATCH] D109526: [OpenCL][Docs] Added ref to libclcxx

2021-09-09 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm accepted this revision.
olestrohm added a comment.
This revision is now accepted and ready to land.

Looks good!


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D109526/new/

https://reviews.llvm.org/D109526

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D109609: [C++4OpenCL] Add support for multiple address spaced destructors

2021-09-10 Thread Ole Strohm via Phabricator via cfe-commits
olestrohm created this revision.
olestrohm added reviewers: Anastasia, svenvh, rjmccall.
olestrohm added a project: clang.
Herald added subscribers: ldrumm, yaxunl.
olestrohm requested review of this revision.
Herald added a subscriber: cfe-commits.

This patch aims to add initial support for multiple address spaced destructors.
Currently this parses fine and the destructors are correctly added to the class,
but there is no logic to choose the correct destructor for a variable in a 
specific address space.
Currently it always picks the first destructor defined in the source code, 
regardless of the 
address space of the variable.

This is not aiming to be a complete implementation, as destructors are used in 
a very large
number of locations, and so doing all of it in one patch would be very 
difficult to review and code.

The goals for this patch is thus to add basic support for destructors, and to 
build a framework for
additional work to be done on this front.
Since this feature won't be completed in this patch, I have attempted to ensure 
that no C++
functionality is changed, to ensure that the changes will only affect C++ for 
OpenCL.
This also has the effect that whenever destructors aren't correctly implemented 
it will fallback
to default behaviour, which is exactly the same currently happens.

In summary destructors in C++ for OpenCL are currently unusable for multiple 
destructors. With
this patch the feature will be usable in the most common situation, and every 
bug that currently 
exists that isn't covered by the changes I have made here will continue to be 
bugs. The hope is that
this patch therefore is almost entirely a positive, since while it doesn't fix 
every bug, it will make the
feature actually work, and will create a base to fix the other bugs as they are 
discovered.

This is why it's mostly implemented through default parameters, as that will 
allow this change to
remain as small as it is, while also allowing further fixes to come along later.

The feature is also C++ for OpenCL specific to let the fast path remain when 
not utilizing the
address spaces, as this new implementation will be slower than the bitfields 
that C++ currently
uses, but I hope this can also be optimized in the future if it turns out to be 
very slow.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D109609

Files:
  clang/include/clang/AST/DeclCXX.h
  clang/include/clang/Sema/Sema.h
  clang/lib/AST/DeclCXX.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaLookup.cpp
  clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp

Index: clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/addrspace-destructors.clcpp
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+// CHECK: CXXDestructorDecl {{.*}} used ~ExactDtor 'void () __private noexcept'
+struct ExactDtor {
+ ~ExactDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~OverloadedDtor 'void () __generic'
+// CHECK: CXXDestructorDecl {{.*}} used ~OverloadedDtor 'void () __private noexcept'
+struct OverloadedDtor {
+ ~OverloadedDtor() __generic;
+ ~OverloadedDtor() __private;
+};
+
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~ImplicitDtor 'void () __global'
+// CHECK: CXXDestructorDecl {{.*}} implicit used ~ImplicitDtor 'void () __private noexcept'
+struct ImplicitDtor {
+~ImplicitDtor() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~Templated 'void () __generic noexcept'
+// CHECK: CXXDestructorDecl
+// CHECK-NOT: used
+// CHECK-SAME: ~Templated 'void () __global'
+template 
+struct Templated {
+~Templated() __generic;
+~Templated() __global;
+};
+
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __private noexcept'
+// CHECK: CXXDestructorDecl {{.*}} used ~BothUsed 'void () __global noexcept'
+struct BothUsed {
+~BothUsed() __private;
+~BothUsed() __global;
+};
+
+__global BothUsed g_inheriting;
+
+kernel void k() {
+__private ExactDtor exact;
+__private OverloadedDtor overloaded;
+__private ImplicitDtor implicit;
+__private Templated templated;
+__private BothUsed inheriting;
+}
Index: clang/lib/Sema/SemaLookup.cpp
===
--- clang/lib/Sema/SemaLookup.cpp
+++ clang/lib/Sema/SemaLookup.cpp
@@ -3054,13 +3054,10 @@
   Functions.append(Operators.begin(), Operators.end());
 }
 
-Sema::SpecialMemberOverloadResult Sema::LookupSpecialMember(CXXRecordDecl *RD,
-   CXXSpecialMember SM,
-   bool ConstArg,
-   bool VolatileArg,
-   bool RValueThis,
-

[PATCH] D107553: [C++4OpenCL] Initialize temporaries in the private address space

2021-09-13 Thread Ole Strohm via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8008009fd25b: [OpenCL] Initialize temporaries in the private 
address space (authored by olestrohm).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D107553/new/

https://reviews.llvm.org/D107553

Files:
  clang/include/clang/Sema/Initialization.h
  clang/lib/Sema/SemaExprCXX.cpp
  clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
  clang/test/SemaOpenCLCXX/temporaries.clcpp


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = X();
+
   __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'}}
Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -1453,7 +1453,8 @@
  "List initialization must have initializer list as expression.");
   SourceRange FullRange = SourceRange(TyBeginLoc, RParenOrBraceLoc);
 
-  InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
+  InitializedEntity Entity =
+  InitializedEntity::InitializeTemporary(Context, TInfo);
   InitializationKind Kind =
   Exprs.size()
   ? ListInitialization
@@ -5290,7 +5291,8 @@
 S, Sema::ExpressionEvaluationContext::Unevaluated);
 Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/true);
 Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-InitializedEntity To(InitializedEntity::InitializeTemporary(Args[0]));
+InitializedEntity To(
+InitializedEntity::InitializeTemporary(S.Context, Args[0]));
 InitializationKind InitKind(InitializationKind::CreateDirect(KWLoc, KWLoc,
  RParenLoc));
 InitializationSequence Init(S, To, InitKind, ArgExprs);
Index: clang/include/clang/Sema/Initialization.h
===
--- clang/include/clang/Sema/Initialization.h
+++ clang/include/clang/Sema/Initialization.h
@@ -335,8 +335,15 @@
   }
 
   /// Create the initialization entity for a temporary.
-  static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) {
-return InitializeTemporary(TypeInfo, TypeInfo->getType());
+  static InitializedEntity InitializeTemporary(ASTContext &Context,
+   TypeSourceInfo *TypeInfo) {
+QualType Type = TypeInfo->getType();
+if (Context.getLangOpts().OpenCLCPlusPlus) {
+  assert(!Type.hasAddressSpace() && "Temporary already has address 
space!");
+  Type = Context.getAddrSpaceQualType(Type, LangAS::opencl_private);
+}
+
+return InitializeTemporary(TypeInfo, Type);
   }
 
   /// Create the initialization entity for a temporary.


Index: clang/test/SemaOpenCLCXX/temporaries.clcpp
===
--- /dev/null
+++ clang/test/SemaOpenCLCXX/temporaries.clcpp
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 %s -pedantic -ast-dump | FileCheck %s
+
+struct X {
+  X() __private = default;
+};
+
+// CHECK: VarDecl {{.*}} gx
+// CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+__global X gx = X();
+
+void k() {
+  // CHECK: VarDecl {{.*}} x1
+  // CHECK: CXXTemporaryObjectExpr {{.*}} '__private X'
+  X x1 = X();
+
+  // CHECK: VarDecl {{.*}} x2
+  // CHECK: CXXConstructExpr {{.*}} 'const __private X'
+  const X x2;
+}
Index: clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
===
--- clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
+++ clang/test/SemaOpenCLCXX/addrspace-constructors.clcpp
@@ -32,6 +32,8 @@
   __local X lx;
   __private X x;
 
+  __private X tx = X();
+
   __private Y py;
   __constant Y cy1; // expected-error{{variable in constant address space must be initialized}}
   __constant Y cy2(1); // expected-error{{no matching