svenvh created this revision. svenvh added reviewers: yaxunl, bader. Herald added subscribers: cfe-commits, Anastasia.
Restrict the following keywords in the OpenCL C++ language mode, according to Section 2.9 of the OpenCL C++ 1.0 Specification. - dynamic_cast - typeid - goto - register (already restricted in OpenCL C, update the diagnostic) - thread_local - asm - exceptions (try/catch/throw) Support the __global, __local, __constant, __private, and __generic keywords in OpenCL C++. OpenCL C++ does not provide the unprefixed address space qualifiers such as global. Instead, libclcxx provides explicit address space pointer classes such as global_ptr and global<T> that are implemented using the __-prefixed qualifiers. This patch is only a first stab at implementing the restrictions of OpenCL C++ and is by no means complete. It primarily covers restrictions that are easily caught before Sema. Repository: rC Clang https://reviews.llvm.org/D46022 Files: include/clang/Basic/DiagnosticSemaKinds.td include/clang/Basic/TokenKinds.def include/clang/Sema/DeclSpec.h lib/Basic/IdentifierTable.cpp lib/Frontend/CompilerInvocation.cpp lib/Parse/ParseDecl.cpp lib/Sema/DeclSpec.cpp test/Parser/opencl-cl20.cl test/Parser/opencl-cxx-keywords.cl test/Parser/opencl-storage-class.cl test/SemaOpenCL/storageclass.cl test/SemaOpenCLCXX/restricted.cl
Index: test/SemaOpenCLCXX/restricted.cl =================================================================== --- /dev/null +++ test/SemaOpenCLCXX/restricted.cl @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only + +// This test checks that various C/C++/OpenCL C constructs are not available in +// OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9. + +// Test storage class qualifiers. +kernel void test_storage_classes() { + register int x; + // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'register' storage class specifier}} + thread_local int y; + // expected-error@-1 {{OpenCL C++ version 1.0 does not support the 'thread_local' storage class specifier}} +} Index: test/SemaOpenCL/storageclass.cl =================================================================== --- test/SemaOpenCL/storageclass.cl +++ test/SemaOpenCL/storageclass.cl @@ -10,14 +10,14 @@ static global float g_global_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} static local float g_local_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} static private float g_private_static_var = 0; // expected-error {{program scope variable must reside in constant address space}} -static generic float g_generic_static_var = 0; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}} +static generic float g_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{program scope variable must reside in constant address space}} extern float g_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} extern constant float g_constant_extern_var; extern global float g_global_extern_var; // expected-error {{extern variable must reside in constant address space}} extern local float g_local_extern_var; // expected-error {{extern variable must reside in constant address space}} extern private float g_private_extern_var; // expected-error {{extern variable must reside in constant address space}} -extern generic float g_generic_extern_var; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} +extern generic float g_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} void kernel foo(int x) { // static is not allowed at local scope before CL2.0 @@ -32,7 +32,7 @@ constant int L1 = 42; // expected-error {{variables in the constant address space can only be declared in the outermost scope of a kernel function}} } - auto int L3 = 7; // expected-error{{OpenCL version 1.2 does not support the 'auto' storage class specifier}} + auto int L3 = 7; // expected-error{{OpenCL C version 1.2 does not support the 'auto' storage class specifier}} global int L4; // expected-error{{function scope variable cannot be declared in global address space}} __attribute__((address_space(100))) int L5; // expected-error{{automatic variable qualified with an invalid address space}} @@ -64,12 +64,12 @@ static global float l_global_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} static local float l_local_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} static private float l_private_static_var = 0; // expected-error {{variables in function scope cannot be declared static}} - static generic float l_generic_static_var = 0; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}} + static generic float l_generic_static_var = 0; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{variables in function scope cannot be declared static}} extern float l_implicit_extern_var; // expected-error {{extern variable must reside in constant address space}} extern constant float l_constant_extern_var; extern global float l_global_extern_var; // expected-error {{extern variable must reside in constant address space}} extern local float l_local_extern_var; // expected-error {{extern variable must reside in constant address space}} extern private float l_private_extern_var; // expected-error {{extern variable must reside in constant address space}} - extern generic float l_generic_extern_var; // expected-error{{OpenCL version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} + extern generic float l_generic_extern_var; // expected-error{{OpenCL C version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}} } Index: test/Parser/opencl-storage-class.cl =================================================================== --- test/Parser/opencl-storage-class.cl +++ test/Parser/opencl-storage-class.cl @@ -2,10 +2,10 @@ void test_storage_class_specs() { - static int a; // expected-error {{OpenCL version 1.0 does not support the 'static' storage class specifier}} - register int b; // expected-error {{OpenCL version 1.0 does not support the 'register' storage class specifier}} - extern int c; // expected-error {{OpenCL version 1.0 does not support the 'extern' storage class specifier}} - auto int d; // expected-error {{OpenCL version 1.0 does not support the 'auto' storage class specifier}} + static int a; // expected-error {{OpenCL C version 1.0 does not support the 'static' storage class specifier}} + register int b; // expected-error {{OpenCL C version 1.0 does not support the 'register' storage class specifier}} + extern int c; // expected-error {{OpenCL C version 1.0 does not support the 'extern' storage class specifier}} + auto int d; // expected-error {{OpenCL C version 1.0 does not support the 'auto' storage class specifier}} #pragma OPENCL EXTENSION cl_clang_storage_class_specifiers : enable static int e; // expected-error {{static local variable must reside in constant address space}} Index: test/Parser/opencl-cxx-keywords.cl =================================================================== --- /dev/null +++ test/Parser/opencl-cxx-keywords.cl @@ -0,0 +1,77 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only -fexceptions -fcxx-exceptions + +// This test checks that various C++ and OpenCL C keywords are not available +// in OpenCL C++, according to OpenCL C++ 1.0 Specification Section 2.9. + +// Test that typeid is not available in OpenCL C++. +namespace std { + // Provide a dummy std::type_info so that we can use typeid. + class type_info { + int a; + }; +} +__constant std::type_info int_ti = typeid(int); +// expected-error@-1 {{expected '(' for function-style cast or type construction}} + +// Test that dynamic_cast is not available in OpenCL C++. +class A { +public: + int a; +}; + +class B : public A { + int b; +}; + +B *test_dynamic_cast(B *p) { + return dynamic_cast<B*>(p); + // expected-error@-1 {{use of undeclared identifier 'dynamic_cast'}} + // expected-error@-2 {{'B' does not refer to a value}} + // expected-error@-3 {{expected expression}} + // expected-note@-9 {{declared here}} +} + +// Test that exceptions are disabled despite passing -fcxx-exceptions. +kernel void test_exceptions() { + int x; + try { + // expected-error@-1 {{cannot use 'try' with exceptions disabled}} + throw 0; + // expected-error@-1 {{cannot use 'throw' with exceptions disabled}} + } catch (int i) { + x = 41; + } +} + +// Test that only __-prefixed address space qualifiers are accepted. +struct test_address_space_qualifiers { + global int *g; + // expected-error@-1 {{unknown type name 'global'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __global int *uug; + local int *l; + // expected-error@-1 {{unknown type name 'local'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __local int *uul; + private int *p; + // expected-error@-1 {{expected ':'}} + __private int *uup; + constant int *c; + // expected-error@-1 {{unknown type name 'constant'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __constant int *uuc; + generic int *ge; + // expected-error@-1 {{unknown type name 'generic'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __generic int *uuge; +}; + +// Test other keywords that are not available in OpenCL C++. +kernel void test_misc() { + goto label; + // expected-error@-1 {{unknown type name 'goto'}} +label: + asm(""); + // expected-error@-1 {{use of undeclared identifier 'asm'}} +} Index: test/Parser/opencl-cl20.cl =================================================================== --- test/Parser/opencl-cl20.cl +++ test/Parser/opencl-cl20.cl @@ -10,17 +10,17 @@ return var; } #ifndef CL20 -// expected-error@-5 {{OpenCL version 1.0 does not support the '__generic' type qualifier}} -// expected-error@-6 {{OpenCL version 1.0 does not support the '__generic' type qualifier}} -// expected-error@-6 {{OpenCL version 1.0 does not support the '__generic' type qualifier}} +// expected-error@-5 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}} +// expected-error@-6 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}} +// expected-error@-6 {{OpenCL C version 1.0 does not support the '__generic' type qualifier}} #endif generic int * generic_test(generic int *arg) { generic int *var; return var; } #ifndef CL20 -// expected-error@-5 {{OpenCL version 1.0 does not support the 'generic' type qualifier}} -// expected-error@-6 {{OpenCL version 1.0 does not support the 'generic' type qualifier}} -// expected-error@-6 {{OpenCL version 1.0 does not support the 'generic' type qualifier}} +// expected-error@-5 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}} +// expected-error@-6 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}} +// expected-error@-6 {{OpenCL C version 1.0 does not support the 'generic' type qualifier}} #endif Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -609,12 +609,25 @@ return false; } -bool DeclSpec::SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, +bool DeclSpec::SetStorageClassSpecThread(Sema &S, TSCS TSC, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { if (ThreadStorageClassSpec != TSCS_unspecified) return BadSpecifier(TSC, (TSCS)ThreadStorageClassSpec, PrevSpec, DiagID); + if (S.getLangOpts().OpenCLCPlusPlus) { + switch (TSC) { + // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not + // supported. + case TSCS_thread_local: + DiagID = diag::err_opencl_unknown_type_specifier; + PrevSpec = getSpecifierName(TSC); + return true; + default: + break; + } + } + ThreadStorageClassSpec = TSC; ThreadStorageClassSpecLoc = Loc; return false; Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3447,18 +3447,18 @@ isStorageClass = true; break; case tok::kw___thread: - isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS___thread, Loc, - PrevSpec, DiagID); + isInvalid = DS.SetStorageClassSpecThread(Actions, DeclSpec::TSCS___thread, + Loc, PrevSpec, DiagID); isStorageClass = true; break; case tok::kw_thread_local: - isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc, - PrevSpec, DiagID); + isInvalid = DS.SetStorageClassSpecThread( + Actions, DeclSpec::TSCS_thread_local, Loc, PrevSpec, DiagID); isStorageClass = true; break; case tok::kw__Thread_local: - isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, - Loc, PrevSpec, DiagID); + isInvalid = DS.SetStorageClassSpecThread( + Actions, DeclSpec::TSCS__Thread_local, Loc, PrevSpec, DiagID); isStorageClass = true; break; @@ -3751,7 +3751,8 @@ case tok::kw___generic: // generic address space is introduced only in OpenCL v2.0 // see OpenCL C Spec v2.0 s6.5.5 - if (Actions.getLangOpts().OpenCLVersion < 200) { + if (Actions.getLangOpts().OpenCLVersion < 200 && + !Actions.getLangOpts().OpenCLCPlusPlus) { DiagID = diag::err_opencl_unknown_type_specifier; PrevSpec = Tok.getIdentifierInfo()->getNameStart(); isInvalid = true; @@ -3802,11 +3803,13 @@ Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); else if (DiagID == diag::err_opencl_unknown_type_specifier) { - const int OpenCLVer = getLangOpts().OpenCLVersion; + bool IsCXX = getLangOpts().OpenCLCPlusPlus; + const int OpenCLVer = IsCXX ? getLangOpts().OpenCLCPlusPlusVersion + : getLangOpts().OpenCLVersion; std::string VerSpec = llvm::to_string(OpenCLVer / 100) + std::string (".") + llvm::to_string((OpenCLVer % 100) / 10); - Diag(Tok, DiagID) << VerSpec << PrevSpec << isStorageClass; + Diag(Tok, DiagID) << IsCXX << VerSpec << PrevSpec << isStorageClass; } else Diag(Tok, DiagID) << PrevSpec; } Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2571,7 +2571,7 @@ // Set the flag to prevent the implementation from emitting device exception // handling code for those requiring so. - if (Opts.OpenMPIsDevice && T.isNVPTX()) { + if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) { Opts.Exceptions = 0; Opts.CXXExceptions = 0; } Index: lib/Basic/IdentifierTable.cpp =================================================================== --- lib/Basic/IdentifierTable.cpp +++ lib/Basic/IdentifierTable.cpp @@ -108,7 +108,7 @@ KEYALTIVEC = 0x40, KEYNOCXX = 0x80, KEYBORLAND = 0x100, - KEYOPENCL = 0x200, + KEYOPENCLC = 0x200, KEYC11 = 0x400, KEYARC = 0x800, KEYNOMS18 = 0x01000, @@ -121,9 +121,11 @@ KEYCOROUTINES = 0x80000, KEYMODULES = 0x100000, KEYCXX2A = 0x200000, + KEYOPENCLCXX = 0x400000, + KEYNOOPENCLCXX = 0x800000, KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A, - KEYALL = (0x3fffff & ~KEYNOMS18 & - ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude. + KEYALL = (0xffffff & ~KEYNOMS18 & + ~KEYNOOPENCL & ~KEYNOOPENCLCXX) // KEYNO* are used to exclude. }; /// \brief How a keyword is treated in the selected standard. @@ -152,7 +154,9 @@ if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled; if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled; if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled; - if (LangOpts.OpenCL && (Flags & KEYOPENCL)) return KS_Enabled; + if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLC)) + return KS_Enabled; + if (LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLCXX)) return KS_Enabled; if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled; if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled; // We treat bridge casts as objective-C keywords so we can warn on them @@ -183,6 +187,10 @@ if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return; + // Don't add this keyword under OpenCL C++. + if (LangOpts.OpenCLCPlusPlus && (Flags & KEYNOOPENCLCXX)) + return; + // Don't add this keyword if disabled in this language. if (AddResult == KS_Disabled) return; Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -620,7 +620,7 @@ bool SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy); - bool SetStorageClassSpecThread(TSCS TSC, SourceLocation Loc, + bool SetStorageClassSpecThread(Sema &S, TSCS TSC, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy); Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -249,8 +249,11 @@ // KEYMS - This is a keyword if Microsoft extensions are enabled // KEYNOMS18 - This is a keyword that must never be enabled under // MSVC <= v18. -// KEYOPENCL - This is a keyword in OpenCL -// KEYNOOPENCL - This is a keyword that is not supported in OpenCL +// KEYOPENCLC - This is a keyword in OpenCL C +// KEYOPENCLCXX - This is a keyword in OpenCL C++ +// KEYNOOPENCL - This is a keyword that is not supported in OpenCL C +// nor in OpenCL C++. +// KEYNOOPENCLCXX - This is a keyword that is not supported in OpenCL C++. // KEYALTIVEC - This is a keyword in AltiVec // KEYZVECTOR - This is a keyword for the System z vector extensions, // which are heavily based on AltiVec @@ -275,7 +278,7 @@ KEYWORD(extern , KEYALL) KEYWORD(float , KEYALL) KEYWORD(for , KEYALL) -KEYWORD(goto , KEYALL) +KEYWORD(goto , KEYALL | KEYNOOPENCLCXX) KEYWORD(if , KEYALL) KEYWORD(inline , KEYC99|KEYCXX|KEYGNU) KEYWORD(int , KEYALL) @@ -311,13 +314,13 @@ // C++ 2.11p1: Keywords. -KEYWORD(asm , KEYCXX|KEYGNU) +KEYWORD(asm , KEYCXX | KEYGNU | KEYNOOPENCLCXX) KEYWORD(bool , BOOLSUPPORT) KEYWORD(catch , KEYCXX) KEYWORD(class , KEYCXX) KEYWORD(const_cast , KEYCXX) KEYWORD(delete , KEYCXX) -KEYWORD(dynamic_cast , KEYCXX) +KEYWORD(dynamic_cast , KEYCXX | KEYNOOPENCL) KEYWORD(explicit , KEYCXX) KEYWORD(export , KEYCXX) KEYWORD(false , BOOLSUPPORT) @@ -337,7 +340,7 @@ KEYWORD(true , BOOLSUPPORT) KEYWORD(try , KEYCXX) KEYWORD(typename , KEYCXX) -KEYWORD(typeid , KEYCXX) +KEYWORD(typeid , KEYCXX | KEYNOOPENCL) KEYWORD(using , KEYCXX) KEYWORD(virtual , KEYCXX) KEYWORD(wchar_t , WCHARSUPPORT) @@ -521,36 +524,36 @@ KEYWORD(__super , KEYMS) // OpenCL address space qualifiers -KEYWORD(__global , KEYOPENCL) -KEYWORD(__local , KEYOPENCL) -KEYWORD(__constant , KEYOPENCL) -KEYWORD(__private , KEYOPENCL) -KEYWORD(__generic , KEYOPENCL) -ALIAS("global", __global , KEYOPENCL) -ALIAS("local", __local , KEYOPENCL) -ALIAS("constant", __constant , KEYOPENCL) -ALIAS("private", __private , KEYOPENCL) -ALIAS("generic", __generic , KEYOPENCL) +KEYWORD(__global , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__local , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__constant , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__private , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__generic , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("global", __global , KEYOPENCLC) +ALIAS("local", __local , KEYOPENCLC) +ALIAS("constant", __constant , KEYOPENCLC) +ALIAS("private", __private , KEYOPENCLC) +ALIAS("generic", __generic , KEYOPENCLC) // OpenCL function qualifiers -KEYWORD(__kernel , KEYOPENCL) -ALIAS("kernel", __kernel , KEYOPENCL) +KEYWORD(__kernel , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("kernel", __kernel , KEYOPENCLC | KEYOPENCLCXX) // OpenCL access qualifiers -KEYWORD(__read_only , KEYOPENCL) -KEYWORD(__write_only , KEYOPENCL) -KEYWORD(__read_write , KEYOPENCL) -ALIAS("read_only", __read_only , KEYOPENCL) -ALIAS("write_only", __write_only , KEYOPENCL) -ALIAS("read_write", __read_write , KEYOPENCL) +KEYWORD(__read_only , KEYOPENCLC) +KEYWORD(__write_only , KEYOPENCLC) +KEYWORD(__read_write , KEYOPENCLC) +ALIAS("read_only", __read_only , KEYOPENCLC) +ALIAS("write_only", __write_only , KEYOPENCLC) +ALIAS("read_write", __read_write , KEYOPENCLC) // OpenCL builtins -KEYWORD(__builtin_astype , KEYOPENCL) -KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR) -#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCL) +KEYWORD(__builtin_astype , KEYOPENCLC) +KEYWORD(vec_step , KEYOPENCLC | KEYALTIVEC | KEYZVECTOR) +#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCLC) #include "clang/Basic/OpenCLImageTypes.def" // OpenMP Type Traits KEYWORD(__builtin_omp_required_simd_align, KEYALL) -KEYWORD(pipe , KEYOPENCL) +KEYWORD(pipe , KEYOPENCLC) // Borland Extensions. KEYWORD(__pascal , KEYALL) Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -8588,7 +8588,8 @@ // OpenCL Section 6.8.g def err_opencl_unknown_type_specifier : Error< - "OpenCL version %0 does not support the '%1' %select{type qualifier|storage class specifier}2">; + "OpenCL %select{C|C++}0 version %1 does not support the '%2' " + "%select{type qualifier|storage class specifier}3">; // OpenCL v2.0 s6.12.5 Blocks restrictions def err_opencl_block_storage_type : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits