azabaznov updated this revision to Diff 316627.
azabaznov added a comment.

Changes in the latest patch:

1. Removed XFAIL and OpenCL C 2.0 test running for r600 and NVPTX target

2. Fixed comments.

3. Core features are being set in `TargetInfo::adjust`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D92277/new/

https://reviews.llvm.org/D92277

Files:
  clang/include/clang/Basic/OpenCLExtensions.def
  clang/include/clang/Basic/OpenCLOptions.h
  clang/include/clang/Basic/TargetInfo.h
  clang/include/clang/Basic/TargetOptions.h
  clang/lib/Basic/CMakeLists.txt
  clang/lib/Basic/OpenCLOptions.cpp
  clang/lib/Basic/TargetInfo.cpp
  clang/lib/Basic/Targets.cpp
  clang/lib/Basic/Targets/AMDGPU.h
  clang/lib/Basic/Targets/NVPTX.h
  clang/lib/Basic/Targets/SPIR.h
  clang/lib/Basic/Targets/X86.h
  clang/lib/Frontend/InitPreprocessor.cpp
  clang/lib/Parse/ParsePragma.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  clang/test/Misc/nvptx.languageOptsOpenCL.cl
  clang/test/Misc/r600.languageOptsOpenCL.cl

Index: clang/test/Misc/r600.languageOptsOpenCL.cl
===================================================================
--- clang/test/Misc/r600.languageOptsOpenCL.cl
+++ clang/test/Misc/r600.languageOptsOpenCL.cl
@@ -2,27 +2,21 @@
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu cayman
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cayman
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu cypress
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu cypress
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -target-cpu turks
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -target-cpu turks
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -target-cpu turks
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -target-cpu turks
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple r600-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -target-cpu turks
 
 // Extensions in all versions
 #ifndef cl_clang_storage_class_specifiers
Index: clang/test/Misc/nvptx.languageOptsOpenCL.cl
===================================================================
--- clang/test/Misc/nvptx.languageOptsOpenCL.cl
+++ clang/test/Misc/nvptx.languageOptsOpenCL.cl
@@ -2,19 +2,15 @@
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx-unknown-unknown
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx64-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx64-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx64-unknown-unknown
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx64-unknown-unknown
 // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
-// RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple nvptx64-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES
 
 // Extensions in all versions
 #ifndef cl_clang_storage_class_specifiers
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -3978,6 +3978,7 @@
     Record.push_back(V.Enabled ? 1 : 0);
     Record.push_back(V.Avail);
     Record.push_back(V.Core);
+    Record.push_back(V.Opt);
   }
   Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
 }
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -3583,11 +3583,12 @@
     case OPENCL_EXTENSIONS:
       for (unsigned I = 0, E = Record.size(); I != E; ) {
         auto Name = ReadString(Record, I);
-        auto &Opt = OpenCLExtensions.OptMap[Name];
-        Opt.Supported = Record[I++] != 0;
-        Opt.Enabled = Record[I++] != 0;
-        Opt.Avail = Record[I++];
-        Opt.Core = Record[I++];
+        auto &OptInfo = OpenCLExtensions.OptMap[Name];
+        OptInfo.Supported = Record[I++] != 0;
+        OptInfo.Enabled = Record[I++] != 0;
+        OptInfo.Avail = Record[I++];
+        OptInfo.Core = Record[I++];
+        OptInfo.Opt = Record[I++];
       }
       break;
 
@@ -7836,7 +7837,7 @@
         NewOverrides.applyOverrides(SemaObj->getLangOpts());
   }
 
-  SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
+  SemaObj->OpenCLFeatures = OpenCLExtensions;
   SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap;
   SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;
 
