[OpenCL] Restrict various keywords in OpenCL C++ mode
authorSven van Haastregt <sven.vanhaastregt@arm.com>
Wed, 9 May 2018 13:16:17 +0000 (13:16 +0000)
committerSven van Haastregt <sven.vanhaastregt@arm.com>
Wed, 9 May 2018 13:16:17 +0000 (13:16 +0000)
Restrict the following keywords in the OpenCL C++ language mode,
according to Sections 2.2 & 2.9 of the OpenCL C++ 1.0 Specification.

 - dynamic_cast
 - typeid
 - register (already restricted in OpenCL C, update the diagnostic)
 - thread_local
 - exceptions (try/catch/throw)
 - access qualifiers read_only, write_only, read_write

Support the `__global`, `__local`, `__constant`, `__private`, and
`__generic` keywords in OpenCL C++.  Leave the unprefixed address
space qualifiers such as global available, i.e., do not mark them as
reserved keywords in OpenCL C++.  libclcxx provides explicit address
space pointer classes such as `global_ptr` and `global<T>` that are
implemented using the `__`-prefixed qualifiers.

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

llvm-svn: 331874

15 files changed:
clang/include/clang/Basic/DiagnosticCommonKinds.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/TokenKinds.def
clang/lib/Basic/IdentifierTable.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/lib/Parse/ParseDecl.cpp
clang/lib/Sema/SemaCast.cpp
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/test/Parser/opencl-cl20.cl
clang/test/Parser/opencl-cxx-keywords.cl [new file with mode: 0644]
clang/test/Parser/opencl-storage-class.cl
clang/test/SemaOpenCL/storageclass.cl
clang/test/SemaOpenCLCXX/restricted.cl [new file with mode: 0644]

index 9c019cb..9dd6876 100644 (file)
@@ -232,6 +232,10 @@ def note_mt_message : Note<"[rewriter] %0">;
 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 d12ac43..ee9ca71 100644 (file)
@@ -1078,6 +1078,8 @@ def err_opencl_logical_exclusive_or : Error<
 // 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 df77ee5..1c89412 100644 (file)
@@ -8609,7 +8609,8 @@ def note_opencl_typedef_access_qualifier : Note<
 
 // 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 6bf945b..cc717f6 100644 (file)
@@ -249,8 +249,10 @@ PUNCTUATOR(caretcaret,            "^^")
 //   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(__unaligned                 , KEYMS)
 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 621bcc2..ec9ca76 100644 (file)
@@ -108,7 +108,7 @@ namespace {
     KEYALTIVEC = 0x40,
     KEYNOCXX = 0x80,
     KEYBORLAND = 0x100,
-    KEYOPENCL = 0x200,
+    KEYOPENCLC = 0x200,
     KEYC11 = 0x400,
     KEYARC = 0x800,
     KEYNOMS18 = 0x01000,
@@ -122,8 +122,9 @@ namespace {
     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 @@ static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
   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 20874fc..71c9464 100644 (file)
@@ -2596,7 +2596,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   // 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 eab07cb..385d0fb 100644 (file)
@@ -3750,11 +3750,25 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
                                  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 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
     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 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
         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 f4d8e8d..32cb307 100644 (file)
@@ -267,6 +267,12 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
                                                 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 6df52d5..377bb10 100644 (file)
@@ -6357,6 +6357,20 @@ NamedDecl *Sema::ActOnVariableDeclarator(
         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 28bda7c..2847069 100644 (file)
@@ -480,6 +480,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType,
 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 b14ad10..be96950 100644 (file)
@@ -10,9 +10,9 @@ __generic int * __generic_test(__generic int *arg) {
   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 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}}
 #endif
 
 generic int * generic_test(generic int *arg) {
@@ -20,7 +20,7 @@ generic int * generic_test(generic int *arg) {
   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 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}}
 #endif
diff --git a/clang/test/Parser/opencl-cxx-keywords.cl b/clang/test/Parser/opencl-cxx-keywords.cl
new file mode 100644 (file)
index 0000000..791da93
--- /dev/null
@@ -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 a8ebc1a..a33c6e8 100644 (file)
@@ -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 cbcb945..f35ab9c 100644 (file)
@@ -10,14 +10,14 @@ static constant float g_constant_static_var = 0;
 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 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 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 @@ void kernel foo(int x) {
     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 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 @@ void f() {
   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 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 version 1.2 does not support the 'generic' type qualifier}} // expected-error {{extern variable must reside in constant address space}}
 }
diff --git a/clang/test/SemaOpenCLCXX/restricted.cl b/clang/test/SemaOpenCLCXX/restricted.cl
new file mode 100644 (file)
index 0000000..c0dfbd6
--- /dev/null
@@ -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<B *>(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}}
+}