r289979 - [OpenCL] Allow disabling types and declarations associated with extensions

Yaxun Liu via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 16 11:22:09 PST 2016


Author: yaxunl
Date: Fri Dec 16 13:22:08 2016
New Revision: 289979

URL: http://llvm.org/viewvc/llvm-project?rev=289979&view=rev
Log:
[OpenCL] Allow disabling types and declarations associated with extensions

Added a map to associate types and declarations with extensions.

Refactored existing diagnostic for disabled types associated with extensions and extended it to declarations for generic situation.

Fixed some bugs for types associated with extensions.

Allow users to use pragma to declare types and functions for supported extensions, e.g.

#pragma OPENCL EXTENSION the_new_extension_name : begin
// declare types and functions associated with the extension here
#pragma OPENCL EXTENSION the_new_extension_name : end

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

Added:
    cfe/trunk/test/CodeGenOpenCL/extension-begin.cl
    cfe/trunk/test/SemaOpenCL/extension-begin.cl
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/OpenCLImageTypes.def
    cfe/trunk/include/clang/Basic/OpenCLOptions.h
    cfe/trunk/include/clang/Basic/TargetInfo.h
    cfe/trunk/include/clang/Sema/Overload.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Serialization/ASTBitCodes.h
    cfe/trunk/include/clang/Serialization/ASTReader.h
    cfe/trunk/include/clang/Serialization/ASTWriter.h
    cfe/trunk/lib/Basic/Targets.cpp
    cfe/trunk/lib/Frontend/InitPreprocessor.cpp
    cfe/trunk/lib/Headers/opencl-c.h
    cfe/trunk/lib/Parse/ParsePragma.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaCast.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/Parser/opencl-atomics-cl20.cl
    cfe/trunk/test/Parser/opencl-pragma.cl
    cfe/trunk/test/SemaOpenCL/extensions.cl

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Fri Dec 16 13:22:08 2016
@@ -968,8 +968,10 @@ def err_opencl_unroll_hint_on_non_loop :
 // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1])
 def warn_pragma_expected_colon : Warning<
   "missing ':' after %0 - ignoring">, InGroup<IgnoredPragmas>;
-def warn_pragma_expected_enable_disable : Warning<
-  "expected 'enable' or 'disable' - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_expected_predicate : Warning<
+  "expected %select{'enable', 'disable', 'begin' or 'end'|'disable'}0 - ignoring">, InGroup<IgnoredPragmas>;
+def warn_pragma_begin_end_mismatch : Warning<
+  "OpenCL extension end directive mismatches begin directive - ignoring">, InGroup<IgnoredPragmas>;
 def warn_pragma_unknown_extension : Warning<
   "unknown OpenCL extension %0 - ignoring">, InGroup<IgnoredPragmas>;
 def warn_pragma_unsupported_extension : Warning<

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 16 13:22:08 2016
@@ -3359,6 +3359,8 @@ def note_ovl_candidate_has_pass_object_s
     "pass_object_size attribute">;
 def note_ovl_candidate_disabled_by_enable_if_attr : Note<
     "candidate disabled: %0">;
+def note_ovl_candidate_disabled_by_extension : Note<
+    "candidate disabled due to OpenCL extension">;
 def err_addrof_function_disabled_by_enable_if_attr : Error<
     "cannot take address of function %0 becuase it has one or more "
     "non-tautological enable_if conditions">;
@@ -7936,8 +7938,6 @@ def ext_c99_array_usage : Extension<
 def err_c99_array_usage_cxx : Error<
   "%select{qualifier in |static |}0array size %select{||'[*] '}0is a C99 "
   "feature, not permitted in C++">;
- def err_type_requires_extension : Error<
-  "use of type %0 requires %1 extension to be enabled">;
 def err_type_unsupported : Error<
   "%0 is not supported on this target">;
 def err_nsconsumed_attribute_mismatch : Error<
@@ -8143,6 +8143,8 @@ def warn_opencl_attr_deprecated_ignored
   InGroup<IgnoredAttributes>;
 def err_opencl_variadic_function : Error<
   "invalid prototype, variadic arguments are not allowed in OpenCL">;
+def err_opencl_requires_extension : Error<
+  "use of %select{type |declaration}0%1 requires %2 extension to be enabled">;
 
 // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions
 def err_opencl_builtin_pipe_first_arg : Error<

Modified: cfe/trunk/include/clang/Basic/OpenCLImageTypes.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenCLImageTypes.def?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenCLImageTypes.def (original)
+++ cfe/trunk/include/clang/Basic/OpenCLImageTypes.def Fri Dec 16 13:22:08 2016
@@ -7,73 +7,79 @@
 //
 //===----------------------------------------------------------------------===//
 //  This file extends builtin types database with OpenCL image singleton types.
-//  Custom code should define one of those two macros:
-//    GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an 
+//  Custom code should define one of those three macros:
+//    GENERIC_IMAGE_TYPE(Type, Id) - a generic image with its Id without an
 //      access type
 //    IMAGE_TYPE(Type, Id, SingletonId, AccessType, CGSuffix) - an image type
-//      with given ID, singleton ID access type and a codegen suffix  
+//      with given ID, singleton ID access type and a codegen suffix
+//    GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) - a generic image with its Id and
+//      required extension without an access type
 
 #ifdef GENERIC_IMAGE_TYPE
 
-#define IMAGE_READ_TYPE(Type, Id) GENERIC_IMAGE_TYPE(Type, Id)
-#define IMAGE_WRITE_TYPE(Type, Id) 
-#define IMAGE_READ_WRITE_TYPE(Type, Id) 
+#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE(Type, Id)
+#define IMAGE_WRITE_TYPE(Type, Id, Ext)
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext)
+
+#elif defined(GENERIC_IMAGE_TYPE_EXT)
+#define IMAGE_READ_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##ROTy, Ext)
+#define IMAGE_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##WOTy, Ext)
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) GENERIC_IMAGE_TYPE_EXT(Type, Id##RWTy, Ext)
 
 #else
-
 #ifndef IMAGE_READ_TYPE
-#define IMAGE_READ_TYPE(Type, Id) \
+#define IMAGE_READ_TYPE(Type, Id, Ext) \
           IMAGE_TYPE(Type, Id##RO, Id##ROTy,  read_only, ro)
 #endif
 #ifndef IMAGE_WRITE_TYPE
-#define IMAGE_WRITE_TYPE(Type, Id) \
+#define IMAGE_WRITE_TYPE(Type, Id, Ext) \
           IMAGE_TYPE(Type, Id##WO, Id##WOTy, write_only, wo)
 #endif
 #ifndef IMAGE_READ_WRITE_TYPE
-#define IMAGE_READ_WRITE_TYPE(Type, Id) \
+#define IMAGE_READ_WRITE_TYPE(Type, Id, Ext) \
           IMAGE_TYPE(Type, Id##RW, Id##RWTy, read_write, rw)
 #endif
 
 #endif
 
-IMAGE_READ_TYPE(image1d, OCLImage1d)
-IMAGE_READ_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_READ_TYPE(image2d, OCLImage2d)
-IMAGE_READ_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_READ_TYPE(image3d, OCLImage3d)
-
-IMAGE_WRITE_TYPE(image1d, OCLImage1d)
-IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_WRITE_TYPE(image2d, OCLImage2d)
-IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_WRITE_TYPE(image3d, OCLImage3d)
-
-IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d)
-IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray)
-IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer)
-IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d)
-IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray)
-IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth)
-IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth)
-IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA)
-IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA)
-IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth)
-IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth)
-IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d)
+IMAGE_READ_TYPE(image1d, OCLImage1d, "")
+IMAGE_READ_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_READ_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_READ_TYPE(image2d, OCLImage2d, "")
+IMAGE_READ_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_READ_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_READ_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_READ_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_TYPE(image3d, OCLImage3d, "")
+
+IMAGE_WRITE_TYPE(image1d, OCLImage1d, "")
+IMAGE_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_WRITE_TYPE(image2d, OCLImage2d, "")
+IMAGE_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_WRITE_TYPE(image3d, OCLImage3d, "")
+
+IMAGE_READ_WRITE_TYPE(image1d, OCLImage1d, "")
+IMAGE_READ_WRITE_TYPE(image1d_array, OCLImage1dArray, "")
+IMAGE_READ_WRITE_TYPE(image1d_buffer, OCLImage1dBuffer, "")
+IMAGE_READ_WRITE_TYPE(image2d, OCLImage2d, "")
+IMAGE_READ_WRITE_TYPE(image2d_array, OCLImage2dArray, "")
+IMAGE_READ_WRITE_TYPE(image2d_depth, OCLImage2dDepth, "")
+IMAGE_READ_WRITE_TYPE(image2d_array_depth, OCLImage2dArrayDepth, "")
+IMAGE_READ_WRITE_TYPE(image2d_msaa, OCLImage2dMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_array_msaa, OCLImage2dArrayMSAA, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_msaa_depth, OCLImage2dMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image2d_array_msaa_depth, OCLImage2dArrayMSAADepth, "cl_khr_gl_msaa_sharing")
+IMAGE_READ_WRITE_TYPE(image3d, OCLImage3d, "")
 
 #undef IMAGE_TYPE
 #undef GENERIC_IMAGE_TYPE

