[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