[clang] 6a92c19 - [C++4OpenCL] Add diagnostics for OpenCL types in templates.

Anastasia Stulova via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 27 05:06:44 PDT 2021


Author: Anastasia Stulova
Date: 2021-04-27T13:04:25+01:00
New Revision: 6a92c19f3bbc47827b8844a2b527f6c6fba63afd

URL: https://github.com/llvm/llvm-project/commit/6a92c19f3bbc47827b8844a2b527f6c6fba63afd
DIFF: https://github.com/llvm/llvm-project/commit/6a92c19f3bbc47827b8844a2b527f6c6fba63afd.diff

LOG: [C++4OpenCL] Add diagnostics for OpenCL types in templates.

Refactored diagnostics for OpenCL types to allow their
reuse for templates.

Patch by olestrohm (Ole Strohm)!

Differential Revision: https://reviews.llvm.org/D100860

Added: 
    clang/test/SemaOpenCLCXX/template-opencl-types.clcpp

Modified: 
    clang/lib/Sema/SemaDecl.cpp
    clang/test/SemaOpenCL/clk_event_t.cl
    clang/test/SemaOpenCL/event_t.cl
    clang/test/SemaOpenCL/sampler_t.cl

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index f57e705604c8..9c5bc19f2215 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6726,17 +6726,20 @@ static bool isDeclExternC(const Decl *D) {
 
   llvm_unreachable("Unknown type of decl!");
 }
+
 /// Returns true if there hasn't been any invalid type diagnosed.
