Index: include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- include/clang/Basic/DiagnosticCommonKinds.td +++ include/clang/Basic/DiagnosticCommonKinds.td @@ -232,6 +232,10 @@ def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">; def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">; +// OpenCL C++. +def err_openclcxx_not_supported : Error< + "'%0' is not supported in OpenCL C++">; + // OpenMP def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">; Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -1078,6 +1078,8 @@ // OpenCL C++. def err_openclcxx_virtual_function : Error< "virtual functions are not supported in OpenCL C++">; +def err_openclcxx_reserved : Error< + "'%0' is a reserved keyword in OpenCL C++">; // OpenMP support. def warn_pragma_omp_ignored : Warning< Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -8609,7 +8609,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< Index: include/clang/Basic/TokenKinds.def =================================================================== --- include/clang/Basic/TokenKinds.def +++ include/clang/Basic/TokenKinds.def @@ -249,8 +249,10 @@ // 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++. // KEYALTIVEC - This is a keyword in AltiVec // KEYZVECTOR - This is a keyword for the System z vector extensions, // which are heavily based on AltiVec @@ -525,36 +527,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 | KEYOPENCLCXX) +KEYWORD(__write_only , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__read_write , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("read_only", __read_only , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("write_only", __write_only , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("read_write", __read_write , KEYOPENCLC | KEYOPENCLCXX) // 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: 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, @@ -122,8 +122,9 @@ KEYCOROUTINES = 0x100000, KEYMODULES = 0x200000, KEYCXX2A = 0x400000, + KEYOPENCLCXX = 0x800000, KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A, - KEYALL = (0x7fffff & ~KEYNOMS18 & + KEYALL = (0xffffff & ~KEYNOMS18 & ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude. }; @@ -154,7 +155,9 @@ if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled; if (LangOpts.Char8 && (Flags & CHAR8SUPPORT)) 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 Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2596,7 +2596,7 @@ // Set the flag to prevent the implementation from emitting device exception // handling code for those requiring so. Opts.OpenMPHostCXXExceptions = Opts.Exceptions && Opts.CXXExceptions; - if (Opts.OpenMPIsDevice && T.isNVPTX()) { + if ((Opts.OpenMPIsDevice && T.isNVPTX()) || Opts.OpenCLCPlusPlus) { Opts.Exceptions = 0; Opts.CXXExceptions = 0; } Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3750,11 +3750,25 @@ getLangOpts()); break; - // OpenCL qualifiers: + // OpenCL access qualifiers: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: + // OpenCL C++ 1.0 s2.2: access qualifiers are reserved keywords. + if (Actions.getLangOpts().OpenCLCPlusPlus) { + DiagID = diag::err_openclcxx_reserved; + PrevSpec = Tok.getIdentifierInfo()->getNameStart(); + isInvalid = true; + } + ParseOpenCLQualifiers(DS.getAttributes()); + break; + + // OpenCL address space qualifiers: 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; @@ -3765,9 +3779,6 @@ case tok::kw___global: case tok::kw___local: case tok::kw___constant: - case tok::kw___read_only: - case tok::kw___write_only: - case tok::kw___read_write: ParseOpenCLQualifiers(DS.getAttributes()); break; @@ -3805,8 +3816,9 @@ Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); else if (DiagID == diag::err_opencl_unknown_type_specifier) { - Diag(Tok, DiagID) << getLangOpts().getOpenCLVersionTuple().getAsString() - << PrevSpec << isStorageClass; + Diag(Tok, DiagID) << getLangOpts().OpenCLCPlusPlus + << getLangOpts().getOpenCLVersionTuple().getAsString() + << PrevSpec << isStorageClass; } else Diag(Tok, DiagID) << PrevSpec; } Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -267,6 +267,12 @@ AngleBrackets)); case tok::kw_dynamic_cast: { + // OpenCL C++ 1.0 s2.9: dynamic_cast is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) + << "dynamic_cast"); + } + if (!TypeDependent) { Op.CheckDynamicCast(); if (Op.SrcExpr.isInvalid()) Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -6357,6 +6357,20 @@ D.setInvalidType(); } } + + // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not + // supported. 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 = getLangOpts().OpenCLCPlusPlus; + Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(), + diag::err_opencl_unknown_type_specifier) + << IsCXX << getLangOpts().getOpenCLVersionTuple().getAsString() + << DeclSpec::getSpecifierName(TSC) << 1; + D.setInvalidType(); + return nullptr; + } } DeclSpec::SCS SCSpec = D.getDeclSpec().getStorageClassSpec(); Index: lib/Sema/SemaExprCXX.cpp =================================================================== --- lib/Sema/SemaExprCXX.cpp +++ lib/Sema/SemaExprCXX.cpp @@ -480,6 +480,12 @@ ExprResult Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc, bool isType, void *TyOrExpr, SourceLocation RParenLoc) { + // OpenCL C++ 1.0 s2.9: typeid is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + return ExprError(Diag(OpLoc, diag::err_openclcxx_not_supported) + << "typeid"); + } + // Find the std::type_info type. if (!getStdNamespace()) return ExprError(Diag(OpLoc, diag::err_need_header_before_typeid)); Index: test/Parser/opencl-cl20.cl =================================================================== --- test/Parser/opencl-cl20.cl +++ test/Parser/opencl-cl20.cl @@ -10,9 +10,9 @@ 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) { @@ -20,7 +20,7 @@ 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: test/Parser/opencl-cxx-keywords.cl =================================================================== --- test/Parser/opencl-cxx-keywords.cl +++ test/Parser/opencl-cxx-keywords.cl @@ -0,0 +1,50 @@ +// 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 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; + int global; // should be fine in OpenCL C++ + + local int *l; + // expected-error@-1 {{unknown type name 'local'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __local int *uul; + int local; // should be fine in OpenCL C++ + + private int *p; + // expected-error@-1 {{expected ':'}} + __private int *uup; + int private; // 'private' is a keyword in C++14 and thus in OpenCL C++ + // expected-error@-1 {{expected member name or ';' after declaration specifiers}} + + constant int *c; + // expected-error@-1 {{unknown type name 'constant'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __constant int *uuc; + int constant; // should be fine in OpenCL C++ + + generic int *ge; + // expected-error@-1 {{unknown type name 'generic'}} + // expected-error@-2 {{expected member name or ';' after declaration specifiers}} + __generic int *uuge; + int generic; // should be fine in OpenCL C++ +}; 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/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/SemaOpenCLCXX/restricted.cl =================================================================== --- test/SemaOpenCLCXX/restricted.cl +++ test/SemaOpenCLCXX/restricted.cl @@ -0,0 +1,63 @@ +// 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 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 {{'typeid' is not supported in OpenCL C++}} + +// 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(p); + // expected-error@-1 {{'dynamic_cast' is not supported in OpenCL C++}} +} + +// Test storage class qualifiers. +__constant _Thread_local int a = 1; +// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '_Thread_local' storage class specifier}} +__constant __thread int b = 2; +// expected-error@-1 {{OpenCL C++ version 1.0 does not support the '__thread' storage class specifier}} +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}} +} + +// Test that access qualifiers are reserved keywords. +kernel void test_access_qualifiers() { + int read_only; + // expected-error@-1 {{'read_only' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} + int __read_only; + // expected-error@-1 {{'__read_only' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} + int write_only; + // expected-error@-1 {{'write_only' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} + int __write_only; + // expected-error@-1 {{'__write_only' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} + int read_write; + // expected-error@-1 {{'read_write' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} + int __read_write; + // expected-error@-1 {{'__read_write' is a reserved keyword in OpenCL C++}} + // expected-warning@-2 {{declaration does not declare anything}} +}