Index: clang/lib/Sema/Sema.cpp
===================================================================
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -296,7 +296,7 @@
   // core features.
   if (getLangOpts().OpenCL) {
     getOpenCLOptions().addSupport(
-        Context.getTargetInfo().getSupportedOpenCLOpts());
+        Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
     getOpenCLOptions().enableSupportedCore(getLangOpts());
     addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
     addImplicitTypedef("event_t", Context.OCLEventTy);
Index: clang/lib/Parse/ParsePragma.cpp
===================================================================
--- clang/lib/Parse/ParsePragma.cpp
+++ clang/lib/Parse/ParsePragma.cpp
@@ -790,7 +790,7 @@
     PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
   else if (Opt.isSupportedExtension(Name, getLangOpts()))
     Opt.enable(Name, State == Enable);
-  else if (Opt.isSupportedCore(Name, getLangOpts()))
+  else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
     PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
   else
     PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Index: clang/lib/Frontend/InitPreprocessor.cpp
===================================================================
--- clang/lib/Frontend/InitPreprocessor.cpp
+++ clang/lib/Frontend/InitPreprocessor.cpp
@@ -1120,10 +1120,7 @@
 
   // OpenCL definitions.
   if (LangOpts.OpenCL) {
-#define OPENCLEXT(Ext)                                                         \
-  if (TI.getSupportedOpenCLOpts().isSupported(#Ext, LangOpts))                 \
-    Builder.defineMacro(#Ext);
-#include "clang/Basic/OpenCLExtensions.def"
+    TI.getOpenCLFeatureDefines(LangOpts, Builder);
 
     if (TI.getTriple().isSPIR())
       Builder.defineMacro("__IMAGE_SUPPORT__");
Index: clang/lib/Basic/Targets/X86.h
===================================================================
--- clang/lib/Basic/Targets/X86.h
+++ clang/lib/Basic/Targets/X86.h
@@ -359,9 +359,7 @@
 
   bool hasSjLjLowering() const override { return true; }
 
-  void setSupportedOpenCLOpts() override {
-    getSupportedOpenCLOpts().supportAll();
-  }
+  void setSupportedOpenCLOpts() override { supportAllOpenCLOpts(); }
 
   uint64_t getPointerWidthV(unsigned AddrSpace) const override {
     if (AddrSpace == ptr32_sptr || AddrSpace == ptr32_uptr)
Index: clang/lib/Basic/Targets/SPIR.h
===================================================================
--- clang/lib/Basic/Targets/SPIR.h
+++ clang/lib/Basic/Targets/SPIR.h
@@ -100,7 +100,7 @@
   void setSupportedOpenCLOpts() override {
     // Assume all OpenCL extensions and optional core features are supported
     // for SPIR since it is a generic target.
-    getSupportedOpenCLOpts().supportAll();
+    supportAllOpenCLOpts();
   }
 
   bool hasExtIntType() const override { return true; }
Index: clang/lib/Basic/Targets/NVPTX.h
===================================================================
--- clang/lib/Basic/Targets/NVPTX.h
+++ clang/lib/Basic/Targets/NVPTX.h
@@ -127,16 +127,16 @@
 
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.support("cl_clang_storage_class_specifiers");
-    Opts.support("__cl_clang_function_pointers");
-    Opts.support("__cl_clang_variadic_functions");
-
-    Opts.support("cl_khr_fp64");
-    Opts.support("cl_khr_byte_addressable_store");
-    Opts.support("cl_khr_global_int32_base_atomics");
-    Opts.support("cl_khr_global_int32_extended_atomics");
-    Opts.support("cl_khr_local_int32_base_atomics");
-    Opts.support("cl_khr_local_int32_extended_atomics");
+    Opts["cl_clang_storage_class_specifiers"] = true;
+    Opts["__cl_clang_function_pointers"] = true;
+    Opts["__cl_clang_variadic_functions"] = true;
+
+    Opts["cl_khr_fp64"] = true;
+    Opts["cl_khr_byte_addressable_store"] = true;
+    Opts["cl_khr_global_int32_base_atomics"] = true;
+    Opts["cl_khr_global_int32_extended_atomics"] = true;
+    Opts["cl_khr_local_int32_base_atomics"] = true;
+    Opts["cl_khr_local_int32_extended_atomics"] = true;
   }
 
   /// \returns If a target requires an address within a target specific address
Index: clang/lib/Basic/Targets/AMDGPU.h
===================================================================
--- clang/lib/Basic/Targets/AMDGPU.h
+++ clang/lib/Basic/Targets/AMDGPU.h
@@ -284,33 +284,32 @@
 
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.support("cl_clang_storage_class_specifiers");
-    Opts.support("__cl_clang_function_pointers");
-    Opts.support("__cl_clang_variadic_functions");
+    Opts["cl_clang_storage_class_specifiers"] = true;
+    Opts["__cl_clang_variadic_functions"] = true;
+    Opts["__cl_clang_function_pointers"] = true;
 
     bool IsAMDGCN = isAMDGCN(getTriple());
 
-    if (hasFP64())
-      Opts.support("cl_khr_fp64");
+    Opts["cl_khr_fp64"] = hasFP64();
 
     if (IsAMDGCN || GPUKind >= llvm::AMDGPU::GK_CEDAR) {
-      Opts.support("cl_khr_byte_addressable_store");
-      Opts.support("cl_khr_global_int32_base_atomics");
-      Opts.support("cl_khr_global_int32_extended_atomics");
-      Opts.support("cl_khr_local_int32_base_atomics");
-      Opts.support("cl_khr_local_int32_extended_atomics");
+      Opts["cl_khr_byte_addressable_store"] = true;
+      Opts["cl_khr_global_int32_base_atomics"] = true;
+      Opts["cl_khr_global_int32_extended_atomics"] = true;
+      Opts["cl_khr_local_int32_base_atomics"] = true;
+      Opts["cl_khr_local_int32_extended_atomics"] = true;
     }
 
     if (IsAMDGCN) {
-      Opts.support("cl_khr_fp16");
-      Opts.support("cl_khr_int64_base_atomics");
-      Opts.support("cl_khr_int64_extended_atomics");
-      Opts.support("cl_khr_mipmap_image");
-      Opts.support("cl_khr_mipmap_image_writes");
-      Opts.support("cl_khr_subgroups");
-      Opts.support("cl_khr_3d_image_writes");
-      Opts.support("cl_amd_media_ops");
-      Opts.support("cl_amd_media_ops2");
+      Opts["cl_khr_fp16"] = true;
+      Opts["cl_khr_int64_base_atomics"] = true;
+      Opts["cl_khr_int64_extended_atomics"] = true;
+      Opts["cl_khr_mipmap_image"] = true;
+      Opts["cl_khr_mipmap_image_writes"] = true;
+      Opts["cl_khr_subgroups"] = true;
+      Opts["cl_khr_3d_image_writes"] = true;
+      Opts["cl_amd_media_ops"] = true;
+      Opts["cl_amd_media_ops2"] = true;
     }
   }
 
Index: clang/lib/Basic/Targets.cpp
===================================================================
--- clang/lib/Basic/Targets.cpp
+++ clang/lib/Basic/Targets.cpp
@@ -705,7 +705,7 @@
     return nullptr;
 
   Target->setSupportedOpenCLOpts();
-  Target->setOpenCLExtensionOpts();
+  Target->setCommandLineOpenCLOpts();
   Target->setMaxAtomicWidth();
 
   if (!Target->validateTarget(Diags))
@@ -715,3 +715,24 @@
 
   return Target.release();
 }
+
+/// getOpenCLFeatureDefines - Define OpenCL macros based on target settings
+/// and language version
+void TargetInfo::getOpenCLFeatureDefines(const LangOptions &Opts,
+                                         MacroBuilder &Builder) const {
+
+  auto defineOpenCLExtMacro = [&](llvm::StringRef Name, unsigned AvailVer,
+                                  unsigned CoreVersions,
+                                  unsigned OptionalVersions) {
+    // Check if extension is supported by target or is a core feature
+    auto It = getTargetOpts().OpenCLFeaturesMap.find(Name);
+    if ((It != getTargetOpts().OpenCLFeaturesMap.end()) && It->getValue() &&
+        OpenCLOptionInfo(AvailVer, CoreVersions, OptionalVersions)
+            .isAvailableIn(Opts))
+      Builder.defineMacro(Name);
+  };
+
+#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt)                        \
+  defineOpenCLExtMacro(#Ext, Avail, Core, Opt);
+#include "clang/Basic/OpenCLExtensions.def"
+}
Index: clang/lib/Basic/TargetInfo.cpp
===================================================================
--- clang/lib/Basic/TargetInfo.cpp
+++ clang/lib/Basic/TargetInfo.cpp
@@ -356,6 +356,10 @@
   }
 
   if (Opts.OpenCL) {
+    // Set core features based on OpenCL version
+    for (auto CoreExt : clang::getCoreFeatures(Opts))
+      getTargetOpts().OpenCLFeaturesMap[CoreExt] = true;
+
     // OpenCL C requires specific widths for types, irrespective of
     // what these normally are for the target.
     // We also define long long and long double here, although the
Index: clang/lib/Basic/OpenCLOptions.cpp
===================================================================
--- /dev/null
+++ clang/lib/Basic/OpenCLOptions.cpp
@@ -0,0 +1,110 @@
+//===--- OpenCLOptions.cpp---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/OpenCLOptions.h"
+
+namespace clang {
+
+bool OpenCLOptions::isKnown(llvm::StringRef Ext) const {
+  return OptMap.find(Ext) != OptMap.end();
+}
+
+bool OpenCLOptions::isEnabled(llvm::StringRef Ext) const {
+  auto E = OptMap.find(Ext);
+  return E != OptMap.end() && E->second.Enabled;
+}
+
+bool OpenCLOptions::isSupported(llvm::StringRef Ext,
+                                const LangOptions &LO) const {
+  auto E = OptMap.find(Ext);
+  if (E == OptMap.end()) {
+    return false;
+  }
+  auto I = OptMap.find(Ext)->getValue();
+  return I.Supported && I.isAvailableIn(LO);
+}
+
+bool OpenCLOptions::isSupportedCore(llvm::StringRef Ext,
+                                    const LangOptions &LO) const {
+  auto E = OptMap.find(Ext);
+  if (E == OptMap.end()) {
+    return false;
+  }
+  auto I = OptMap.find(Ext)->getValue();
+  return I.Supported && I.isCoreIn(LO);
+}
+
+bool OpenCLOptions::isSupportedOptionalCore(llvm::StringRef Ext,
+                                            const LangOptions &LO) const {
+  auto E = OptMap.find(Ext);
+  if (E == OptMap.end()) {
+    return false;
+  }
+  auto I = OptMap.find(Ext)->getValue();
+  return I.Supported && I.isOptionalCoreIn(LO);
+}
+
+bool OpenCLOptions::isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
+                                                  const LangOptions &LO) const {
+  return isSupportedCore(Ext, LO) || isSupportedOptionalCore(Ext, LO);
+}
+
+bool OpenCLOptions::isSupportedExtension(llvm::StringRef Ext,
+                                         const LangOptions &LO) const {
+  auto E = OptMap.find(Ext);
+  if (E == OptMap.end()) {
+    return false;
+  }
+  auto I = OptMap.find(Ext)->getValue();
+  return I.Supported && I.isAvailableIn(LO) &&
+         !isSupportedCoreOrOptionalCore(Ext, LO);
+}
+
+void OpenCLOptions::enable(llvm::StringRef Ext, bool V) {
+  OptMap[Ext].Enabled = V;
+}
+
+void OpenCLOptions::support(llvm::StringRef Ext, bool V) {
+  assert(!Ext.empty() && "Extension is empty.");
+  assert(Ext[0] != '+' && Ext[0] != '-');
+  OptMap[Ext].Supported = V;
+}
+
+OpenCLOptions::OpenCLOptions() {
+#define OPENCL_GENERIC_EXTENSION(Ext, AvailVer, CoreVer, OptVer)               \
+  OptMap[#Ext].Avail = AvailVer;                                               \
+  OptMap[#Ext].Core = CoreVer;                                                 \
+  OptMap[#Ext].Opt = OptVer;
+#include "clang/Basic/OpenCLExtensions.def"
+}
+
+void OpenCLOptions::addSupport(const llvm::StringMap<bool> &FeaturesMap,
+                               const LangOptions &Opts) {
+  for (const auto &F : FeaturesMap) {
+    const auto &Name = F.getKey();
+    if (F.getValue() && isKnown(Name) && OptMap[Name].isAvailableIn(Opts))
+      support(Name);
+  }
+}
+
+void OpenCLOptions::disableAll() {
+  for (llvm::StringMap<OpenCLOptionInfo>::iterator I = OptMap.begin(),
+                                                   E = OptMap.end();
+       I != E; ++I)
+    I->second.Enabled = false;
+}
+
+void OpenCLOptions::enableSupportedCore(const LangOptions &LO) {
+  for (llvm::StringMap<OpenCLOptionInfo>::iterator I = OptMap.begin(),
+                                                   E = OptMap.end();
+       I != E; ++I)
+    if (isSupportedCoreOrOptionalCore(I->getKey(), LO))
+      I->second.Enabled = true;
+}
+
+} // end namespace clang
Index: clang/lib/Basic/CMakeLists.txt
===================================================================
--- clang/lib/Basic/CMakeLists.txt
+++ clang/lib/Basic/CMakeLists.txt
@@ -56,6 +56,7 @@
   LangStandards.cpp
   Module.cpp
   ObjCRuntime.cpp
+  OpenCLOptions.cpp
   OpenMPKinds.cpp
   OperatorPrecedence.cpp
   SanitizerBlacklist.cpp
Index: clang/include/clang/Basic/TargetOptions.h
===================================================================
--- clang/include/clang/Basic/TargetOptions.h
+++ clang/include/clang/Basic/TargetOptions.h
@@ -62,7 +62,7 @@
   llvm::StringMap<bool> FeatureMap;
 
   /// Supported OpenCL extensions and optional core features.
-  OpenCLOptions SupportedOpenCLOptions;
+  llvm::StringMap<bool> OpenCLFeaturesMap;
 
   /// The list of OpenCL extensions to enable or disable, as written on
   /// the command line.
Index: clang/include/clang/Basic/TargetInfo.h
===================================================================
--- clang/include/clang/Basic/TargetInfo.h
+++ clang/include/clang/Basic/TargetInfo.h
@@ -1438,21 +1438,39 @@
   /// Set supported OpenCL extensions and optional core features.
   virtual void setSupportedOpenCLOpts() {}
 
+  virtual void supportAllOpenCLOpts(bool V = true) {
+#define OPENCLEXTNAME(Ext) getTargetOpts().OpenCLFeaturesMap[#Ext] = V;
+#include "clang/Basic/OpenCLExtensions.def"
+  }
+
   /// Set supported OpenCL extensions as written on command line
-  virtual void setOpenCLExtensionOpts() {
+  virtual void setCommandLineOpenCLOpts() {
     for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) {
-      getTargetOpts().SupportedOpenCLOptions.support(Ext);
+      bool IsPrefixed = (Ext[0] == '+' || Ext[0] == '-');
+      std::string Name = IsPrefixed ? Ext.substr(1) : Ext;
+      bool V = IsPrefixed ? Ext[0] == '+' : true;
+
+      if (Name == "all") {
+        supportAllOpenCLOpts(V);
+        continue;
+      }
+
+      getTargetOpts().OpenCLFeaturesMap[Name] = V;
     }
   }
 
+  /// Define OpenCL macros based on target settings and language version
+  void getOpenCLFeatureDefines(const LangOptions &Opts,
+                               MacroBuilder &Builder) const;
+
   /// Get supported OpenCL extensions and optional core features.
-  OpenCLOptions &getSupportedOpenCLOpts() {
-    return getTargetOpts().SupportedOpenCLOptions;
+  llvm::StringMap<bool> &getSupportedOpenCLOpts() {
+    return getTargetOpts().OpenCLFeaturesMap;
   }
 
   /// Get const supported OpenCL extensions and optional core features.
-  const OpenCLOptions &getSupportedOpenCLOpts() const {
-      return getTargetOpts().SupportedOpenCLOptions;
+  const llvm::StringMap<bool> &getSupportedOpenCLOpts() const {
+    return getTargetOpts().OpenCLFeaturesMap;
   }
 
   /// Get address space for OpenCL type.
Index: clang/include/clang/Basic/OpenCLOptions.h
===================================================================
--- clang/include/clang/Basic/OpenCLOptions.h
+++ clang/include/clang/Basic/OpenCLOptions.h
@@ -19,157 +19,156 @@
 
 namespace clang {
 
-/// OpenCL supported extensions and optional core features
-class OpenCLOptions {
-  struct Info {
-    bool Supported; // Is this option supported
-    bool Enabled;   // Is this option enabled
-    unsigned Avail; // Option starts to be available in this OpenCL version
-    unsigned Core;  // Option becomes (optional) core feature in this OpenCL
-                    // version
-    Info(bool S = false, bool E = false, unsigned A = 100, unsigned C = ~0U)
-      :Supported(S), Enabled(E), Avail(A), Core(C){}
-  };
-  llvm::StringMap<Info> OptMap;
-public:
-  /// Check if \c Ext is a recognized OpenCL extension.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \returns \c true if \c Ext is known, \c false otherwise.
-  bool isKnown(llvm::StringRef Ext) const {
-    return OptMap.find(Ext) != OptMap.end();
-  }
+// This enum maps OpenCL version(s) into value. These values are used as
+// a mask to indicate in which OpenCL version(s) extension is a core or
+// optional core feature.
+enum OpenCLVersionID : unsigned int {
+  OCL_C_10 = 0x1,
+  OCL_C_11 = 0x2,
+  OCL_C_12 = 0x4,
+  OCL_C_20 = 0x8,
+  OCL_C_30 = 0x10,
+  OCL_C_ALL = 0x1f,
+  OCL_C_11P = OCL_C_ALL ^ OCL_C_10,              // OpenCL C 1.1+
+  OCL_C_12P = OCL_C_ALL ^ (OCL_C_10 | OCL_C_11), // OpenCL C 1.2+
+};
 
-  /// Check if \c Ext is an enabled OpenCL extension.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \returns \c true if \c Ext is known and enabled, \c false otherwise.
-  bool isEnabled(llvm::StringRef Ext) const {
-    auto E = OptMap.find(Ext);
-    return E != OptMap.end() && E->second.Enabled;
+static inline OpenCLVersionID encodeOpenCLVersion(unsigned OpenCLVersion) {
+  switch (OpenCLVersion) {
+  default:
+    llvm_unreachable("Unknown OpenCL versin code");
+  case 100:
+    return OCL_C_10;
+  case 110:
+    return OCL_C_11;
+  case 120:
+    return OCL_C_12;
+  case 200:
+    return OCL_C_20;
+  case 300:
+    return OCL_C_30;
   }
+}
 
-  /// Check if \c Ext is supported as either an extension or an (optional) core
-  /// feature for the given OpenCL version.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \param LO - \c LangOptions specifying the OpenCL version.
-  /// \returns \c true if \c Ext is known and supported, \c false otherwise.
-  bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const {
-    auto E = OptMap.find(Ext);
-    if (E == OptMap.end()) {
-      return false;
-    }
-    // In C++ mode all extensions should work at least as in v2.0.
-    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
-    auto I = E->getValue();
-    return I.Supported && I.Avail <= CLVer;
-  }
+// Simple helper to check if OpenCL C version is contained in a given encoded
+// OpenCL C version mask
+static inline bool OpenCLVersionIsContainedInMask(const LangOptions &LO,
+                                                  unsigned Mask) {
+  auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
+  OpenCLVersionID Code = encodeOpenCLVersion(CLVer);
+  return Mask & Code;
+}
 
-  /// Check if \c Ext is supported as an (optional) OpenCL core features for
-  /// the given OpenCL version.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \param LO - \c LangOptions specifying the OpenCL version.
-  /// \returns \c true if \c Ext is known and supported, \c false otherwise.
-  bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const {
-    auto E = OptMap.find(Ext);
-    if (E == OptMap.end()) {
-      return false;
-    }
-    // In C++ mode all extensions should work at least as in v2.0.
-    auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
-    auto I = E->getValue();
-    return I.Supported && I.Avail <= CLVer && I.Core != ~0U && CLVer >= I.Core;
-  }
+struct OpenCLOptionInfo {
+  // Option starts to be available in this OpenCL version
+  unsigned Avail;
 
-  /// Check if \c Ext is a supported OpenCL extension for the given OpenCL
-  /// version.
-  ///
-  /// \param Ext - Extension to look up.
-  /// \param LO - \c LangOptions specifying the OpenCL version.
-  /// \returns \c true if \c Ext is known and supported, \c false otherwise.
-  bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const {
-    auto E = OptMap.find(Ext);
-    if (E == OptMap.end()) {
-      return false;
-    }
+  // Option becomes core feature in this OpenCL versions
+  unsigned Core;
+
+  // Option becomes optional core feature in this OpenCL versions
+  unsigned Opt;
+
+  // Is this option supported
+  bool Supported = false;
+
+  // Is this option enabled
+  bool Enabled = false;
+
+  OpenCLOptionInfo(unsigned A = 100, unsigned C = 0U, unsigned O = 0U)
+      : Avail(A), Core(C), Opt(O) {}
+
+  bool isCore() const { return Core != 0U; }
+
+  bool isOptionalCore() const { return Opt != 0U; }
+
+  // Is option available in OpenCL version \p LO.
+  bool isAvailableIn(const LangOptions &LO) const {
     // In C++ mode all extensions should work at least as in v2.0.
     auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
-    auto I = E->getValue();
-    return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core);
+    return CLVer >= Avail;
   }
 
-  void enable(llvm::StringRef Ext, bool V = true) {
-    OptMap[Ext].Enabled = V;
+  // Is core option in OpenCL version \p LO.
+  bool isCoreIn(const LangOptions &LO) const {
+    return isAvailableIn(LO) && OpenCLVersionIsContainedInMask(LO, Core);
   }
 
-  /// Enable or disable support for OpenCL extensions
-  /// \param Ext name of the extension optionally prefixed with
-  ///        '+' or '-'
-  /// \param V used when \p Ext is not prefixed by '+' or '-'
-  void support(llvm::StringRef Ext, bool V = true) {
-    assert(!Ext.empty() && "Extension is empty.");
-
-    switch (Ext[0]) {
-    case '+':
-      V = true;
-      Ext = Ext.drop_front();
-      break;
-    case '-':
-      V = false;
-      Ext = Ext.drop_front();
-      break;
-    }
-
-    if (Ext.equals("all")) {
-      supportAll(V);
-      return;
-    }
-    OptMap[Ext].Supported = V;
+  // Is optional core option in OpenCL version \p LO.
+  bool isOptionalCoreIn(const LangOptions &LO) const {
+    return isAvailableIn(LO) && OpenCLVersionIsContainedInMask(LO, Opt);
   }
+};
 
-  OpenCLOptions(){
-#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
-    OptMap[#Ext].Avail = AvailVer; \
-    OptMap[#Ext].Core = CoreVer;
-#include "clang/Basic/OpenCLExtensions.def"
-  }
+/// OpenCL supported extensions and optional core features
+class OpenCLOptions {
 
-  void addSupport(const OpenCLOptions &Opts) {
-    for (auto &I:Opts.OptMap)
-      if (I.second.Supported)
-        OptMap[I.getKey()].Supported = true;
-  }
+  llvm::StringMap<OpenCLOptionInfo> OptMap;
 
-  void copy(const OpenCLOptions &Opts) {
-    OptMap = Opts.OptMap;
-  }
+public:
+  bool isKnown(llvm::StringRef Ext) const;
 
-  // Turn on or off support of all options.
-  void supportAll(bool On = true) {
-    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
-         E = OptMap.end(); I != E; ++I)
-      I->second.Supported = On;
-  }
+  bool isEnabled(llvm::StringRef Ext) const;
 
-  void disableAll() {
-    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
-         E = OptMap.end(); I != E; ++I)
-      I->second.Enabled = false;
-  }
+  // Is supported as either an extension or an (optional) core feature for
+  // OpenCL version \p LO.
+  bool isSupported(llvm::StringRef Ext, const LangOptions &LO) const;
 
-  void enableSupportedCore(LangOptions LO) {
-    for (llvm::StringMap<Info>::iterator I = OptMap.begin(), E = OptMap.end();
-         I != E; ++I)
-      if (isSupportedCore(I->getKey(), LO))
-        I->second.Enabled = true;
-  }
+  // Is supported OpenCL core feature for OpenCL version \p LO.
+  // For supported extension, return false.
+  bool isSupportedCore(llvm::StringRef Ext, const LangOptions &LO) const;
+
+  // Is supported optional core OpenCL feature for OpenCL version \p LO.
+  // For supported extension, return false.
+  bool isSupportedOptionalCore(llvm::StringRef Ext,
+                               const LangOptions &LO) const;
+
+  // Is supported optional core or core OpenCL feature for OpenCL version \p
+  // LO. For supported extension, return false.
+  bool isSupportedCoreOrOptionalCore(llvm::StringRef Ext,
+                                     const LangOptions &LO) const;
+
+  // Is supported OpenCL extension for OpenCL version \p LO.
+  // For supported core or optional core feature, return false.
+  bool isSupportedExtension(llvm::StringRef Ext, const LangOptions &LO) const;
+
+  void enable(llvm::StringRef Ext, bool V = true);
+
+  /// Enable or disable support for OpenCL extensions
+  /// \param Ext name of the extension (not prefixed with '+' or '-')
+  /// \param V value to set for a extension
+  void support(llvm::StringRef Ext, bool V = true);
+
+  OpenCLOptions();
+  OpenCLOptions(const OpenCLOptions &) = default;
+
+  // Set supported options based on target settings and language version
+  void addSupport(const llvm::StringMap<bool> &FeaturesMap,
+                  const LangOptions &Opts);
+
+  // Disable all extensions
+  void disableAll();
+
+  // Enable supported core and optional core features
+  void enableSupportedCore(const LangOptions &LO);
 
   friend class ASTWriter;
   friend class ASTReader;
 };
 
+// Get a list of all extensions which are core in OpenCL version \p LO.
+static inline llvm::SmallVector<std::string, 16>
+getCoreFeatures(const LangOptions &LO) {
+  llvm::SmallVector<std::string, 16> CoreFeatures;
+
+#define OPENCL_GENERIC_EXTENSION(Ext, Avail, Core, Opt)                        \
+  if (OpenCLOptionInfo(Avail, Core, Opt).isCoreIn(LO))                         \
+    CoreFeatures.push_back(#Ext);
+#include "clang/Basic/OpenCLExtensions.def"
+
+  return CoreFeatures;
+}
+
 } // end namespace clang
 
 #endif
Index: clang/include/clang/Basic/OpenCLExtensions.def
===================================================================
--- clang/include/clang/Basic/OpenCLExtensions.def
+++ clang/include/clang/Basic/OpenCLExtensions.def
@@ -10,19 +10,23 @@
 //
 //===----------------------------------------------------------------------===//
 
-// Macro OPENCLEXT or OPENCLEXT_INTERNAL can be defined to enumerate the
+// Macro OPENCLEXTNAME or OPENCL_GENERIC_EXTENSION can be defined to enumerate all
 // OpenCL extensions listed in this file.
 //
 // If the extensions are to be enumerated without the supported OpenCL version,
-// define OPENCLEXT(ext) where ext is the name of the extension.
+// define OPENCLEXTNAME(ext) where ext is the name of the extension.
 //
 // If the extensions are to be enumerated with supported OpenCL version,
-// define OPENCLEXT_INTERNAL(ext, avail, core) where
+// define OPENCL_GENERIC_EXTENSION(ext, avail, core, opt) where
 //   ext - name of the extension or optional core feature.
 //   avail - minimum OpenCL version supporting it.
-//   core - minimum OpenCL version when the extension becomes optional core
-//          feature or core feature. ~0U indicates not a core feature or an
-//          optional core feature.
+//   core - OpenCL versions mask when the extension becomes core feature.
+//          0U indicates not a core feature.
+//   opt - OpenCL versions mask when the extension becomes optional core
+//         feature. 0U indicates not a optional core feature.
+//
+// Difference between optional core feature and core feature is that the 
+// later is unconditionally supported in specific OpenCL version.
 //
 // As per The OpenCL Extension Specification, Section 1.2, in this file, an
 // extension is defined if and only it either:
@@ -32,63 +36,79 @@
 // For such an extension, a preprocessor #define that matches the extension
 // name must be created and a #pragma is required if and only if the
 // compilation flow is impacted, e.g. due to a difference of syntax or
-// semantics in the language compared to the core standard.
+// semantics in the language compared to the core standard. #pragma directive
+// has no effect for optional core and core features.
 
-#ifndef OPENCLEXT_INTERNAL
-#ifndef OPENCLEXT
-#pragma error "macro OPENCLEXT or OPENCLEXT_INTERNAL is required"
+#ifndef OPENCL_GENERIC_EXTENSION
+#ifndef OPENCLEXTNAME
+#pragma error "macro OPENCLEXTNAME or OPENCL_GENERIC_EXTENSION is required"
 #else
-#define OPENCLEXT_INTERNAL(ext, ...) OPENCLEXT(ext)
-#endif // OPENCLEXT
-#endif // OPENCLEXT_INTERNAL
+#define OPENCL_GENERIC_EXTENSION(ext, ...) OPENCLEXTNAME(ext)
+#endif // OPENCLEXTNAME
+#endif // OPENCL_GENERIC_EXTENSION
+
+// Declaration helpers
+#define OPENCL_EXTENSION(ext, avail) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, 0U)
+#define OPENCL_COREFEATURE(ext, avail, core)  OPENCL_GENERIC_EXTENSION(ext, avail, core, 0U)
+#define OPENCL_OPTIONALCOREFEATURE(ext, avail, opt) OPENCL_GENERIC_EXTENSION(ext, avail, 0U, opt)
 
 // OpenCL 1.0.
-OPENCLEXT_INTERNAL(cl_khr_3d_image_writes, 100, 200)
-OPENCLEXT_INTERNAL(cl_khr_byte_addressable_store, 100, 110)
-OPENCLEXT_INTERNAL(cl_khr_fp16, 100, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_fp64, 100, 120)
-OPENCLEXT_INTERNAL(cl_khr_global_int32_base_atomics, 100, 110)
-OPENCLEXT_INTERNAL(cl_khr_global_int32_extended_atomics, 100, 110)
-OPENCLEXT_INTERNAL(cl_khr_local_int32_base_atomics, 100, 110)
-OPENCLEXT_INTERNAL(cl_khr_local_int32_extended_atomics, 100, 110)
-OPENCLEXT_INTERNAL(cl_khr_int64_base_atomics, 100, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_int64_extended_atomics, 100, ~0U)
+OPENCL_COREFEATURE(cl_khr_byte_addressable_store, 100, OCL_C_11P)
+OPENCL_COREFEATURE(cl_khr_global_int32_base_atomics, 100, OCL_C_11P)
+OPENCL_COREFEATURE(cl_khr_global_int32_extended_atomics, 100, OCL_C_11P)
+OPENCL_COREFEATURE(cl_khr_local_int32_base_atomics, 100, OCL_C_11P)
+OPENCL_COREFEATURE(cl_khr_local_int32_extended_atomics, 100, OCL_C_11P)
+OPENCL_OPTIONALCOREFEATURE(cl_khr_fp64, 100, OCL_C_12P)
+OPENCL_EXTENSION(cl_khr_fp16, 100)
+OPENCL_EXTENSION(cl_khr_int64_base_atomics, 100)
+OPENCL_EXTENSION(cl_khr_int64_extended_atomics, 100)
+OPENCL_GENERIC_EXTENSION(cl_khr_3d_image_writes, 100, OCL_C_20, OCL_C_30)
 
 // EMBEDDED_PROFILE
-OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U)
+OPENCL_EXTENSION(cles_khr_int64, 110)
 
 // OpenCL 1.2.
-OPENCLEXT_INTERNAL(cl_khr_depth_images, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_gl_msaa_sharing, 120, ~0U)
+OPENCL_EXTENSION(cl_khr_depth_images, 120)
+OPENCL_EXTENSION(cl_khr_gl_msaa_sharing, 120)
 
 // OpenCL 2.0.
-OPENCLEXT_INTERNAL(cl_khr_mipmap_image, 200, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_mipmap_image_writes, 200, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_srgb_image_writes, 200, ~0U)
-OPENCLEXT_INTERNAL(cl_khr_subgroups, 200, ~0U)
+OPENCL_EXTENSION(cl_khr_mipmap_image, 200)
+OPENCL_EXTENSION(cl_khr_mipmap_image_writes, 200)
+OPENCL_EXTENSION(cl_khr_srgb_image_writes, 200)
+OPENCL_EXTENSION(cl_khr_subgroups, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_extended_types, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_non_uniform_vote, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_ballot, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_non_uniform_arithmetic, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_shuffle, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_shuffle_relative, 200)
+OPENCL_EXTENSION(cl_khr_subgroup_clustered_reduce, 200)
 
 // Clang Extensions.
-OPENCLEXT_INTERNAL(cl_clang_storage_class_specifiers, 100, ~0U)
-OPENCLEXT_INTERNAL(__cl_clang_function_pointers, 100, ~0U)
-OPENCLEXT_INTERNAL(__cl_clang_variadic_functions, 100, ~0U)
+OPENCL_EXTENSION(cl_clang_storage_class_specifiers, 100)
+OPENCL_EXTENSION(__cl_clang_function_pointers, 100)
+OPENCL_EXTENSION(__cl_clang_variadic_functions, 100)
 
 // AMD OpenCL extensions
-OPENCLEXT_INTERNAL(cl_amd_media_ops, 100, ~0U)
-OPENCLEXT_INTERNAL(cl_amd_media_ops2, 100, ~0U)
+OPENCL_EXTENSION(cl_amd_media_ops, 100)
+OPENCL_EXTENSION(cl_amd_media_ops2, 100)
 
 // ARM OpenCL extensions
-OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_int8, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int8, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_int16, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_arm_integer_dot_product_accumulate_saturate_int8, 120, ~0U)
+OPENCL_EXTENSION(cl_arm_integer_dot_product_int8, 120)
+OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int8, 120)
+OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_int16, 120)
+OPENCL_EXTENSION(cl_arm_integer_dot_product_accumulate_saturate_int8, 120)
 
 // Intel OpenCL extensions
-OPENCLEXT_INTERNAL(cl_intel_subgroups, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_intel_subgroups_short, 120, ~0U)
-OPENCLEXT_INTERNAL(cl_intel_device_side_avc_motion_estimation, 120, ~0U)
+OPENCL_EXTENSION(cl_intel_subgroups, 120)
+OPENCL_EXTENSION(cl_intel_subgroups_short, 120)
+OPENCL_EXTENSION(cl_intel_device_side_avc_motion_estimation, 120)
+
 
-#undef OPENCLEXT_INTERNAL
+#undef OPENCL_OPTIONALCOREFEATURE
+#undef OPENCL_COREFEATURE
+#undef OPENCL_GENERIC_EXTENSION
 
-#ifdef OPENCLEXT
-#undef OPENCLEXT
+#ifdef OPENCLEXTNAME
+#undef OPENCLEXTNAME
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to