-static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
-                                DeclContext *DC, QualType R) {
+static bool diagnoseOpenCLTypes(Sema &Se, VarDecl *NewVD) {
+  DeclContext *DC = NewVD->getDeclContext();
+  QualType R = NewVD->getType();
+
   // OpenCL v2.0 s6.9.b - Image type can only be used as a function argument.
   // OpenCL v2.0 s6.13.16.1 - Pipe type can only be used as a function
   // argument.
   if (R->isImageType() || R->isPipeType()) {
-    Se.Diag(D.getIdentifierLoc(),
+    Se.Diag(NewVD->getLocation(),
             diag::err_opencl_type_can_only_be_used_as_function_parameter)
         << R;
-    D.setInvalidType();
+    NewVD->setInvalidDecl();
     return false;
   }
 
@@ -6745,12 +6748,12 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
   // OpenCL v2.0 s6.9.q:
   // The clk_event_t and reserve_id_t types cannot be declared in program
   // scope.
-  if (NULL == S->getParent()) {
+  if (NewVD->hasGlobalStorage() && !NewVD->isStaticLocal()) {
     if (R->isReserveIDT() || R->isClkEventT() || R->isEventT()) {
-      Se.Diag(D.getIdentifierLoc(),
+      Se.Diag(NewVD->getLocation(),
               diag::err_invalid_type_for_program_scope_var)
           << R;
-      D.setInvalidType();
+      NewVD->setInvalidDecl();
       return false;
     }
   }
@@ -6763,9 +6766,9 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
            NR->isReferenceType()) {
       if (NR->isFunctionPointerType() || NR->isMemberFunctionPointerType() ||
           NR->isFunctionReferenceType()) {
-        Se.Diag(D.getIdentifierLoc(), diag::err_opencl_function_pointer)
+        Se.Diag(NewVD->getLocation(), diag::err_opencl_function_pointer)
             << NR->isReferenceType();
-        D.setInvalidType();
+        NewVD->setInvalidDecl();
         return false;
       }
       NR = NR->getPointeeType();
@@ -6777,8 +6780,8 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
     // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
     // half array type (unless the cl_khr_fp16 extension is enabled).
     if (Se.Context.getBaseElementType(R)->isHalfType()) {
-      Se.Diag(D.getIdentifierLoc(), diag::err_opencl_half_declaration) << R;
-      D.setInvalidType();
+      Se.Diag(NewVD->getLocation(), diag::err_opencl_half_declaration) << R;
+      NewVD->setInvalidDecl();
       return false;
     }
   }
@@ -6788,34 +6791,20 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
   // address space qualifiers.
   if (R->isEventT()) {
     if (R.getAddressSpace() != LangAS::opencl_private) {
-      Se.Diag(D.getBeginLoc(), diag::err_event_t_addr_space_qual);
-      D.setInvalidType();
+      Se.Diag(NewVD->getBeginLoc(), diag::err_event_t_addr_space_qual);
+      NewVD->setInvalidDecl();
       return false;
     }
   }
 
-  // C++ for OpenCL does not allow the thread_local storage qualifier.
-  // OpenCL C does not support thread_local either, and
-  // also reject all other thread storage class specifiers.
-  DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
-  if (TSC != TSCS_unspecified) {
-    bool IsCXX = Se.getLangOpts().OpenCLCPlusPlus;
-    Se.Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
-            diag::err_opencl_unknown_type_specifier)
-        << IsCXX << Se.getLangOpts().getOpenCLVersionTuple().getAsString()
-        << DeclSpec::getSpecifierName(TSC) << 1;
-    D.setInvalidType();
-    return false;
-  }
-
   if (R->isSamplerT()) {
     // OpenCL v1.2 s6.9.b p4:
     // The sampler type cannot be used with the __local and __global address
     // space qualifiers.
     if (R.getAddressSpace() == LangAS::opencl_local ||
         R.getAddressSpace() == LangAS::opencl_global) {
-      Se.Diag(D.getIdentifierLoc(), diag::err_wrong_sampler_addressspace);
-      D.setInvalidType();
+      Se.Diag(NewVD->getLocation(), diag::err_wrong_sampler_addressspace);
+      NewVD->setInvalidDecl();
     }
 
     // OpenCL v1.2 s6.12.14.1:
@@ -6824,12 +6813,13 @@ static bool diagnoseOpenCLTypes(Scope *S, Sema &Se, Declarator &D,
     if (DC->isTranslationUnit() &&
         !(R.getAddressSpace() == LangAS::opencl_constant ||
           R.isConstQualified())) {
-      Se.Diag(D.getIdentifierLoc(), diag::err_opencl_nonconst_global_sampler);
-      D.setInvalidType();
+      Se.Diag(NewVD->getLocation(), diag::err_opencl_nonconst_global_sampler);
+      NewVD->setInvalidDecl();
     }
-    if (D.isInvalidType())
+    if (NewVD->isInvalidDecl())
       return false;
   }
+
   return true;
 }
 
@@ -7256,10 +7246,17 @@ NamedDecl *Sema::ActOnVariableDeclarator(
   }
 
   if (getLangOpts().OpenCL) {
-
     deduceOpenCLAddressSpace(NewVD);
 
-    diagnoseOpenCLTypes(S, *this, D, DC, NewVD->getType());
+    DeclSpec::TSCS TSC = D.getDeclSpec().getThreadStorageClassSpec();
+    if (TSC != TSCS_unspecified) {
+      bool IsCXX = getLangOpts().OpenCLCPlusPlus;
+      Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+           diag::err_opencl_unknown_type_specifier)
+          << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString()
+          << DeclSpec::getSpecifierName(TSC) << 1;
+      NewVD->setInvalidDecl();
+    }
   }
 
   // Handle attributes prior to checking for duplicates in MergeVarDecl
@@ -7923,6 +7920,9 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
   }
 
   if (getLangOpts().OpenCL) {
+    if (!diagnoseOpenCLTypes(*this, NewVD))
+      return;
+
     // OpenCL v2.0 s6.12.5 - The __block storage type is not supported.
     if (NewVD->hasAttr<BlocksAttr>()) {
       Diag(NewVD->getLocation(), diag::err_opencl_block_storage_type);
@@ -7944,6 +7944,7 @@ void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {
         return;
       }
     }
+
     // OpenCL C v1.2 s6.5 - All program scope variables must be declared in the
     // __constant address space.
     // OpenCL C v2.0 s6.5.1 - Variables defined at program scope and static

diff  --git a/clang/test/SemaOpenCL/clk_event_t.cl b/clang/test/SemaOpenCL/clk_event_t.cl
index 2259359ae3c9..4cc579aa3da2 100644
--- a/clang/test/SemaOpenCL/clk_event_t.cl
+++ b/clang/test/SemaOpenCL/clk_event_t.cl
@@ -12,6 +12,9 @@ int clk_event_tests() {
   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;
   }

diff  --git a/clang/test/SemaOpenCL/event_t.cl b/clang/test/SemaOpenCL/event_t.cl
index 80af4013a6cb..85d57a422adc 100644
--- a/clang/test/SemaOpenCL/event_t.cl
+++ b/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 foo(event_t evt); // expected-note {{passing argument to parameter 'evt' he
 
 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'}}

diff  --git a/clang/test/SemaOpenCL/sampler_t.cl b/clang/test/SemaOpenCL/sampler_t.cl
index a9fcab7faf06..33086343489f 100644
--- a/clang/test/SemaOpenCL/sampler_t.cl
+++ b/clang/test/SemaOpenCL/sampler_t.cl
@@ -48,9 +48,6 @@ constant struct sampler_s {
 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 at -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;

diff  --git a/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp b/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
new file mode 100644
index 000000000000..f217a1e553b7
--- /dev/null
+++ b/clang/test/SemaOpenCLCXX/template-opencl-types.clcpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 %s -pedantic -verify -fsyntax-only
+
+template<typename T>
+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<typename T>
+void templ() {
+  T loc;
+  // expected-error at -1{{type '__private __read_only image1d_t' can only be used as a function parameter in OpenCL}}
+  // expected-error at -2{{declaring variable of type '__private half' is not allowed}}
+  // expected-error at -3{{the event_t type can only be used with __private address space qualifier}}
+}
+
+void foo() {
+  templ<image1d_t>(); // expected-note{{in instantiation of function template specialization 'templ<__read_only image1d_t>' requested here}}
+  templ<half>(); // expected-note{{in instantiation of function template specialization 'templ<half>' 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<clk_event_t>; // expected-note{{in instantiation of variable template specialization 'global_variable' requested here}}
+}


        


More information about the cfe-commits mailing list