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 @@ -1076,6 +1076,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 @@ -8571,7 +8571,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 @@ -521,36 +523,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: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -651,7 +651,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: 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,8 +121,9 @@ KEYCOROUTINES = 0x80000, KEYMODULES = 0x100000, KEYCXX2A = 0x200000, + KEYOPENCLCXX = 0x400000, KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A, - KEYALL = (0x3fffff & ~KEYNOMS18 & + KEYALL = (0x7fffff & ~KEYNOMS18 & ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude. }; @@ -152,7 +153,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 Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -2582,7 +2582,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/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3451,18 +3451,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; @@ -3755,11 +3755,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; @@ -3770,9 +3784,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; @@ -3810,11 +3821,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/Parse/ParseStmtAsm.cpp =================================================================== --- lib/Parse/ParseStmtAsm.cpp +++ lib/Parse/ParseStmtAsm.cpp @@ -690,6 +690,11 @@ assert(Tok.is(tok::kw_asm) && "Not an asm stmt"); SourceLocation AsmLoc = ConsumeToken(); + if (Actions.getLangOpts().OpenCLCPlusPlus) { + Diag(AsmLoc, diag::err_openclcxx_not_supported) << "asm"; + return StmtError(); + } + if (getLangOpts().AsmBlocks && !isGCCAsmStatement(Tok)) { msAsm = true; return ParseMicrosoftAsmStatement(AsmLoc); Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -609,12 +609,20 @@ 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) { + // OpenCL C++ 1.0 s2.9: the thread_local storage qualifier is not + // supported. Also reject all other thread storage class specifiers. + DiagID = diag::err_opencl_unknown_type_specifier; + PrevSpec = getSpecifierName(TSC); + return true; + } + ThreadStorageClassSpec = TSC; ThreadStorageClassSpecLoc = Loc; return false; 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/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: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -2784,6 +2784,12 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { + // OpenCL C++ 1.0 s2.9: goto is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + return StmtError(Diag(GotoLoc, diag::err_openclcxx_not_supported) + << "goto"); + } + setFunctionHasBranchIntoScope(); TheDecl->markUsed(Context); return new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc); @@ -2792,6 +2798,12 @@ StmtResult Sema::ActOnIndirectGotoStmt(SourceLocation GotoLoc, SourceLocation StarLoc, Expr *E) { + // OpenCL C++ 1.0 s2.9: goto is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + return StmtError(Diag(GotoLoc, diag::err_openclcxx_not_supported) + << "goto"); + } + // Convert operand to void* if (!E->isTypeDependent()) { QualType ETy = E->getType(); 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 =================================================================== --- /dev/null +++ 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 =================================================================== --- /dev/null +++ test/SemaOpenCLCXX/restricted.cl @@ -0,0 +1,77 @@ +// 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}} +} + +// Test other keywords that are not available in OpenCL C++. +kernel void test_misc() { + goto label; + // expected-error@-1 {{'goto' is not supported in OpenCL C++}} + goto *&&label; + // expected-error@-1 {{'goto' is not supported in OpenCL C++}} + // expected-warning@-2 {{use of GNU indirect-goto extension}} + // expected-warning@-3 {{use of GNU address-of-label extension}} +label: + asm(""); + // expected-error@-1 {{'asm' is not supported in OpenCL C++}} + // expected-warning@-2 {{expression result unused}} +}