Modified: cfe/trunk/include/clang/Basic/OpenCLOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/OpenCLOptions.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/OpenCLOptions.h (original)
+++ cfe/trunk/include/clang/Basic/OpenCLOptions.h Fri Dec 16 13:22:08 2016
@@ -15,81 +15,122 @@
 #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H
 #define LLVM_CLANG_BASIC_OPENCLOPTIONS_H
 
-#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringMap.h"
 
 namespace clang {
 
 /// \brief 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:
-#define OPENCLEXT(nm) unsigned nm : 1;
-#include "clang/Basic/OpenCLExtensions.def"
+  bool isKnown(StringRef Ext) const {
+    return OptMap.find(Ext) != OptMap.end();
+  }
 
-  OpenCLOptions() {
-#define OPENCLEXT(nm)   nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
+  bool isEnabled(StringRef Ext) const {
+    return OptMap.find(Ext)->second.Enabled;
   }
 
-  // Enable or disable all options.
-  void setAll(bool Enable = true) {
-#define OPENCLEXT(nm)   nm = Enable;
-#include "clang/Basic/OpenCLExtensions.def"
+  // Is supported as either an extension or an (optional) core feature for
+  // OpenCL version \p CLVer.
+  bool isSupported(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer;
+  }
+
+  // Is supported (optional) OpenCL core features for OpenCL version \p CLVer.
+  // For supported extension, return false.
+  bool isSupportedCore(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer &&
+      I.Core != ~0U && CLVer >= I.Core;
+  }
+
+  // Is supported OpenCL extension for OpenCL version \p CLVer.
+  // For supported (optional) core feature, return false.
+ bool isSupportedExtension(StringRef Ext, unsigned CLVer) const {
+    auto I = OptMap.find(Ext)->getValue();
+    return I.Supported && I.Avail <= CLVer &&
+      (I.Core == ~0U || CLVer < I.Core);
+  }
+
+  void enable(StringRef Ext, bool V = true) {
+    OptMap[Ext].Enabled = V;
   }
 
   /// \brief Enable or disable support for OpenCL extensions
   /// \param Ext name of the extension optionally prefixed with
   ///        '+' or '-'
   /// \param Enable used when \p Ext is not prefixed by '+' or '-'
-  void set(llvm::StringRef Ext, bool Enable = true) {
+  void support(StringRef Ext, bool V = true) {
     assert(!Ext.empty() && "Extension is empty.");
 
     switch (Ext[0]) {
     case '+':
-      Enable = true;
+      V = true;
       Ext = Ext.drop_front();
       break;
     case '-':
-      Enable = false;
+      V = false;
       Ext = Ext.drop_front();
       break;
     }
 
     if (Ext.equals("all")) {
-      setAll(Enable);
+      supportAll(V);
       return;
     }
+    OptMap[Ext].Supported = V;
+  }
 
-#define OPENCLEXT(nm)       \
-    if (Ext.equals(#nm)) {  \
-      nm = Enable;          \
-    }
+  OpenCLOptions(){
+#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \
+    OptMap[#Ext].Avail = AvailVer; \
+    OptMap[#Ext].Core = CoreVer;
 #include "clang/Basic/OpenCLExtensions.def"
   }
 
-  // Is supported with OpenCL version \p OCLVer.
-#define OPENCLEXT_INTERNAL(Ext, Avail, ...) \
-  bool is_##Ext##_supported(unsigned OCLVer) const { \
-    return Ext && OCLVer >= Avail; \
+  void addSupport(const OpenCLOptions &Opts) {
+    for (auto &I:Opts.OptMap)
+      if (I.second.Supported)
+        OptMap[I.getKey()].Supported = true;
   }
-#include "clang/Basic/OpenCLExtensions.def"
 
+  void copy(const OpenCLOptions &Opts) {
+    OptMap = Opts.OptMap;
+  }
 
-  // Is supported OpenCL extension with OpenCL version \p OCLVer.
-  // For supported optional core feature, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
-  bool is_##Ext##_supported_extension(unsigned CLVer) const { \
-    return is_##Ext##_supported(CLVer) && (Core == ~0U || CLVer < Core); \
+  // 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;
   }
-#include "clang/Basic/OpenCLExtensions.def"
 
-  // Is supported OpenCL core features with OpenCL version \p OCLVer.
-  // For supported extension, return false.
-#define OPENCLEXT_INTERNAL(Ext, Avail, Core) \
-  bool is_##Ext##_supported_core(unsigned CLVer) const { \
-    return is_##Ext##_supported(CLVer) && Core != ~0U && CLVer >= Core; \
+  void disableAll() {
+    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+         E = OptMap.end(); I != E; ++I)
+      I->second.Enabled = false;
+  }
+
+  void enableSupportedCore(unsigned CLVer) {
+    for (llvm::StringMap<Info>::iterator I = OptMap.begin(),
+         E = OptMap.end(); I != E; ++I)
+      if (isSupportedCore(I->getKey(), CLVer))
+        I->second.Enabled = true;
   }
-#include "clang/Basic/OpenCLExtensions.def"
 
+  friend class ASTWriter;
+  friend class ASTReader;
 };
 
 }  // end namespace clang

Modified: cfe/trunk/include/clang/Basic/TargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetInfo.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetInfo.h (original)
+++ cfe/trunk/include/clang/Basic/TargetInfo.h Fri Dec 16 13:22:08 2016
@@ -1005,7 +1005,7 @@ public:
   /// \brief Set supported OpenCL extensions as written on command line
   virtual void setOpenCLExtensionOpts() {
     for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) {
-      getTargetOpts().SupportedOpenCLOptions.set(Ext);
+      getTargetOpts().SupportedOpenCLOptions.support(Ext);
     }
   }
 

Modified: cfe/trunk/include/clang/Sema/Overload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Overload.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Overload.h (original)
+++ cfe/trunk/include/clang/Sema/Overload.h Fri Dec 16 13:22:08 2016
@@ -592,7 +592,10 @@ namespace clang {
     ovl_fail_enable_if,
 
     /// This candidate was not viable because its address could not be taken.
-    ovl_fail_addr_not_available
+    ovl_fail_addr_not_available,
+
+    /// This candidate was not viable because its OpenCL extension is disabled.
+    ovl_fail_ext_disabled,
   };
 
   /// OverloadCandidate - A single candidate in an overload set (C++ 13.3).

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Dec 16 13:22:08 2016
@@ -8051,6 +8051,58 @@ public:
   void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body);
 
   //===--------------------------------------------------------------------===//
+  // OpenCL extensions.
+  //
+private:
+  std::string CurrOpenCLExtension;
+  /// Extensions required by an OpenCL type.
+  llvm::DenseMap<const Type*, std::set<std::string>> OpenCLTypeExtMap;
+  /// Extensions required by an OpenCL declaration.
+  llvm::DenseMap<const Decl*, std::set<std::string>> OpenCLDeclExtMap;
+public:
+  llvm::StringRef getCurrentOpenCLExtension() const {
+    return CurrOpenCLExtension;
+  }
+  void setCurrentOpenCLExtension(llvm::StringRef Ext) {
+    CurrOpenCLExtension = Ext;
+  }
+
+  /// \brief Set OpenCL extensions for a type which can only be used when these
+  /// OpenCL extensions are enabled. If \p Exts is empty, do nothing.
+  /// \param Exts A space separated list of OpenCL extensions.
+  void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts);
+
+  /// \brief Set OpenCL extensions for a declaration which can only be
+  /// used when these OpenCL extensions are enabled. If \p Exts is empty, do
+  /// nothing.
+  /// \param Exts A space separated list of OpenCL extensions.
+  void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts);
+
+  /// \brief Set current OpenCL extensions for a type which can only be used
+  /// when these OpenCL extensions are enabled. If current OpenCL extension is
+  /// empty, do nothing.
+  void setCurrentOpenCLExtensionForType(QualType T);
+
+  /// \brief Set current OpenCL extensions for a declaration which
+  /// can only be used when these OpenCL extensions are enabled. If current
+  /// OpenCL extension is empty, do nothing.
+  void setCurrentOpenCLExtensionForDecl(Decl *FD);
+
+  bool isOpenCLDisabledDecl(Decl *FD);
+
+  /// \brief Check if type \p T corresponding to declaration specifier \p DS
+  /// is disabled due to required OpenCL extensions being disabled. If so,
+  /// emit diagnostics.
+  /// \return true if type is disabled.
+  bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T);
+
+  /// \brief Check if declaration \p D used by expression \p E
+  /// is disabled due to required OpenCL extensions being disabled. If so,
+  /// emit diagnostics.
+  /// \return true if type is disabled.
+  bool checkOpenCLDisabledDecl(const Decl &D, const Expr &E);
+
+  //===--------------------------------------------------------------------===//
   // OpenMP directives and clauses.
   //
 private:
