From 2e8331cab61615d3831f4eb497a38171eaccc9e7 Mon Sep 17 00:00:00 2001 From: Yaxun Liu Date: Fri, 16 Dec 2016 19:22:08 +0000 Subject: [PATCH] [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 llvm-svn: 289979 --- clang/include/clang/Basic/DiagnosticParseKinds.td | 6 +- clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 +- clang/include/clang/Basic/OpenCLImageTypes.def | 98 +++++++------- clang/include/clang/Basic/OpenCLOptions.h | 111 +++++++++++----- clang/include/clang/Basic/TargetInfo.h | 2 +- clang/include/clang/Sema/Overload.h | 5 +- clang/include/clang/Sema/Sema.h | 67 ++++++++++ clang/include/clang/Serialization/ASTBitCodes.h | 28 ++-- clang/include/clang/Serialization/ASTReader.h | 8 +- clang/include/clang/Serialization/ASTWriter.h | 2 + clang/lib/Basic/Targets.cpp | 54 ++++---- clang/lib/Frontend/InitPreprocessor.cpp | 2 +- clang/lib/Headers/opencl-c.h | 4 + clang/lib/Parse/ParsePragma.cpp | 97 ++++++++------ clang/lib/Parse/Parser.cpp | 2 + clang/lib/Sema/DeclSpec.cpp | 2 +- clang/lib/Sema/Sema.cpp | 155 +++++++++++++++++++--- clang/lib/Sema/SemaCast.cpp | 3 +- clang/lib/Sema/SemaDecl.cpp | 9 +- clang/lib/Sema/SemaExpr.cpp | 13 +- clang/lib/Sema/SemaOverload.cpp | 16 +++ clang/lib/Sema/SemaType.cpp | 57 +------- clang/lib/Serialization/ASTReader.cpp | 45 +++++-- clang/lib/Serialization/ASTWriter.cpp | 43 +++++- clang/test/CodeGenOpenCL/extension-begin.cl | 25 ++++ clang/test/Parser/opencl-atomics-cl20.cl | 19 +-- clang/test/Parser/opencl-pragma.cl | 4 +- clang/test/SemaOpenCL/extension-begin.cl | 56 ++++++++ clang/test/SemaOpenCL/extensions.cl | 2 - 29 files changed, 666 insertions(+), 275 deletions(-) create mode 100644 clang/test/CodeGenOpenCL/extension-begin.cl create mode 100644 clang/test/SemaOpenCL/extension-begin.cl diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index f6d8b3a..0ebf348 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -968,8 +968,10 @@ def err_opencl_unroll_hint_on_non_loop : Error< // 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< diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8498740..73f7f4d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3359,6 +3359,8 @@ def note_ovl_candidate_has_pass_object_size_params: Note< "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 : Warning < InGroup; 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< diff --git a/clang/include/clang/Basic/OpenCLImageTypes.def b/clang/include/clang/Basic/OpenCLImageTypes.def index 26db4ce..1ca12f6 100644 --- a/clang/include/clang/Basic/OpenCLImageTypes.def +++ b/clang/include/clang/Basic/OpenCLImageTypes.def @@ -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) -#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 diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h index fa52ae7..9fb4dbb 100644 --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -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 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; + } + + void copy(const OpenCLOptions &Opts) { + OptMap = Opts.OptMap; } -#include "clang/Basic/OpenCLExtensions.def" + // Turn on or off support of all options. + void supportAll(bool On = true) { + for (llvm::StringMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) + I->second.Supported = On; + } - // 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 disableAll() { + for (llvm::StringMap::iterator I = OptMap.begin(), + E = OptMap.end(); I != E; ++I) + I->second.Enabled = false; } -#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 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; } -#include "clang/Basic/OpenCLExtensions.def" + friend class ASTWriter; + friend class ASTReader; }; } // end namespace clang diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index ec566f0..dcd5a08 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -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); } } diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index f677afe..7c6699a 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -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). diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index e5b08b0..98e85a4 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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> 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 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 + 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. diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 32e8c42..c6fd109 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -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. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 6f1a6ac..57a504c 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -807,7 +807,13 @@ private: SourceLocation PointersToMembersPragmaLocation; /// \brief The OpenCL extension settings. - SmallVector OpenCLExtensions; + OpenCLOptions OpenCLExtensions; + + /// \brief Extensions required by an OpenCL type. + llvm::DenseMap> OpenCLTypeExtMap; + + /// \brief Extensions required by an OpenCL declaration. + llvm::DenseMap> OpenCLDeclExtMap; /// \brief A list of the namespaces we've seen. SmallVector KnownNamespaces; diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 2462900..1469555 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -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); diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index ee84089..f887b05 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -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.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"); } }; @@ -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(); } }; diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 31340e0..47881b1 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -988,7 +988,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // 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" diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 004eca3..0c25d31 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -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. diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp index d6539c9..2dc6a07 100644 --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -486,42 +486,48 @@ StmtResult Parser::HandlePragmaCaptured() } 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() { @@ -1441,29 +1447,34 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, "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(); - - 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(); @@ -1475,19 +1486,21 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, 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. diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index e97b5e4..d8a4ea6 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -934,6 +934,8 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, 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); diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index cc644c7..a55cdcc 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -558,7 +558,7 @@ bool DeclSpec::SetStorageClassSpec(Sema &S, SCS SC, SourceLocation Loc, // 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: diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index fc76a86..412f944 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -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 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 & Sema::getMismatchingDeleteExpressions() const { return DeleteExprs; } + +void Sema::setOpenCLExtensionForType(QualType T, llvm::StringRef ExtStr) { + if (ExtStr.empty()) + return; + llvm::SmallVector 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 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 +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(QT.getTypePtr())) + Decl = TypedefT->getDecl(); + if (auto TagT = dyn_cast(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()); +} diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index d1e37c0..6222e4c 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7878355..c327575 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4838,6 +4838,9 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { 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(VarDecl *NewVD) { // 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 getOpenCLKernelParameterType(Sema &S, QualType PT) { // 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()) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c81d805..b888345 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -657,7 +657,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { 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::DefaultArgumentPromotion(Expr *E) { 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(const Token &Tok, Scope *UDLScope) { 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(const Token &Tok, Scope *UDLScope) { 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 *Scope, Expr *Fn, SourceLocation LParenLoc, 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(Expr *LHSExpr, ExprResult &RHS, // 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(); diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 1cf6850..1899e41 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5949,6 +5949,12 @@ Sema::AddOverloadCandidate(FunctionDecl *Function, 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(Sema &S, OverloadCandidate *Cand) { << 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 &S, OverloadCandidate *Cand, 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; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 9a01040..0466835 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1401,13 +1401,6 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { 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(TypeProcessingState &state) { 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. @@ -1636,6 +1587,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { 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 *GetFullTypeForDeclarator(TypeProcessingState &state, // 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 *GetFullTypeForDeclarator(TypeProcessingState &state, // 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(); diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 8d6735c..ba1a389 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -3164,8 +3164,38 @@ ASTReader::ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities) { 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++]) /* Supported */, + static_cast(Record[I++]) /* Enabled */, + static_cast(Record[I++]) /* Avail */, + static_cast(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(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(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(); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 8b863bc..493941a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -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(Sema &SemaRef) { 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(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(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 &SemaRef, StringRef isysroot, WriteIdentifierTable(PP, SemaRef.IdResolver, isModule); WriteFPPragmaOptions(SemaRef.getFPOptions()); WriteOpenCLExtensions(SemaRef); + WriteOpenCLExtensionTypes(SemaRef); + WriteOpenCLExtensionDecls(SemaRef); WriteCUDAPragmas(SemaRef); WritePragmaDiagnosticMappings(Context.getDiagnostics(), isModule); diff --git a/clang/test/CodeGenOpenCL/extension-begin.cl b/clang/test/CodeGenOpenCL/extension-begin.cl new file mode 100644 index 0000000..1d5f789 --- /dev/null +++ b/clang/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); +} diff --git a/clang/test/Parser/opencl-atomics-cl20.cl b/clang/test/Parser/opencl-atomics-cl20.cl index cd37757..65fb9d9 100644 --- a/clang/test/Parser/opencl-atomics-cl20.cl +++ b/clang/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 @@ void atomic_types_test() { // 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 diff --git a/clang/test/Parser/opencl-pragma.cl b/clang/test/Parser/opencl-pragma.cl index b002b08..02f053f 100644 --- a/clang/test/Parser/opencl-pragma.cl +++ b/clang/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 diff --git a/clang/test/SemaOpenCL/extension-begin.cl b/clang/test/SemaOpenCL/extension-begin.cl new file mode 100644 index 0000000..3393458 --- /dev/null +++ b/clang/test/SemaOpenCL/extension-begin.cl @@ -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@-26 {{candidate disabled due to OpenCL extension}} + // expected-note@-22 {{candidate function not viable: requires 0 arguments, but 1 was provided}} +} + +#endif // HEADER_USER + diff --git a/clang/test/SemaOpenCL/extensions.cl b/clang/test/SemaOpenCL/extensions.cl index 688185e..c27f339 100644 --- a/clang/test/SemaOpenCL/extensions.cl +++ b/clang/test/SemaOpenCL/extensions.cl @@ -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 -- 2.7.4