Index: include/clang/Basic/OpenCLOptions.h =================================================================== --- include/clang/Basic/OpenCLOptions.h +++ include/clang/Basic/OpenCLOptions.h @@ -57,13 +57,35 @@ // Is supported OpenCL extension for OpenCL version \p CLVer. // For supported (optional) core feature, return false. - bool isSupportedExtension(llvm::StringRef Ext, unsigned CLVer) const { + bool isSupportedExtension(llvm::StringRef Ext, unsigned CLVer) const { auto I = OptMap.find(Ext)->getValue(); return I.Supported && I.Avail <= CLVer && (I.Core == ~0U || CLVer < I.Core); } + llvm::StringRef split(llvm::StringRef Ext, bool& V) { + switch (Ext[0]) { + case '+': + V = true; + Ext = Ext.drop_front(); + break; + case '-': + V = false; + Ext = Ext.drop_front(); + break; + } + return Ext; + } + void enable(llvm::StringRef Ext, bool V = true) { + assert(!Ext.empty() && "Extension is empty."); + + Ext = split(Ext, V); + + if (Ext.equals("all")) { + enableAll(V); + return; + } OptMap[Ext].Enabled = V; } @@ -74,16 +96,7 @@ void support(llvm::StringRef Ext, bool V = true) { assert(!Ext.empty() && "Extension is empty."); - switch (Ext[0]) { - case '+': - V = true; - Ext = Ext.drop_front(); - break; - case '-': - V = false; - Ext = Ext.drop_front(); - break; - } + Ext = split(Ext, V); if (Ext.equals("all")) { supportAll(V); @@ -116,10 +129,14 @@ I->second.Supported = On; } - void disableAll() { + void enableAll(bool On = true) { for (llvm::StringMap::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) - I->second.Enabled = false; + I->second.Enabled = On; + } + + void disableAll() { + enableAll(false); } void enableSupportedCore(unsigned CLVer) { Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -7525,6 +7525,13 @@ SemaObj->OpenCLTypeExtMap = OpenCLTypeExtMap; SemaObj->OpenCLDeclExtMap = OpenCLDeclExtMap; + // OpenCL features imported from a module can be overwritten by -cl-ext option + for (const auto &Ext : + getContext().getTargetInfo().getTargetOpts().OpenCLExtensionsAsWritten) { + SemaObj->OpenCLFeatures.support(Ext); + SemaObj->OpenCLFeatures.enable(Ext); + } + UpdateSema(); } Index: test/SemaOpenCL/extensions-import.h =================================================================== --- /dev/null +++ test/SemaOpenCL/extensions-import.h @@ -0,0 +1 @@ +extern double foo(); Index: test/SemaOpenCL/extensions-import.cl =================================================================== --- /dev/null +++ test/SemaOpenCL/extensions-import.cl @@ -0,0 +1,27 @@ +// When we compile a PCH cl_khr_fp64 is enabled by default. +// And its support is imported alongside with the PCH. +// Check that we can disable features enabled in the PCH we import. + +// No PCH +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL1.2 %s -fsyntax-only -verify -DFP64 +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL1.2 %s -fsyntax-only -verify -cl-ext=-cl_khr_fp64 + +// With PCH +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL1.2 -I %S -emit-pch -o %t.pch %S/extensions-import.h +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL1.2 -include-pch %t.pch %s -fsyntax-only -verify -DIMPORT -DFP64 +// RUN: %clang_cc1 -x cl -O0 -cl-std=CL1.2 -include-pch %t.pch %s -fsyntax-only -verify -DIMPORT -cl-ext=-cl_khr_fp64 + +#ifdef FP64 +// expected-no-diagnostics +#else +// expected-error@+4 {{type 'double' requires cl_khr_fp64 extension}} +// expected-error@+4 {{type 'double' requires cl_khr_fp64 extension}} +// expected-warning@+4 {{double precision constant requires cl_khr_fp64}} +#endif +void kernel f1(double da) { + double d; + (void) 1.0; +#ifdef IMPORT + d = foo(); +#endif +}