@@ -8066,6 +8118,21 @@ private:
   /// Returns OpenMP nesting level for current directive.
   unsigned getOpenMPNestingLevel() const;
 
+  /// Checks if a type or a declaration is disabled due to the owning extension
+  /// being disabled, and emits diagnostic messages if it is disabled.
+  /// \param D type or declaration to be checked.
+  /// \param DiagLoc source location for the diagnostic message.
+  /// \param DiagInfo information to be emitted for the diagnostic message.
+  /// \param SrcRange source range of the declaration.
+  /// \param Map maps type or declaration to the extensions.
+  /// \param Selector selects diagnostic message: 0 for type and 1 for
+  ///        declaration.
+  /// \return true if the type or declaration is disabled.
+  template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+  bool checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc, DiagInfoT DiagInfo,
+                                     MapT &Map, unsigned Selector = 0,
+                                     SourceRange SrcRange = SourceRange());
+
 public:
   /// \brief Return true if the provided declaration \a VD should be captured by
   /// reference.

Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Fri Dec 16 13:22:08 2016
@@ -344,7 +344,7 @@ namespace clang {
       ///
       /// The TYPE_OFFSET constant describes the record that occurs
       /// within the AST block. The record itself is an array of offsets that
-      /// point into the declarations and types block (identified by 
+      /// point into the declarations and types block (identified by
       /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
       /// of a type. For a given type ID @c T, the lower three bits of
       /// @c T are its qualifiers (const, volatile, restrict), as in
@@ -446,10 +446,10 @@ namespace clang {
 
       /// \brief Record code for the set of ext_vector type names.
       EXT_VECTOR_DECLS = 16,
-      
+
       /// \brief Record code for the array of unused file scoped decls.
       UNUSED_FILESCOPED_DECLS = 17,
-      
+
       /// \brief Record code for the table of offsets to entries in the
       /// preprocessing record.
       PPD_ENTITIES_OFFSETS = 18,
@@ -465,7 +465,7 @@ namespace clang {
       /// \brief Record code for an update to the TU's lexically contained
       /// declarations.
       TU_UPDATE_LEXICAL = 22,
-      
+
       // ID 23 used to be for a list of local redeclarations.
 
       /// \brief Record code for declarations that Sema keeps references of.
@@ -490,7 +490,7 @@ namespace clang {
 
       // ID 30 used to be a decl update record. These are now in the DECLTYPES
       // block.
-      
+
       // ID 31 used to be a list of offsets to DECL_CXX_BASE_SPECIFIERS records.
 
       /// \brief Record code for \#pragma diagnostic mappings.
@@ -498,7 +498,7 @@ namespace clang {
 
       /// \brief Record code for special CUDA declarations.
       CUDA_SPECIAL_DECL_REFS = 33,
-      
+
       /// \brief Record code for header search information.
       HEADER_SEARCH_TABLE = 34,
 
@@ -516,7 +516,7 @@ namespace clang {
       KNOWN_NAMESPACES = 38,
 
       /// \brief Record code for the remapping information used to relate
-      /// loaded modules to the various offsets and IDs(e.g., source location 
+      /// loaded modules to the various offsets and IDs(e.g., source location
       /// offests, declaration and type IDs) that are used in that module to
       /// refer to other modules.
       MODULE_OFFSET_MAP = 39,
@@ -525,20 +525,20 @@ namespace clang {
       /// which stores information about \#line directives.
       SOURCE_MANAGER_LINE_TABLE = 40,
 
-      /// \brief Record code for map of Objective-C class definition IDs to the 
+      /// \brief Record code for map of Objective-C class definition IDs to the
       /// ObjC categories in a module that are attached to that class.
       OBJC_CATEGORIES_MAP = 41,
 
       /// \brief Record code for a file sorted array of DeclIDs in a module.
       FILE_SORTED_DECLS = 42,
-      
+
       /// \brief Record code for an array of all of the (sub)modules that were
       /// imported by the AST file.
       IMPORTED_MODULES = 43,
-      
+
       // ID 44 used to be a table of merged canonical declarations.
       // ID 45 used to be a list of declaration IDs of local redeclarations.
-      
+
       /// \brief Record code for the array of Objective-C categories (including
       /// extensions).
       ///
@@ -585,6 +585,12 @@ namespace clang {
       /// \brief Number of unmatched #pragma clang cuda_force_host_device begin
       /// directives we've seen.
       CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57,
+
+      /// \brief Record code for types associated with OpenCL extensions.
+      OPENCL_EXTENSION_TYPES = 58,
+
+      /// \brief Record code for declarations associated with OpenCL extensions.
+      OPENCL_EXTENSION_DECLS = 59,
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Fri Dec 16 13:22:08 2016
@@ -807,7 +807,13 @@ private:
   SourceLocation PointersToMembersPragmaLocation;
 
   /// \brief The OpenCL extension settings.
-  SmallVector<uint64_t, 1> OpenCLExtensions;
+  OpenCLOptions OpenCLExtensions;
+
+  /// \brief Extensions required by an OpenCL type.
+  llvm::DenseMap<const Type *, std::set<std::string>> OpenCLTypeExtMap;
+
+  /// \brief Extensions required by an OpenCL declaration.
+  llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap;
 
   /// \brief A list of the namespaces we've seen.
   SmallVector<uint64_t, 4> KnownNamespaces;

Modified: cfe/trunk/include/clang/Serialization/ASTWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTWriter.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTWriter.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTWriter.h Fri Dec 16 13:22:08 2016
@@ -459,6 +459,8 @@ private:
   void WriteDeclContextVisibleUpdate(const DeclContext *DC);
   void WriteFPPragmaOptions(const FPOptions &Opts);
   void WriteOpenCLExtensions(Sema &SemaRef);
+  void WriteOpenCLExtensionTypes(Sema &SemaRef);
+  void WriteOpenCLExtensionDecls(Sema &SemaRef);
   void WriteCUDAPragmas(Sema &SemaRef);
   void WriteObjCCategories();
   void WriteLateParsedTemplates(Sema &SemaRef);

Modified: cfe/trunk/lib/Basic/Targets.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Targets.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Targets.cpp (original)
+++ cfe/trunk/lib/Basic/Targets.cpp Fri Dec 16 13:22:08 2016
@@ -1924,16 +1924,16 @@ public:
   }
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.cl_clang_storage_class_specifiers = 1;
-    Opts.cl_khr_gl_sharing = 1;
-    Opts.cl_khr_icd = 1;
-
-    Opts.cl_khr_fp64 = 1;
-    Opts.cl_khr_byte_addressable_store = 1;
-    Opts.cl_khr_global_int32_base_atomics = 1;
-    Opts.cl_khr_global_int32_extended_atomics = 1;
-    Opts.cl_khr_local_int32_base_atomics = 1;
-    Opts.cl_khr_local_int32_extended_atomics = 1;
+    Opts.support("cl_clang_storage_class_specifiers");
+    Opts.support("cl_khr_gl_sharing");
+    Opts.support("cl_khr_icd");
+
+    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");
   }
 };
 
@@ -2208,27 +2208,27 @@ public:
 
   void setSupportedOpenCLOpts() override {
     auto &Opts = getSupportedOpenCLOpts();
-    Opts.cl_clang_storage_class_specifiers = 1;
-    Opts.cl_khr_icd = 1;
+    Opts.support("cl_clang_storage_class_specifiers");
+    Opts.support("cl_khr_icd");
 
     if (hasFP64)
-      Opts.cl_khr_fp64 = 1;
+      Opts.support("cl_khr_fp64");
     if (GPU >= GK_EVERGREEN) {
-      Opts.cl_khr_byte_addressable_store = 1;
-      Opts.cl_khr_global_int32_base_atomics = 1;
-      Opts.cl_khr_global_int32_extended_atomics = 1;
-      Opts.cl_khr_local_int32_base_atomics = 1;
-      Opts.cl_khr_local_int32_extended_atomics = 1;
+      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");
     }
     if (GPU >= GK_GFX6) {
-      Opts.cl_khr_fp16 = 1;
-      Opts.cl_khr_int64_base_atomics = 1;
-      Opts.cl_khr_int64_extended_atomics = 1;
-      Opts.cl_khr_mipmap_image = 1;
-      Opts.cl_khr_subgroups = 1;
-      Opts.cl_khr_3d_image_writes = 1;
-      Opts.cl_amd_media_ops = 1;
-      Opts.cl_amd_media_ops2 = 1;
+      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_subgroups");
+      Opts.support("cl_khr_3d_image_writes");
+      Opts.support("cl_amd_media_ops");
+      Opts.support("cl_amd_media_ops2");
     }
   }
 
@@ -2932,7 +2932,7 @@ public:
   }
 
   void setSupportedOpenCLOpts() override {
-    getSupportedOpenCLOpts().setAll();
+    getSupportedOpenCLOpts().supportAll();
   }
 };
 
@@ -8188,7 +8188,7 @@ public:
   void setSupportedOpenCLOpts() override {
     // Assume all OpenCL extensions and optional core features are supported
     // for SPIR since it is a generic target.
-    getSupportedOpenCLOpts().setAll();
+    getSupportedOpenCLOpts().supportAll();
   }
 };
 

Modified: cfe/trunk/lib/Frontend/InitPreprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitPreprocessor.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/InitPreprocessor.cpp (original)
+++ cfe/trunk/lib/Frontend/InitPreprocessor.cpp Fri Dec 16 13:22:08 2016
@@ -988,7 +988,7 @@ static void InitializePredefinedMacros(c
   // OpenCL definitions.
   if (LangOpts.OpenCL) {
 #define OPENCLEXT(Ext) \
-    if (TI.getSupportedOpenCLOpts().is_##Ext##_supported( \
+    if (TI.getSupportedOpenCLOpts().isSupported(#Ext, \
         LangOpts.OpenCLVersion)) \
       Builder.defineMacro(#Ext);
 #include "clang/Basic/OpenCLExtensions.def"

Modified: cfe/trunk/lib/Headers/opencl-c.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/opencl-c.h?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/opencl-c.h (original)
+++ cfe/trunk/lib/Headers/opencl-c.h Fri Dec 16 13:22:08 2016
@@ -15490,6 +15490,10 @@ int printf(__constant const char* st, ..
 #define CLK_FILTER_NEAREST              0x10
 #define CLK_FILTER_LINEAR               0x20
 
+#ifdef cl_khr_gl_msaa_sharing
+#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
+#endif //cl_khr_gl_msaa_sharing
+
 /**
  * Use the coordinate (coord.xy) to do an element lookup in
  * the 2D image object specified by image.

Modified: cfe/trunk/lib/Parse/ParsePragma.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParsePragma.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParsePragma.cpp (original)
+++ cfe/trunk/lib/Parse/ParsePragma.cpp Fri Dec 16 13:22:08 2016
@@ -486,42 +486,48 @@ StmtResult Parser::HandlePragmaCaptured(
 }
 
 namespace {
-  typedef llvm::PointerIntPair<IdentifierInfo *, 1, bool> OpenCLExtData;
+  enum OpenCLExtState : char {
+    Disable, Enable, Begin, End
+  };
+  typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
 }
 
 void Parser::HandlePragmaOpenCLExtension() {
   assert(Tok.is(tok::annot_pragma_opencl_extension));
-  OpenCLExtData data =
-      OpenCLExtData::getFromOpaqueValue(Tok.getAnnotationValue());
-  unsigned state = data.getInt();
-  IdentifierInfo *ename = data.getPointer();
+  OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
+  auto State = Data->second;
+  auto Ident = Data->first;
   SourceLocation NameLoc = Tok.getLocation();
   ConsumeToken(); // The annotation token.
 
-  OpenCLOptions &f = Actions.getOpenCLOptions();
-  auto CLVer = getLangOpts().OpenCLVersion;
-  auto &Supp = getTargetInfo().getSupportedOpenCLOpts();
+  auto &Opt = Actions.getOpenCLOptions();
+  auto Name = Ident->getName();
   // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
   // overriding all previously issued extension directives, but only if the
   // behavior is set to disable."
-  if (state == 0 && ename->isStr("all")) {
-#define OPENCLEXT(nm) \
-    if (Supp.is_##nm##_supported_extension(CLVer)) \
-      f.nm = 0;
-#include "clang/Basic/OpenCLExtensions.def"
-  }
-#define OPENCLEXT(nm) else if (ename->isStr(#nm)) \
-   if (Supp.is_##nm##_supported_extension(CLVer)) \
-     f.nm = state; \
-   else if (Supp.is_##nm##_supported_core(CLVer)) \
-     PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << ename; \
-   else \
-     PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << ename;
-#include "clang/Basic/OpenCLExtensions.def"
-  else {
-    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << ename;
-    return;
-  }
+  if (Name == "all") {
+    if (State == Disable)
+      Opt.disableAll();
+    else
+      PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
+  } else if (State == Begin) {
+    if (!Opt.isKnown(Name) ||
+        !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) {
+      Opt.support(Name);
+    }
+    Actions.setCurrentOpenCLExtension(Name);
+  } else if (State == End) {
+    if (Name != Actions.getCurrentOpenCLExtension())
+      PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
+    Actions.setCurrentOpenCLExtension("");
+  } else if (!Opt.isKnown(Name))
+    PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
+  else if (Opt.isSupportedExtension(Name, getLangOpts().OpenCLVersion))
+    Opt.enable(Name, State == Enable);
+  else if (Opt.isSupportedCore(Name, getLangOpts().OpenCLVersion))
+    PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
+  else
+    PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
 }
 
 void Parser::HandlePragmaMSPointersToMembers() {
@@ -1441,29 +1447,34 @@ PragmaOpenCLExtensionHandler::HandlePrag
       "OPENCL";
     return;
   }
-  IdentifierInfo *ename = Tok.getIdentifierInfo();
+  IdentifierInfo *Ext = Tok.getIdentifierInfo();
   SourceLocation NameLoc = Tok.getLocation();
 
   PP.Lex(Tok);
   if (Tok.isNot(tok::colon)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << ename;
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
     return;
   }
 
   PP.Lex(Tok);
   if (Tok.isNot(tok::identifier)) {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
     return;
   }
-  IdentifierInfo *op = Tok.getIdentifierInfo();
+  IdentifierInfo *Pred = Tok.getIdentifierInfo();
 
-  unsigned state;
-  if (op->isStr("enable")) {
-    state = 1;
-  } else if (op->isStr("disable")) {
-    state = 0;
-  } else {
-    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable);
+  OpenCLExtState State;
+  if (Pred->isStr("enable")) {
+    State = Enable;
+  } else if (Pred->isStr("disable")) {
+    State = Disable;
+  } else if (Pred->isStr("begin"))
+    State = Begin;
+  else if (Pred->isStr("end"))
+    State = End;
+  else {
+    PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
+      << Ext->isStr("all");
     return;
   }
   SourceLocation StateLoc = Tok.getLocation();
@@ -1475,19 +1486,21 @@ PragmaOpenCLExtensionHandler::HandlePrag
     return;
   }
 
-  OpenCLExtData data(ename, state);
+  auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
+  Info->first = Ext;
+  Info->second = State;
   MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
                               1);
   Toks[0].startToken();
   Toks[0].setKind(tok::annot_pragma_opencl_extension);
   Toks[0].setLocation(NameLoc);
-  Toks[0].setAnnotationValue(data.getOpaqueValue());
+  Toks[0].setAnnotationValue(static_cast<void*>(Info));
   Toks[0].setAnnotationEndLoc(StateLoc);
   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true);
 
   if (PP.getPPCallbacks())
-    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, ename, 
-                                               StateLoc, state);
+    PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext, 
+                                               StateLoc, State);
 }
 
 /// \brief Handle '#pragma omp ...' when OpenMP is disabled.

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Fri Dec 16 13:22:08 2016
@@ -934,6 +934,8 @@ Parser::ParseDeclOrFunctionDefInternal(P
     Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS_none,
                                                        DS, AnonRecord);
     DS.complete(TheDecl);
+    if (getLangOpts().OpenCL)
+      Actions.setCurrentOpenCLExtensionForDecl(TheDecl);
     if (AnonRecord) {
       Decl* decls[] = {AnonRecord, TheDecl};
       return Actions.BuildDeclaratorGroup(decls, /*TypeMayContainAuto=*/false);

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Fri Dec 16 13:22:08 2016
@@ -558,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema
   // OpenCL v1.2 s6.8 changes this to "The auto and register storage-class
   // specifiers are not supported."
   if (S.getLangOpts().OpenCL &&
-      !S.getOpenCLOptions().cl_clang_storage_class_specifiers) {
+      !S.getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers")) {
     switch (SC) {
     case SCS_extern:
     case SCS_private_extern:

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Dec 16 13:22:08 2016
@@ -207,14 +207,11 @@ void Sema::Initialize() {
     addImplicitTypedef("size_t", Context.getSizeType());
   }
 
-  // Initialize predefined OpenCL types and supported optional core features.
+  // Initialize predefined OpenCL types and supported extensions and (optional)
+  // core features.
   if (getLangOpts().OpenCL) {
-#define OPENCLEXT(Ext) \
-     if (Context.getTargetInfo().getSupportedOpenCLOpts().is_##Ext##_supported_core( \
-         getLangOpts().OpenCLVersion)) \
-       getOpenCLOptions().Ext = 1;
-#include "clang/Basic/OpenCLExtensions.def"
-
+    getOpenCLOptions().addSupport(Context.getTargetInfo().getSupportedOpenCLOpts());
+    getOpenCLOptions().enableSupportedCore(getLangOpts().OpenCLVersion);
     addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
     addImplicitTypedef("event_t", Context.OCLEventTy);
     if (getLangOpts().OpenCLVersion >= 200) {
@@ -225,26 +222,60 @@ void Sema::Initialize() {
       addImplicitTypedef("atomic_int", Context.getAtomicType(Context.IntTy));
       addImplicitTypedef("atomic_uint",
                          Context.getAtomicType(Context.UnsignedIntTy));
-      addImplicitTypedef("atomic_long", Context.getAtomicType(Context.LongTy));
-      addImplicitTypedef("atomic_ulong",
-                         Context.getAtomicType(Context.UnsignedLongTy));
+      auto AtomicLongT = Context.getAtomicType(Context.LongTy);
+      addImplicitTypedef("atomic_long", AtomicLongT);
+      auto AtomicULongT = Context.getAtomicType(Context.UnsignedLongTy);
+      addImplicitTypedef("atomic_ulong", AtomicULongT);
       addImplicitTypedef("atomic_float",
                          Context.getAtomicType(Context.FloatTy));
-      addImplicitTypedef("atomic_double",
-                         Context.getAtomicType(Context.DoubleTy));
+      auto AtomicDoubleT = Context.getAtomicType(Context.DoubleTy);
+      addImplicitTypedef("atomic_double", AtomicDoubleT);
       // OpenCLC v2.0, s6.13.11.6 requires that atomic_flag is implemented as
       // 32-bit integer and OpenCLC v2.0, s6.1.1 int is always 32-bit wide.
       addImplicitTypedef("atomic_flag", Context.getAtomicType(Context.IntTy));
-      addImplicitTypedef("atomic_intptr_t",
-                         Context.getAtomicType(Context.getIntPtrType()));
-      addImplicitTypedef("atomic_uintptr_t",
-                         Context.getAtomicType(Context.getUIntPtrType()));
-      addImplicitTypedef("atomic_size_t",
-                         Context.getAtomicType(Context.getSizeType()));
-      addImplicitTypedef("atomic_ptrdiff_t",
-                         Context.getAtomicType(Context.getPointerDiffType()));
+      auto AtomicIntPtrT = Context.getAtomicType(Context.getIntPtrType());
+      addImplicitTypedef("atomic_intptr_t", AtomicIntPtrT);
+      auto AtomicUIntPtrT = Context.getAtomicType(Context.getUIntPtrType());
+      addImplicitTypedef("atomic_uintptr_t", AtomicUIntPtrT);
+      auto AtomicSizeT = Context.getAtomicType(Context.getSizeType());
+      addImplicitTypedef("atomic_size_t", AtomicSizeT);
+      auto AtomicPtrDiffT = Context.getAtomicType(Context.getPointerDiffType());
+      addImplicitTypedef("atomic_ptrdiff_t", AtomicPtrDiffT);
+
+      // OpenCL v2.0 s6.13.11.6:
+      // - The atomic_long and atomic_ulong types are supported if the
+      //   cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics
+      //   extensions are supported.
+      // - The atomic_double type is only supported if double precision
+      //   is supported and the cl_khr_int64_base_atomics and
+      //   cl_khr_int64_extended_atomics extensions are supported.
+      // - If the device address space is 64-bits, the data types
+      //   atomic_intptr_t, atomic_uintptr_t, atomic_size_t and
+      //   atomic_ptrdiff_t are supported if the cl_khr_int64_base_atomics and
+      //   cl_khr_int64_extended_atomics extensions are supported.
+      std::vector<QualType> Atomic64BitTypes;
+      Atomic64BitTypes.push_back(AtomicLongT);
+      Atomic64BitTypes.push_back(AtomicULongT);
+      Atomic64BitTypes.push_back(AtomicDoubleT);
+      if (Context.getTypeSize(AtomicSizeT) == 64) {
+        Atomic64BitTypes.push_back(AtomicSizeT);
+        Atomic64BitTypes.push_back(AtomicIntPtrT);
+        Atomic64BitTypes.push_back(AtomicUIntPtrT);
+        Atomic64BitTypes.push_back(AtomicPtrDiffT);
+      }
+      for (auto &I : Atomic64BitTypes)
+        setOpenCLExtensionForType(I,
+            "cl_khr_int64_base_atomics cl_khr_int64_extended_atomics");
+
+      setOpenCLExtensionForType(AtomicDoubleT, "cl_khr_fp64");
     }
-  }
+
+    setOpenCLExtensionForType(Context.DoubleTy, "cl_khr_fp64");
+
+#define GENERIC_IMAGE_TYPE_EXT(Type, Id, Ext) \
+    setOpenCLExtensionForType(Context.Id, Ext);
+#include "clang/Basic/OpenCLImageTypes.def"
+    };
 
   if (Context.getTargetInfo().hasBuiltinMSVaList()) {
     DeclarationName MSVaList = &Context.Idents.get("__builtin_ms_va_list");
@@ -1542,3 +1573,85 @@ const llvm::MapVector<FieldDecl *, Sema:
 Sema::getMismatchingDeleteExpressions() const {
   return DeleteExprs;
 }
+
+void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) {
+  if (ExtStr.empty())
+    return;
+  llvm::SmallVector<StringRef, 1> Exts;
+  ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+  auto CanT = T.getCanonicalType().getTypePtr();
+  for (auto &I : Exts)
+    OpenCLTypeExtMap[CanT].insert(I.str());
+}
+
+void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) {
+  llvm::SmallVector<StringRef, 1> Exts;
+  ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false);
+  if (Exts.empty())
+    return;
+  for (auto &I : Exts)
+    OpenCLDeclExtMap[FD].insert(I.str());
+}
+
+void Sema::setCurrentOpenCLExtensionForType(QualType T) {
+  if (CurrOpenCLExtension.empty())
+    return;
+  setOpenCLExtensionForType(T, CurrOpenCLExtension);
+}
+
+void Sema::setCurrentOpenCLExtensionForDecl(Decl *D) {
+  if (CurrOpenCLExtension.empty())
+    return;
+  setOpenCLExtensionForDecl(D, CurrOpenCLExtension);
+}
+
+bool Sema::isOpenCLDisabledDecl(Decl *FD) {
+  auto Loc = OpenCLDeclExtMap.find(FD);
+  if (Loc == OpenCLDeclExtMap.end())
+    return false;
+  for (auto &I : Loc->second) {
+    if (!getOpenCLOptions().isEnabled(I))
+      return true;
+  }
+  return false;
+}
+
+template <typename T, typename DiagLocT, typename DiagInfoT, typename MapT>
+bool Sema::checkOpenCLDisabledTypeOrDecl(T D, DiagLocT DiagLoc,
+                                         DiagInfoT DiagInfo, MapT &Map,
+                                         unsigned Selector,
+                                         SourceRange SrcRange) {
+  auto Loc = Map.find(D);
+  if (Loc == Map.end())
+    return false;
+  bool Disabled = false;
+  for (auto &I : Loc->second) {
+    if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) {
+      Diag(DiagLoc, diag::err_opencl_requires_extension) << Selector << DiagInfo
+                                                         << I << SrcRange;
+      Disabled = true;
+    }
+  }
+  return Disabled;
+}
+
+bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) {
+  // Check extensions for declared types.
+  Decl *Decl = nullptr;
+  if (auto TypedefT = dyn_cast<TypedefType>(QT.getTypePtr()))
+    Decl = TypedefT->getDecl();
+  if (auto TagT = dyn_cast<TagType>(QT.getCanonicalType().getTypePtr()))
+    Decl = TagT->getDecl();
+  auto Loc = DS.getTypeSpecTypeLoc();
+  if (checkOpenCLDisabledTypeOrDecl(Decl, Loc, QT, OpenCLDeclExtMap))
+    return true;
+
+  // Check extensions for builtin types.
+  return checkOpenCLDisabledTypeOrDecl(QT.getCanonicalType().getTypePtr(), Loc,
+                                       QT, OpenCLTypeExtMap);
+}
+
+bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) {
+  return checkOpenCLDisabledTypeOrDecl(&D, E.getLocStart(), "",
+                                       OpenCLDeclExtMap, 1, D.getSourceRange());
+}

Modified: cfe/trunk/lib/Sema/SemaCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCast.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCast.cpp Fri Dec 16 13:22:08 2016
@@ -2529,7 +2529,8 @@ void CastOperation::CheckCStyleCast() {
     }
   }
 
-  if (Self.getLangOpts().OpenCL && !Self.getOpenCLOptions().cl_khr_fp16) {
+  if (Self.getLangOpts().OpenCL &&
+      !Self.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
     if (DestType->isHalfType()) {
       Self.Diag(SrcExpr.get()->getLocStart(), diag::err_opencl_cast_to_half)
         << DestType << SrcExpr.get()->getSourceRange();

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 16 13:22:08 2016
@@ -4838,6 +4838,9 @@ Decl *Sema::ActOnDeclarator(Scope *S, De
       Dcl && Dcl->getDeclContext()->isFileContext())
     Dcl->setTopLevelDeclInObjCContainer();
 
+  if (getLangOpts().OpenCL)
+    setCurrentOpenCLExtensionForDecl(Dcl);
+
   return Dcl;
 }
 
@@ -5939,7 +5942,7 @@ NamedDecl *Sema::ActOnVariableDeclarator
       NR = NR->getPointeeType();
     }
 
-    if (!getOpenCLOptions().cl_khr_fp16) {
+    if (!getOpenCLOptions().isEnabled("cl_khr_fp16")) {
       // OpenCL v1.2 s6.1.1.1: reject declaring variables of the half and
       // half array type (unless the cl_khr_fp16 extension is enabled).
       if (Context.getBaseElementType(R)->isHalfType()) {
@@ -6909,7 +6912,7 @@ void Sema::CheckVariableDeclarationType(
   // OpenCL v1.2 s6.8 - The static qualifier is valid only in program
   // scope.
   if (getLangOpts().OpenCLVersion == 120 &&
-      !getOpenCLOptions().cl_clang_storage_class_specifiers &&
+      !getOpenCLOptions().isEnabled("cl_clang_storage_class_specifiers") &&
       NewVD->isStaticLocal()) {
     Diag(NewVD->getLocation(), diag::err_static_function_scope);
     NewVD->setInvalidDecl();
@@ -7617,7 +7620,7 @@ static OpenCLParamType getOpenCLKernelPa
   // OpenCL extension spec v1.2 s9.5:
   // This extension adds support for half scalar and vector types as built-in
   // types that can be used for arithmetic operations, conversions etc.
-  if (!S.getOpenCLOptions().cl_khr_fp16 && PT->isHalfType())
+  if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16") && PT->isHalfType())
     return InvalidKernelParam;
 
   if (PT->isRecordType())

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Dec 16 13:22:08 2016
@@ -657,7 +657,7 @@ ExprResult Sema::DefaultLvalueConversion
     return E;
 
   // OpenCL usually rejects direct accesses to values of 'half' type.
-  if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+  if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
       T->isHalfType()) {
     Diag(E->getExprLoc(), diag::err_opencl_half_load_store)
       << 0 << T;
@@ -819,7 +819,7 @@ ExprResult Sema::DefaultArgumentPromotio
   if (BTy && (BTy->getKind() == BuiltinType::Half ||
               BTy->getKind() == BuiltinType::Float)) {
     if (getLangOpts().OpenCL &&
-        !(getOpenCLOptions().cl_khr_fp64)) {
+        !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
         if (BTy->getKind() == BuiltinType::Half) {
             E = ImpCastExprToType(E, Context.FloatTy, CK_FloatingCast).get();
         }
@@ -3386,7 +3386,7 @@ ExprResult Sema::ActOnNumericConstant(co
   if (Literal.isFloatingLiteral()) {
     QualType Ty;
     if (Literal.isHalf){
-      if (getOpenCLOptions().cl_khr_fp16)
+      if (getOpenCLOptions().isEnabled("cl_khr_fp16"))
         Ty = Context.HalfTy;
       else {
         Diag(Tok.getLocation(), diag::err_half_const_requires_fp16);
@@ -3410,7 +3410,7 @@ ExprResult Sema::ActOnNumericConstant(co
           Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
         }
       } else if (getLangOpts().OpenCL &&
-                 !(getOpenCLOptions().cl_khr_fp64)) {
+                 !getOpenCLOptions().isEnabled("cl_khr_fp64")) {
         // Impose single-precision float type when cl_khr_fp64 is not enabled.
         Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64);
         Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get();
@@ -5289,6 +5289,9 @@ ExprResult Sema::ActOnCallExpr(Scope *Sc
                                            Fn->getLocStart()))
       return ExprError();
 
+    if (getLangOpts().OpenCL && checkOpenCLDisabledDecl(*FD, *Fn))
+      return ExprError();
+    
     // CheckEnableIf assumes that the we're passing in a sane number of args for
     // FD, but that doesn't always hold true here. This is because, in some
     // cases, we'll emit a diag about an ill-formed function call, but then
@@ -10186,7 +10189,7 @@ QualType Sema::CheckAssignmentOperands(E
   // OpenCL v1.2 s6.1.1.1 p2:
   // The half data type can only be used to declare a pointer to a buffer that
   // contains half values
-  if (getLangOpts().OpenCL && !getOpenCLOptions().cl_khr_fp16 &&
+  if (getLangOpts().OpenCL && !getOpenCLOptions().isEnabled("cl_khr_fp16") &&
     LHSType->isHalfType()) {
     Diag(Loc, diag::err_opencl_half_load_store) << 1
         << LHSType.getUnqualifiedType();

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Dec 16 13:22:08 2016
@@ -5949,6 +5949,12 @@ Sema::AddOverloadCandidate(FunctionDecl
     Candidate.DeductionFailure.Data = FailedAttr;
     return;
   }
+
+  if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) {
+    Candidate.Viable = false;
+    Candidate.FailureKind = ovl_fail_ext_disabled;
+    return;
+  }
 }
 
 ObjCMethodDecl *
@@ -9798,6 +9804,13 @@ static void DiagnoseFailedEnableIfAttr(S
       << Attr->getCond()->getSourceRange() << Attr->getMessage();
 }
 
+static void DiagnoseOpenCLExtensionDisabled(Sema &S, OverloadCandidate *Cand) {
+  FunctionDecl *Callee = Cand->Function;
+
+  S.Diag(Callee->getLocation(),
+         diag::note_ovl_candidate_disabled_by_extension);
+}
+
 /// Generates a 'note' diagnostic for an overload candidate.  We've
 /// already generated a primary error at the call site.
 ///
@@ -9875,6 +9888,9 @@ static void NoteFunctionCandidate(Sema &
   case ovl_fail_enable_if:
     return DiagnoseFailedEnableIfAttr(S, Cand);
 
+  case ovl_fail_ext_disabled:
+    return DiagnoseOpenCLExtensionDisabled(S, Cand);
+
   case ovl_fail_addr_not_available: {
     bool Available = checkAddressOfCandidateIsAvailable(S, Cand->Function);
     (void)Available;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Dec 16 13:22:08 2016
@@ -1401,13 +1401,6 @@ static QualType ConvertDeclSpecToType(Ty
       Result = Context.LongDoubleTy;
     else
       Result = Context.DoubleTy;
-
-    if (S.getLangOpts().OpenCL &&
-        !(S.getOpenCLOptions().cl_khr_fp64)) {
-      S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
-          << Result << "cl_khr_fp64";
-      declarator.setInvalidType(true);
-    }
     break;
   case DeclSpec::TST_float128:
     if (!S.Context.getTargetInfo().hasFloat128Type())
@@ -1459,48 +1452,6 @@ static QualType ConvertDeclSpecToType(Ty
     Result = S.GetTypeFromParser(DS.getRepAsType());
     if (Result.isNull()) {
       declarator.setInvalidType(true);
-    } else if (S.getLangOpts().OpenCL) {
-      if (Result->getAs<AtomicType>()) {
-        StringRef TypeName = Result.getBaseTypeIdentifier()->getName();
-        bool NoExtTypes =
-            llvm::StringSwitch<bool>(TypeName)
-                .Cases("atomic_int", "atomic_uint", "atomic_float",
-                       "atomic_flag", true)
-                .Default(false);
-        if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) {
-          S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
-              << Result << "cl_khr_int64_base_atomics";
-          declarator.setInvalidType(true);
-        }
-        if (!S.getOpenCLOptions().cl_khr_int64_extended_atomics &&
-            !NoExtTypes) {
-          S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
-              << Result << "cl_khr_int64_extended_atomics";
-          declarator.setInvalidType(true);
-        }
-        if (!S.getOpenCLOptions().cl_khr_fp64 &&
-            !TypeName.compare("atomic_double")) {
-          S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
-              << Result << "cl_khr_fp64";
-          declarator.setInvalidType(true);
-        }
-      } else if (!S.getOpenCLOptions().cl_khr_gl_msaa_sharing &&
-                 (Result->isOCLImage2dArrayMSAADepthROType() ||
-                  Result->isOCLImage2dArrayMSAADepthWOType() ||
-                  Result->isOCLImage2dArrayMSAADepthRWType() ||
-                  Result->isOCLImage2dArrayMSAAROType() ||
-                  Result->isOCLImage2dArrayMSAARWType() ||
-                  Result->isOCLImage2dArrayMSAAWOType() ||
-                  Result->isOCLImage2dMSAADepthROType() ||
-                  Result->isOCLImage2dMSAADepthRWType() ||
-                  Result->isOCLImage2dMSAADepthWOType() ||
-                  Result->isOCLImage2dMSAAROType() ||
-                  Result->isOCLImage2dMSAARWType() ||
-                  Result->isOCLImage2dMSAAWOType())) {
-        S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension)
-            << Result << "cl_khr_gl_msaa_sharing";
-        declarator.setInvalidType(true);
-      }
     }
 
     // TypeQuals handled by caller.
@@ -1636,6 +1587,10 @@ static QualType ConvertDeclSpecToType(Ty
     break;
   }
 
+  if (S.getLangOpts().OpenCL &&
+      S.checkOpenCLDisabledTypeDeclSpec(DS, Result))
+    declarator.setInvalidType(true);
+
   // Handle complex types.
   if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
     if (S.getLangOpts().Freestanding)
@@ -4185,7 +4140,7 @@ static TypeSourceInfo *GetFullTypeForDec
       // FIXME: This really should be in BuildFunctionType.
       if (T->isHalfType()) {
         if (S.getLangOpts().OpenCL) {
-          if (!S.getOpenCLOptions().cl_khr_fp16) {
+          if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
             S.Diag(D.getIdentifierLoc(), diag::err_opencl_invalid_return)
                 << T << 0 /*pointer hint*/;
             D.setInvalidType(true);
@@ -4418,7 +4373,7 @@ static TypeSourceInfo *GetFullTypeForDec
             // Disallow half FP parameters.
             // FIXME: This really should be in BuildFunctionType.
             if (S.getLangOpts().OpenCL) {
-              if (!S.getOpenCLOptions().cl_khr_fp16) {
+              if (!S.getOpenCLOptions().isEnabled("cl_khr_fp16")) {
                 S.Diag(Param->getLocation(),
                   diag::err_opencl_half_param) << ParamTy;
                 D.setInvalidType();

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Fri Dec 16 13:22:08 2016
@@ -3164,8 +3164,38 @@ ASTReader::ReadASTBlock(ModuleFile &F, u
       break;
 
     case OPENCL_EXTENSIONS:
-      // Later tables overwrite earlier ones.
-      OpenCLExtensions.swap(Record);
+      for (unsigned I = 0, E = Record.size(); I != E; ) {
+        auto Name = ReadString(Record, I);
+        OpenCLExtensions.OptMap[Name] = {
+            static_cast<bool>(Record[I++]) /* Supported */,
+            static_cast<bool>(Record[I++]) /* Enabled */,
+            static_cast<unsigned>(Record[I++]) /* Avail */,
+            static_cast<unsigned>(Record[I++]) /* Core */};
+      }
+      break;
+
+    case OPENCL_EXTENSION_TYPES:
+      for (unsigned I = 0, E = Record.size(); I != E;) {
+        auto TypeID = static_cast<::TypeID>(Record[I++]);
+        auto *Type = GetType(TypeID).getTypePtr();
+        auto NumExt = static_cast<unsigned>(Record[I++]);
+        for (unsigned II = 0; II != NumExt; ++II) {
+          auto Ext = ReadString(Record, I);
+          OpenCLTypeExtMap[Type].insert(Ext);
+        }
+      }
+      break;
+
+    case OPENCL_EXTENSION_DECLS:
+      for (unsigned I = 0, E = Record.size(); I != E;) {
+        auto DeclID = static_cast<::DeclID>(Record[I++]);
+        auto *Decl = GetDecl(DeclID);
+        auto NumExt = static_cast<unsigned>(Record[I++]);
+        for (unsigned II = 0; II != NumExt; ++II) {
+          auto Ext = ReadString(Record, I);
+          OpenCLDeclExtMap[Decl].insert(Ext);
+        }
+      }
       break;
 
     case TENTATIVE_DEFINITIONS:
@@ -7091,14 +7121,9 @@ void ASTReader::InitializeSema(Sema &S)
     SemaObj->FPFeatures.fp_contract = FPPragmaOptions[0];
   }
 
-  // FIXME: What happens if these are changed by a module import?
-  if (!OpenCLExtensions.empty()) {
-    unsigned I = 0;
-#define OPENCLEXT(nm)  SemaObj->OpenCLFeatures.nm = OpenCLExtensions[I++];
-#include "clang/Basic/OpenCLExtensions.def"
-
-    assert(OpenCLExtensions.size() == I && "Wrong number of OPENCL_EXTENSIONS");
-  }
+  SemaObj->OpenCLFeatures.copy(OpenCLExtensions);
+  SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap;
+  SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap;
 
   UpdateSema();
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Dec 16 13:22:08 2016
@@ -1053,6 +1053,8 @@ void ASTWriter::WriteBlockInfoBlock() {
   RECORD(HEADER_SEARCH_TABLE);
   RECORD(FP_PRAGMA_OPTIONS);
   RECORD(OPENCL_EXTENSIONS);
+  RECORD(OPENCL_EXTENSION_TYPES);
+  RECORD(OPENCL_EXTENSION_DECLS);
   RECORD(DELEGATING_CTORS);
   RECORD(KNOWN_NAMESPACES);
   RECORD(MODULE_OFFSET_MAP);
@@ -3939,11 +3941,46 @@ void ASTWriter::WriteOpenCLExtensions(Se
 
   const OpenCLOptions &Opts = SemaRef.getOpenCLOptions();
   RecordData Record;
-#define OPENCLEXT(nm)  Record.push_back(Opts.nm);
-#include "clang/Basic/OpenCLExtensions.def"
+  for (const auto &I:Opts.OptMap) {
+    AddString(I.getKey(), Record);
+    auto V = I.getValue();
+    Record.push_back(V.Supported);
+    Record.push_back(V.Enabled);
+    Record.push_back(V.Avail);
+    Record.push_back(V.Core);
+  }
   Stream.EmitRecord(OPENCL_EXTENSIONS, Record);
 }
 
+void ASTWriter::WriteOpenCLExtensionTypes(Sema &SemaRef) {
+  if (!SemaRef.Context.getLangOpts().OpenCL)
+    return;
+
+  RecordData Record;
+  for (const auto &I : SemaRef.OpenCLTypeExtMap) {
+    Record.push_back(
+        static_cast<unsigned>(getTypeID(I.first->getCanonicalTypeInternal())));
+    Record.push_back(I.second.size());
+    for (auto Ext : I.second)
+      AddString(Ext, Record);
+  }
+  Stream.EmitRecord(OPENCL_EXTENSION_TYPES, Record);
+}
+
+void ASTWriter::WriteOpenCLExtensionDecls(Sema &SemaRef) {
+  if (!SemaRef.Context.getLangOpts().OpenCL)
+    return;
+
+  RecordData Record;
+  for (const auto &I : SemaRef.OpenCLDeclExtMap) {
+    Record.push_back(getDeclID(I.first));
+    Record.push_back(static_cast<unsigned>(I.second.size()));
+    for (auto Ext : I.second)
+      AddString(Ext, Record);
+  }
+  Stream.EmitRecord(OPENCL_EXTENSION_DECLS, Record);
+}
+
 void ASTWriter::WriteCUDAPragmas(Sema &SemaRef) {
   if (SemaRef.ForceCUDAHostDeviceDepth > 0) {
     RecordData::value_type Record[] = {SemaRef.ForceCUDAHostDeviceDepth};
@@ -4628,6 +4665,8 @@ uint64_t ASTWriter::WriteASTCore(Sema &S
   WriteIdentifierTable(PP, SemaRef.IdResolver, isModule);
   WriteFPPragmaOptions(SemaRef.getFPOptions());
   WriteOpenCLExtensions(SemaRef);
+  WriteOpenCLExtensionTypes(SemaRef);
+  WriteOpenCLExtensionDecls(SemaRef);
   WriteCUDAPragmas(SemaRef);
   WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule);
 

Added: cfe/trunk/test/CodeGenOpenCL/extension-begin.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenOpenCL/extension-begin.cl?rev=289979&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenOpenCL/extension-begin.cl (added)
+++ cfe/trunk/test/CodeGenOpenCL/extension-begin.cl Fri Dec 16 13:22:08 2016
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 %s -triple spir-unknown-unknown -emit-llvm -o - | FileCheck %s
+
+__attribute__((overloadable)) void f(int x);
+
+#pragma OPENCL EXTENSION my_ext : begin
+
+__attribute__((overloadable)) void f(long x);
+
+#pragma OPENCL EXTENSION my_ext : end
+
+#pragma OPENCL EXTENSION my_ext : enable
+
+//CHECK: define spir_func void @test_f1(i64 %x)
+//CHECK: call spir_func void @_Z1fl(i64 %{{.*}})
+void test_f1(long x) {
+  f(x);
+}
+
+#pragma OPENCL EXTENSION my_ext : disable
+
+//CHECK: define spir_func void @test_f2(i64 %x)
+//CHECK: call spir_func void @_Z1fi(i32 %{{.*}})
+void test_f2(long x) {
+  f(x);
+}

Modified: cfe/trunk/test/Parser/opencl-atomics-cl20.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/opencl-atomics-cl20.cl?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/test/Parser/opencl-atomics-cl20.cl (original)
+++ cfe/trunk/test/Parser/opencl-atomics-cl20.cl Fri Dec 16 13:22:08 2016
@@ -1,5 +1,6 @@
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
+// RUN: %clang_cc1 %s -triple spir64-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -fsyntax-only -cl-std=CL2.0 -DCL20 -DEXT -Wpedantic-core-features
 
 #ifdef EXT
@@ -47,14 +48,16 @@ void atomic_types_test() {
 // expected-error at -28 {{use of type 'atomic_ulong' (aka '_Atomic(unsigned long)') requires cl_khr_int64_extended_atomics extension to be enabled}}
 // expected-error at -27 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_base_atomics extension to be enabled}}
 // expected-error at -28 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re at -27 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re at -28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re at -28 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re at -29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re at -29 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re at -30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
-// expected-error-re at -30 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
-// expected-error-re at -31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+#if __LP64__
+// expected-error-re at -28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re at -29 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re at -29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re at -30 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re at -30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re at -31 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+// expected-error-re at -31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}}
+// expected-error-re at -32 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}}
+#endif
 #endif
 
 #ifdef CL20

Modified: cfe/trunk/test/Parser/opencl-pragma.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/opencl-pragma.cl?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/test/Parser/opencl-pragma.cl (original)
+++ cfe/trunk/test/Parser/opencl-pragma.cl Fri Dec 16 13:22:08 2016
@@ -5,9 +5,9 @@
 #pragma OPENCL EXTENSION cl_no_such_extension : disable /* expected-warning {{unknown OpenCL extension 'cl_no_such_extension' - ignoring}} */
 
 #pragma OPENCL EXTENSION all : disable
-#pragma OPENCL EXTENSION all : enable /* expected-warning {{unknown OpenCL extension 'all' - ignoring}} */
+#pragma OPENCL EXTENSION all : enable /* expected-warning {{expected 'disable' - ignoring}} */
 
-#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable' or 'disable' - ignoring}} */
+#pragma OPENCL EXTENSION cl_khr_fp64 : on /* expected-warning {{expected 'enable', 'disable', 'begin' or 'end' - ignoring}} */
 
 #pragma OPENCL FP_CONTRACT ON
 #pragma OPENCL FP_CONTRACT OFF

Added: cfe/trunk/test/SemaOpenCL/extension-begin.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/extension-begin.cl?rev=289979&view=auto
==============================================================================
--- cfe/trunk/test/SemaOpenCL/extension-begin.cl (added)
+++ cfe/trunk/test/SemaOpenCL/extension-begin.cl Fri Dec 16 13:22:08 2016
@@ -0,0 +1,56 @@
+// Test this without pch.
+// RUN: %clang_cc1 %s -DHEADER -DHEADER_USER -triple spir-unknown-unknown -verify -pedantic -fsyntax-only
+
+// Test with pch.
+// RUN: %clang_cc1 %s -DHEADER -triple spir-unknown-unknown -emit-pch -o %t -verify -pedantic
+// RUN: %clang_cc1 %s -DHEADER_USER -triple spir-unknown-unknown -include-pch %t -fsyntax-only -verify -pedantic
+
+#if defined(HEADER) && !defined(INCLUDED)
+#define INCLUDED 
+
+#pragma OPENCL EXTENSION all : begin // expected-warning {{expected 'disable' - ignoring}}
+#pragma OPENCL EXTENSION all : end // expected-warning {{expected 'disable' - ignoring}}
+
+#pragma OPENCL EXTENSION my_ext : begin 
+
+struct A {
+  int a;
+};
+
+typedef struct A TypedefOfA;
+typedef const TypedefOfA* PointerOfA;
+
+void f(void);
+
+__attribute__((overloadable)) void g(long x);
+
+#pragma OPENCL EXTENSION my_ext : end
+#pragma OPENCL EXTENSION my_ext : end // expected-warning {{OpenCL extension end directive mismatches begin directive - ignoring}}
+
+__attribute__((overloadable)) void g(void);
+
+#endif // defined(HEADER) && !defined(INCLUDED)
+
+#ifdef HEADER_USER
+
+#pragma OPENCL EXTENSION my_ext : enable
+void test_f1(void) {
+  struct A test_A1;
+  f();
+  g(0);
+}
+
+#pragma OPENCL EXTENSION my_ext : disable 
+void test_f2(void) {
+  struct A test_A2; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
+  const struct A test_A_local; // expected-error {{use of type 'struct A' requires my_ext extension to be enabled}}
+  TypedefOfA test_typedef_A; // expected-error {{use of type 'TypedefOfA' (aka 'struct A') requires my_ext extension to be enabled}}
+  PointerOfA test_A_pointer; // expected-error {{use of type 'PointerOfA' (aka 'const struct A *') requires my_ext extension to be enabled}}
+  f(); // expected-error {{use of declaration requires my_ext extension to be enabled}}
+  g(0); // expected-error {{no matching function for call to 'g'}}
+        // expected-note at -26 {{candidate disabled due to OpenCL extension}}
+        // expected-note at -22 {{candidate function not viable: requires 0 arguments, but 1 was provided}}
+}
+
+#endif // HEADER_USER
+

Modified: cfe/trunk/test/SemaOpenCL/extensions.cl
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaOpenCL/extensions.cl?rev=289979&r1=289978&r2=289979&view=diff
==============================================================================
--- cfe/trunk/test/SemaOpenCL/extensions.cl (original)
+++ cfe/trunk/test/SemaOpenCL/extensions.cl Fri Dec 16 13:22:08 2016
@@ -22,8 +22,6 @@
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64 -cl-ext=+cl_khr_fp16 -cl-ext=-cl_khr_fp64 -DNOFP64
 // RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-ext=-all -cl-ext=+cl_khr_fp64,-cl_khr_fp64,+cl_khr_fp16 -DNOFP64
 
-
-
 #ifdef FP64
 // expected-no-diagnostics
 #endif




More information about the cfe-commits mailing list