Index: include/clang/Basic/DiagnosticParseKinds.td =================================================================== --- include/clang/Basic/DiagnosticParseKinds.td +++ include/clang/Basic/DiagnosticParseKinds.td @@ -922,8 +922,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' or 'disable' or 'register'|'disable'}0 - ignoring">, InGroup; +def warn_pragma_register_supported : Warning< + "register supported OpenCL extension or optional core feature - ignoring">, InGroup; def warn_pragma_unknown_extension : Warning< "unknown OpenCL extension %0 - ignoring">, InGroup; def warn_pragma_unsupported_extension : Warning< Index: include/clang/Basic/OpenCLOptions.h =================================================================== --- include/clang/Basic/OpenCLOptions.h +++ include/clang/Basic/OpenCLOptions.h @@ -17,50 +17,100 @@ #include #include +#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/Serialization/ASTReader.h =================================================================== --- include/clang/Serialization/ASTReader.h +++ include/clang/Serialization/ASTReader.h @@ -788,7 +788,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"); } }; @@ -2111,23 +2111,23 @@ 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_3d_image_writes = 1; + Opts.support("cl_khr_fp16"); + Opts.support("cl_khr_int64_base_atomics"); + Opts.support("cl_khr_int64_extended_atomics"); + Opts.support("cl_khr_3d_image_writes"); } } }; @@ -2805,7 +2805,7 @@ } void setSupportedOpenCLOpts() override { - getSupportedOpenCLOpts().setAll(); + getSupportedOpenCLOpts().supportAll(); } }; @@ -7927,7 +7927,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 @@ -958,7 +958,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/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -455,42 +455,44 @@ } namespace { - typedef llvm::PointerIntPair OpenCLExtData; + enum OpenCLExtState : char { + Disable, Enable, Register + }; + 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 == Register) { + if (!Opt.isKnown(Name) || + !Opt.isSupported(Name, getLangOpts().OpenCLVersion)) + Opt.support(Name); + else + PP.Diag(NameLoc, diag::warn_pragma_register_supported); + } 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 +1412,32 @@ "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(); + IdentifierInfo *Pred = Tok.getIdentifierInfo(); - unsigned state; - if (op->isStr("enable")) { - state = 1; - } else if (op->isStr("disable")) { - state = 0; - } else { - PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_enable_disable); + OpenCLExtState State; + if (Pred->isStr("enable")) { + State = Enable; + } else if (Pred->isStr("disable")) { + State = Disable; + } else if (Pred->isStr("register")) + State = Register; + else { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) + << Ext->isStr("all"); return; } SourceLocation StateLoc = Tok.getLocation(); @@ -1444,19 +1449,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/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -511,7 +511,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 @@ -209,14 +209,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) { 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 @@ -5861,7 +5861,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()) { @@ -6741,7 +6741,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 @@ -665,7 +665,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; @@ -3366,7 +3366,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); @@ -3388,7 +3388,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(); } Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -1414,7 +1414,7 @@ if (S.getLangOpts().OpenCL && !((S.getLangOpts().OpenCLVersion >= 120) || - S.getOpenCLOptions().cl_khr_fp64)) { + S.getOpenCLOptions().isEnabled("cl_khr_fp64"))) { S.Diag(DS.getTypeSpecTypeLoc(), diag::err_type_requires_extension) << Result << "cl_khr_fp64"; declarator.setInvalidType(true); @@ -1478,24 +1478,25 @@ .Cases("atomic_int", "atomic_uint", "atomic_float", "atomic_flag", true) .Default(false); - if (!S.getOpenCLOptions().cl_khr_int64_base_atomics && !NoExtTypes) { + if (!S.getOpenCLOptions().isEnabled("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) { + if (!S.getOpenCLOptions().isEnabled("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 && + if (!S.getOpenCLOptions().isEnabled("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 && + } else if (!S.getOpenCLOptions().isEnabled("cl_khr_gl_msaa_sharing") && (Result->isOCLImage2dArrayMSAADepthROType() || Result->isOCLImage2dArrayMSAADepthWOType() || Result->isOCLImage2dArrayMSAADepthRWType() || @@ -4008,7 +4009,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); @@ -4214,7 +4215,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 @@ -3097,8 +3097,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: @@ -6924,14 +6930,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 @@ -3829,8 +3829,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/PCH/opencl-extensions.cl =================================================================== --- test/PCH/opencl-extensions.cl +++ test/PCH/opencl-extensions.cl @@ -6,10 +6,13 @@ // Header. #pragma OPENCL EXTENSION cl_khr_fp64 : enable +#pragma OPENCL EXTENSION my_ext_example : register #else // Using the header. +#pragma OPENCL EXTENSION my_extension : enable + void test(void) { double d; } Index: test/Parser/opencl-pragma.cl =================================================================== --- test/Parser/opencl-pragma.cl +++ test/Parser/opencl-pragma.cl @@ -5,9 +5,13 @@ #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 all : register /* expected-warning {{expected 'disable' - ignoring}} */ +#pragma OPENCL EXTENSION all : on /* 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' or 'disable' or 'register' - ignoring}} */ + +#pragma OPENCL EXTENSION my_ext : on /* expected-warning {{expected 'enable' or 'disable' or 'register' - ignoring}} */ #pragma OPENCL FP_CONTRACT ON #pragma OPENCL FP_CONTRACT OFF Index: test/SemaOpenCL/extension-register.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/extension-register.cl @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only + +#pragma OPENCL EXTENSION cl_khr_fp16 : register // expected-warning {{register supported OpenCL extension or optional core feature - ignoring}} + +#pragma OPENCL EXTENSION all : register /* expected-warning {{expected 'disable' - ignoring}} */ + +#pragma OPENCL EXTENSION my_ext : enable // expected-warning {{unknown OpenCL extension 'my_ext' - ignoring}} +#pragma OPENCL EXTENSION my_ext : disable // expected-warning {{unknown OpenCL extension 'my_ext' - ignoring}} +#pragma OPENCL EXTENSION my_ext : register +#pragma OPENCL EXTENSION my_ext : register // expected-warning {{register supported OpenCL extension or optional core feature - ignoring}} +#pragma OPENCL EXTENSION my_ext : enable +#pragma OPENCL EXTENSION my_ext : disable +