Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -952,8 +952,10 @@ // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1]) def warn_pragma_expected_colon : Warning< "missing ':' after %0 - ignoring">, InGroup; -def warn_pragma_expected_enable_disable : Warning< - "expected 'enable' or 'disable' - ignoring">, InGroup; +def warn_pragma_expected_predicate : Warning< + "expected %select{'enable', 'disable', 'begin' or 'end'|'disable'}0 - ignoring">, InGroup; +def warn_pragma_begin_end_mismatch : Warning< + "OpenCL extension end directive mismatches begin directive - ignoring">, InGroup; def warn_pragma_unknown_extension : Warning< "unknown OpenCL extension %0 - ignoring">, InGroup; def warn_pragma_unsupported_extension : Warning< Index: include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- include/clang/Basic/DiagnosticSemaKinds.td +++ include/clang/Basic/DiagnosticSemaKinds.td @@ -3280,6 +3280,8 @@ "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">; @@ -7993,6 +7995,8 @@ def warn_opencl_attr_deprecated_ignored : Warning < "%0 attribute is deprecated and ignored in OpenCL version %1">, InGroup; + def err_decl_requires_extension : Error< + "use of declaration requires %0 extension to be enabled">; // OpenCL v2.0 s6.13.6 -- Builtin Pipe Functions def err_opencl_builtin_pipe_first_arg : Error< Index: include/clang/Basic/OpenCLImageTypes.def =================================================================== --- include/clang/Basic/OpenCLImageTypes.def +++ include/clang/Basic/OpenCLImageTypes.def @@ -7,76 +7,82 @@ // //===----------------------------------------------------------------------===// // 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) -#else +#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_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) -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_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) -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_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 #undef IMAGE_READ_TYPE #undef IMAGE_WRITE_TYPE -#undef IMAGE_READ_WRITE_TYPE \ No newline at end of file +#undef IMAGE_READ_WRITE_TYPE Index: include/clang/Basic/OpenCLOptions.h =================================================================== --- include/clang/Basic/OpenCLOptions.h +++ include/clang/Basic/OpenCLOptions.h @@ -15,49 +15,100 @@ #ifndef LLVM_CLANG_BASIC_OPENCLOPTIONS_H #define LLVM_CLANG_BASIC_OPENCLOPTIONS_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; // Options 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 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 all options. - void setAll() { -#define OPENCLEXT(nm) nm = 1; -#include "clang/Basic/OpenCLExtensions.def" + // Is supported OpenCL extension or (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 with OpenCL version \p OCLVer. -#define OPENCLEXT_INTERNAL(Ext, Avail, ...) \ - bool is_##Ext##_supported(unsigned OCLVer) const { \ - return Ext && OCLVer >= Avail; \ + // 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; } -#include "clang/Basic/OpenCLExtensions.def" + // 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); + } - // 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); \ + void enable(StringRef Ext, bool V = true) { + OptMap[Ext].Enabled = V; } -#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 support(StringRef Ext, bool V = true) { + OptMap[Ext].Supported = V; } + + OpenCLOptions(){ +#define OPENCLEXT_INTERNAL(Ext, AvailVer, CoreVer) \ + OptMap[#Ext].Avail = AvailVer; \ + OptMap[#Ext].Core = CoreVer; #include "clang/Basic/OpenCLExtensions.def" + } + + void addSupport(const OpenCLOptions &Opts) { + for (auto &I:Opts.OptMap) + if (I.second.Supported) + OptMap[I.getKey()].Supported = true; + } + + void copy(const OpenCLOptions &Opts) { + OptMap = Opts.OptMap; + } + + void supportAll() { + for (llvm::StringMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) + I->second.Supported = true; + } + + void disableAll() { + for (llvm::StringMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) + I->second.Enabled = false; + } + + void enableSupportedCore(unsigned CLVer) { + for (llvm::StringMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) + if (isSupportedCore(I->getKey(), CLVer)) + I->second.Enabled = true; + } + friend class ASTWriter; + friend class ASTReader; }; } // end namespace clang Index: include/clang/Sema/Overload.h =================================================================== --- include/clang/Sema/Overload.h +++ include/clang/Sema/Overload.h @@ -587,7 +587,10 @@ 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). Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -7986,6 +7986,58 @@ void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); //===--------------------------------------------------------------------===// + // OpenCL extensions. + // +private: + std::string CurrOpenCLExtension; + /// Extensions required by an OpenCL type. + llvm::DenseMap> OpenCLTypeExtMap; + /// Extensions required by an OpenCL declaration. + llvm::DenseMap> 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 Extsion 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: Index: include/clang/Serialization/ASTReader.h =================================================================== --- include/clang/Serialization/ASTReader.h +++ include/clang/Serialization/ASTReader.h @@ -787,7 +787,7 @@ SourceLocation PointersToMembersPragmaLocation; /// \brief The OpenCL extension settings. - SmallVector OpenCLExtensions; + OpenCLOptions OpenCLExtensions; /// \brief A list of the namespaces we've seen. SmallVector KnownNamespaces; Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -1864,16 +1864,16 @@ } 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.support("cl_clang_storage_class_specifiers"); + Opts.support("cl_khr_gl_sharing"); + Opts.support("cl_khr_icd"); - 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_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"); } }; @@ -2141,27 +2141,27 @@ 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_SOUTHERN_ISLANDS) { - 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"); } } @@ -2853,7 +2853,7 @@ } void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().setAll(); + getSupportedOpenCLOpts().supportAll(); } }; @@ -8041,7 +8041,7 @@ 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(); } }; Index: lib/Frontend/InitPreprocessor.cpp =================================================================== --- lib/Frontend/InitPreprocessor.cpp +++ lib/Frontend/InitPreprocessor.cpp @@ -955,7 +955,7 @@ // 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" Index: lib/Headers/opencl-c.h =================================================================== --- lib/Headers/opencl-c.h +++ lib/Headers/opencl-c.h @@ -15480,6 +15480,10 @@ #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. Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -455,42 +455,48 @@ } namespace { - typedef llvm::PointerIntPair OpenCLExtData; + enum OpenCLExtState : char { + Disable, Enable, Begin, End + }; + typedef std::pair 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(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() { @@ -1410,29 +1416,34 @@ "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); + if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_register)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0; return; } - IdentifierInfo *op = 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); + IdentifierInfo *Pred = Tok.getIdentifierInfo(); + + 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(); @@ -1444,19 +1455,21 @@ return; } - OpenCLExtData data(ename, state); + auto Info = PP.getPreprocessorAllocator().Allocate(1); + Info->first = Ext; + Info->second = State; MutableArrayRef Toks(PP.getPreprocessorAllocator().Allocate(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(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. Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -930,6 +930,8 @@ 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); Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -543,7 +543,7 @@ // 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: Index: lib/Sema/Sema.cpp =================================================================== --- lib/Sema/Sema.cpp +++ lib/Sema/Sema.cpp @@ -208,14 +208,11 @@ 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) { @@ -226,26 +223,60 @@ 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 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"); @@ -1519,3 +1550,92 @@ Sema::getMismatchingDeleteExpressions() const { return DeleteExprs; } + +void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) { + llvm::SmallVector Exts; + ExtStr.split(Exts, " ", /* limit */ -1, /* keep empty */ false); + if (Exts.empty()) + return; + auto CanT = T.getCanonicalType().getTypePtr(); + for (auto &I : Exts) + OpenCLTypeExtMap[CanT].insert(I.str()); +} + +void Sema::setOpenCLExtensionForDecl(Decl *FD, StringRef ExtStr) { + llvm::SmallVector 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; +} + +bool Sema::checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType QT) { + // Check extensions for declared types. + Decl *Decl = nullptr; + if (auto TypedefT = dyn_cast(QT.getTypePtr())) + Decl = TypedefT->getDecl(); + if (auto TagT = dyn_cast(QT.getCanonicalType().getTypePtr())) + Decl = TagT->getDecl(); + auto DL = OpenCLDeclExtMap.find(Decl); + if (DL != OpenCLDeclExtMap.end()) { + for (auto &I : DL->second) { + if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << QT << I; + return true; + } + } + } + + // Check extensions for builtin types. + auto Loc = OpenCLTypeExtMap.find(QT.getCanonicalType().getTypePtr()); + if (Loc == OpenCLTypeExtMap.end()) + return false; + bool Disabled = false; + for (auto &I : Loc->second) { + if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) { + Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) + << QT << I; + Disabled = true; + } + } + return Disabled; +} + +bool Sema::checkOpenCLDisabledDecl(const Decl &D, const Expr &E) { + auto DL = OpenCLDeclExtMap.find(&D); + if (DL != OpenCLDeclExtMap.end()) { + for (auto &I : DL->second) { + if (I != CurrOpenCLExtension && !getOpenCLOptions().isEnabled(I)) { + Diag(E.getLocStart(), diag::err_decl_requires_extension) + << I << D.getSourceRange(); + return true; + } + } + } + return false; +} Index: lib/Sema/SemaCast.cpp =================================================================== --- lib/Sema/SemaCast.cpp +++ lib/Sema/SemaCast.cpp @@ -2519,7 +2519,8 @@ } } - 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(); Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -4793,6 +4793,9 @@ Dcl && Dcl->getDeclContext()->isFileContext()) Dcl->setTopLevelDeclInObjCContainer(); + if (getLangOpts().OpenCL) + setCurrentOpenCLExtensionForDecl(Dcl); + return Dcl; } @@ -5908,7 +5911,7 @@ 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()) { @@ -6815,7 +6818,7 @@ // 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(); Index: lib/Sema/SemaExpr.cpp =================================================================== --- lib/Sema/SemaExpr.cpp +++ lib/Sema/SemaExpr.cpp @@ -668,7 +668,7 @@ 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; @@ -3385,7 +3385,7 @@ 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); @@ -3407,7 +3407,7 @@ Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } else if (getLangOpts().OpenCL && !((getLangOpts().OpenCLVersion >= 120) || - getOpenCLOptions().cl_khr_fp64)) { + getOpenCLOptions().isEnabled("cl_khr_fp64"))) { Diag(Tok.getLocation(), diag::warn_double_const_requires_fp64); Res = ImpCastExprToType(Res, Context.FloatTy, CK_FloatingCast).get(); } @@ -5270,6 +5270,9 @@ Fn->getLocStart())) return ExprError(); + if (S.getLangOpts().OpenCL && S.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 Index: lib/Sema/SemaOverload.cpp =================================================================== --- lib/Sema/SemaOverload.cpp +++ lib/Sema/SemaOverload.cpp @@ -5857,6 +5857,12 @@ Candidate.DeductionFailure.Data = FailedAttr; return; } + + if (LangOpts.OpenCL && isOpenCLDisabledDecl(Function)) { + Candidate.Viable = false; + Candidate.FailureKind = ovl_fail_ext_disabled; + return; + } } ObjCMethodDecl * @@ -9673,6 +9679,13 @@ << 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. /// @@ -9750,6 +9763,9 @@ 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; Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1411,14 +1411,6 @@ Result = Context.LongDoubleTy; else Result = Context.DoubleTy; - - if (S.getLangOpts().OpenCL && - !((S.getLangOpts().OpenCLVersion >= 120) || - 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()) @@ -1470,48 +1462,6 @@ Result = S.GetTypeFromParser(DS.getRepAsType()); if (Result.isNull()) { declarator.setInvalidType(true); - } else if (S.getLangOpts().OpenCL) { - if (Result->getAs()) { - StringRef TypeName = Result.getBaseTypeIdentifier()->getName(); - bool NoExtTypes = - llvm::StringSwitch(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. @@ -1637,6 +1587,10 @@ 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) @@ -4043,7 +3997,7 @@ // 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); @@ -4250,7 +4204,7 @@ // 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(); Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -3098,8 +3098,14 @@ 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(Record[I++]), + static_cast(Record[I++]), + static_cast(Record[I++]), + static_cast(Record[I++])}; + } break; case TENTATIVE_DEFINITIONS: @@ -6938,14 +6944,7 @@ 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); UpdateSema(); } Index: lib/Serialization/ASTWriter.cpp =================================================================== --- lib/Serialization/ASTWriter.cpp +++ lib/Serialization/ASTWriter.cpp @@ -3839,8 +3839,14 @@ 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); } Index: test/CodeGenOpenCL/extension-begin.cl =================================================================== --- /dev/null +++ test/CodeGenOpenCL/extension-begin.cl @@ -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); +} Index: test/Parser/opencl-atomics-cl20.cl =================================================================== --- test/Parser/opencl-atomics-cl20.cl +++ test/Parser/opencl-atomics-cl20.cl @@ -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 @@ // expected-error@-28 {{use of type 'atomic_ulong' (aka '_Atomic(unsigned long)') requires cl_khr_int64_extended_atomics extension to be enabled}} // expected-error@-27 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_base_atomics extension to be enabled}} // expected-error@-28 {{use of type 'atomic_double' (aka '_Atomic(double)') requires cl_khr_int64_extended_atomics extension to be enabled}} -// expected-error-re@-27 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} -// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} -// expected-error-re@-28 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} -// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} -// expected-error-re@-29 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} -// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} -// expected-error-re@-30 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} -// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} +#if __LP64__ +// expected-error-re@-28 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} +// expected-error-re@-29 {{use of type 'atomic_intptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} +// expected-error-re@-29 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} +// expected-error-re@-30 {{use of type 'atomic_uintptr_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} +// expected-error-re@-30 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} +// expected-error-re@-31 {{use of type 'atomic_size_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} +// expected-error-re@-31 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_base_atomics extension to be enabled}} +// expected-error-re@-32 {{use of type 'atomic_ptrdiff_t' (aka '_Atomic({{.+}})') requires cl_khr_int64_extended_atomics extension to be enabled}} +#endif #endif #ifdef CL20 Index: test/Parser/opencl-pragma.cl =================================================================== --- test/Parser/opencl-pragma.cl +++ test/Parser/opencl-pragma.cl @@ -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 Index: test/SemaOpenCL/extension-begin.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/extension-begin.cl @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only + +#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; +}; + +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); + +#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}} + 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@-19 {{candidate disabled due to OpenCL extension}} + // expected-note@-15 {{candidate function not viable: requires 0 arguments, but 1 was provided}} +}