/// Return the OpenCL C or C++ version as a VersionTuple.
VersionTuple getOpenCLVersionTuple() const;
+ /// Return the OpenCL version that kernel language is compatible with
+ unsigned getOpenCLCompatibleVersion() const;
+
/// Return the OpenCL C or C++ for OpenCL language name and version
/// as a string.
std::string getOpenCLVersionString() const;
// mask.
static inline bool isOpenCLVersionContainedInMask(const LangOptions &LO,
unsigned Mask) {
- auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
+ auto CLVer = LO.getOpenCLCompatibleVersion();
OpenCLVersionID Code = encodeOpenCLVersion(CLVer);
return Mask & Code;
}
// the __opencl_c_program_scope_global_variables feature is supported
// C++ for OpenCL inherits rule from OpenCL C v2.0.
bool areProgramScopeVariablesSupported(const LangOptions &Opts) const {
- return Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200 ||
+ return Opts.getOpenCLCompatibleVersion() == 200 ||
(Opts.OpenCLVersion == 300 &&
isSupported("__opencl_c_program_scope_global_variables", Opts));
}
// Is option available in OpenCL version \p LO.
bool isAvailableIn(const LangOptions &LO) const {
// In C++ mode all extensions should work at least as in v2.0.
- auto CLVer = LO.OpenCLCPlusPlus ? 200 : LO.OpenCLVersion;
- return CLVer >= Avail;
+ return LO.getOpenCLCompatibleVersion() >= Avail;
}
// Is core option in OpenCL version \p LO.
bool OclC1Unsupported = (LangOpts.OpenCLVersion / 100) != 1 &&
(BuiltinInfo.Langs & ALL_OCLC_LANGUAGES ) == OCLC1X_LANG;
bool OclC2Unsupported =
- (LangOpts.OpenCLVersion != 200 && !LangOpts.OpenCLCPlusPlus) &&
+ (LangOpts.getOpenCLCompatibleVersion() != 200) &&
(BuiltinInfo.Langs & ALL_OCLC_LANGUAGES) == OCLC20_LANG;
bool OclCUnsupported = !LangOpts.OpenCL &&
(BuiltinInfo.Langs & ALL_OCLC_LANGUAGES);
return VersionTuple(Ver / 100, (Ver % 100) / 10);
}
+unsigned LangOptions::getOpenCLCompatibleVersion() const {
+ if (!OpenCLCPlusPlus)
+ return OpenCLVersion;
+ if (OpenCLCPlusPlusVersion == 100)
+ return 200;
+ if (OpenCLCPlusPlusVersion == 202100)
+ return 300;
+ llvm_unreachable("Unknown OpenCL version");
+}
+
void LangOptions::remapPathPrefix(SmallString<256> &Path) const {
for (const auto &Entry : MacroPrefixMap)
if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
// Validate that feature macros are set properly for OpenCL C 3.0.
// In other cases assume that target is always valid.
- if (Opts.OpenCLCPlusPlus || Opts.OpenCLVersion < 300)
+ if (Opts.getOpenCLCompatibleVersion() < 300)
return true;
return OpenCLOptions::diagnoseUnsupportedFeatureDependencies(*this, Diags) &&
if (getTriple().isSPIR()) {
// SPIR v2.0 s2.12 - The SPIR version used by the module is stored in the
// opencl.spir.version named metadata.
- // C++ is backwards compatible with OpenCL v2.0.
- auto Version = LangOpts.OpenCLCPlusPlus ? 200 : LangOpts.OpenCLVersion;
+ // C++ for OpenCL has a distinct mapping for version compatibility with
+ // OpenCL.
+ auto Version = LangOpts.getOpenCLCompatibleVersion();
llvm::Metadata *SPIRVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, Version / 100)),
void CodeGenModule::EmitOpenCLMetadata() {
// SPIR v2.0 s2.13 - The OpenCL version used by the module is stored in the
// opencl.ocl.version named metadata node.
- // C++ is backwards compatible with OpenCL v2.0.
- // FIXME: We might need to add CXX version at some point too?
- auto Version = LangOpts.OpenCLCPlusPlus ? 200 : LangOpts.OpenCLVersion;
+ // C++ for OpenCL has a distinct mapping for versions compatibile with OpenCL.
+ auto Version = LangOpts.getOpenCLCompatibleVersion();
llvm::Metadata *OCLVerElts[] = {
llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
Int32Ty, Version / 100)),
// This option should be deprecated for CL > 1.0 because
// this option was added for compatibility with OpenCL 1.0.
if (Args.getLastArg(OPT_cl_strict_aliasing) &&
- (LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion > 100))
+ (LangOpts.getOpenCLCompatibleVersion() > 100))
Diags.Report(diag::warn_option_invalid_ocl_version)
<< LangOpts.getOpenCLVersionString()
<< Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args);
Opts.ZVector = 0;
Opts.setDefaultFPContractMode(LangOptions::FPM_On);
Opts.OpenCLCPlusPlus = Opts.CPlusPlus;
- Opts.OpenCLPipes = Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
- Opts.OpenCLGenericAddressSpace =
- Opts.OpenCLCPlusPlus || Opts.OpenCLVersion == 200;
+ Opts.OpenCLPipes = Opts.getOpenCLCompatibleVersion() == 200;
+ Opts.OpenCLGenericAddressSpace = Opts.getOpenCLCompatibleVersion() == 200;
// Include default header file for OpenCL.
if (Opts.IncludeDefaultHeader) {
isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
break;
case tok::kw_pipe:
- if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200 &&
- !getLangOpts().OpenCLCPlusPlus)) {
+ if (!getLangOpts().OpenCL ||
+ getLangOpts().getOpenCLCompatibleVersion() < 200) {
// OpenCL 2.0 and later define this keyword. OpenCL 1.2 and earlier
// should support the "pipe" word as identifier.
Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
// OpenCL 2.0 and later define this keyword.
case tok::kw_pipe:
- return (getLangOpts().OpenCL && getLangOpts().OpenCLVersion >= 200) ||
- getLangOpts().OpenCLCPlusPlus;
+ return getLangOpts().OpenCL &&
+ getLangOpts().getOpenCLCompatibleVersion() >= 200;
case tok::identifier: // foo::bar
// Unfortunate hack to support "Class.factoryMethod" notation.
return true;
// OpenCL 2.0 and later define this keyword.
- if (Kind == tok::kw_pipe &&
- ((Lang.OpenCL && Lang.OpenCLVersion >= 200) || Lang.OpenCLCPlusPlus))
+ if (Kind == tok::kw_pipe && Lang.OpenCL &&
+ Lang.getOpenCLCompatibleVersion() >= 200)
return true;
if (!Lang.CPlusPlus)
case SCS_extern:
case SCS_private_extern:
case SCS_static:
- if (S.getLangOpts().OpenCLVersion < 120 &&
- !S.getLangOpts().OpenCLCPlusPlus) {
+ if (S.getLangOpts().getOpenCLCompatibleVersion() < 120) {
DiagID = diag::err_opencl_unknown_type_specifier;
PrevSpec = getSpecifierName(SC);
return true;
Context.getTargetInfo().getSupportedOpenCLOpts(), getLangOpts());
addImplicitTypedef("sampler_t", Context.OCLSamplerTy);
addImplicitTypedef("event_t", Context.OCLEventTy);
- if (getLangOpts().OpenCLCPlusPlus || getLangOpts().OpenCLVersion >= 200) {
+ if (getLangOpts().getOpenCLCompatibleVersion() >= 200) {
addImplicitTypedef("clk_event_t", Context.OCLClkEventTy);
addImplicitTypedef("queue_t", Context.OCLQueueTy);
if (getLangOpts().OpenCLPipes)
// OpenCL v3.0 s6.11.a:
// A kernel function argument cannot be declared as a pointer to a pointer
// type. [...] This restriction only applies to OpenCL C 1.2 or below.
- if (S.getLangOpts().OpenCLVersion <= 120 &&
- !S.getLangOpts().OpenCLCPlusPlus) {
+ if (S.getLangOpts().getOpenCLCompatibleVersion() <= 120) {
S.Diag(Param->getLocation(), diag::err_opencl_ptrptr_kernel_param);
D.setInvalidType();
return;
// OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value
// types.
- if (getLangOpts().OpenCLVersion >= 200 || getLangOpts().OpenCLCPlusPlus) {
+ if (getLangOpts().getOpenCLCompatibleVersion() >= 200) {
if(const PipeType *PipeTy = PT->getAs<PipeType>()) {
QualType ElemTy = PipeTy->getElementType();
if (ElemTy->isReferenceType() || ElemTy->isPointerType()) {
}
static void handleOpenCLNoSVMAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
- if (S.LangOpts.OpenCLVersion < 200 && !S.LangOpts.OpenCLCPlusPlusVersion)
+ if (S.LangOpts.getOpenCLCompatibleVersion() < 200)
S.Diag(AL.getLoc(), diag::err_attribute_requires_opencl_version)
<< AL << "2.0" << 1;
else
return computeResultTy();
}
- if (getLangOpts().OpenCLVersion >= 200 || getLangOpts().OpenCLCPlusPlus) {
+ if (getLangOpts().getOpenCLCompatibleVersion() >= 200) {
if (LHSType->isClkEventT() && RHSType->isClkEventT()) {
return computeResultTy();
}
/*AllowBoolConversions*/false);
if (vType.isNull())
return InvalidOperands(Loc, LHS, RHS);
- if (getLangOpts().OpenCL && getLangOpts().OpenCLVersion < 120 &&
- !getLangOpts().OpenCLCPlusPlus && vType->hasFloatingRepresentation())
+ if (getLangOpts().OpenCL &&
+ getLangOpts().getOpenCLCompatibleVersion() < 120 &&
+ vType->hasFloatingRepresentation())
return InvalidOperands(Loc, LHS, RHS);
// FIXME: The check for C++ here is for GCC compatibility. GCC rejects the
// usage of the logical operators && and || with vectors in C. This
}
} else if (resultType->isExtVectorType()) {
if (Context.getLangOpts().OpenCL &&
- Context.getLangOpts().OpenCLVersion < 120 &&
- !Context.getLangOpts().OpenCLCPlusPlus) {
+ Context.getLangOpts().getOpenCLCompatibleVersion() < 120) {
// OpenCL v1.1 6.3.h: The logical operator not (!) does not
// operate on vector float types.
QualType T = resultType->castAs<ExtVectorType>()->getElementType();
// value being declared, poison it as invalid so we don't get chains of
// errors.
declarator.setInvalidType(true);
- } else if ((S.getLangOpts().OpenCLVersion >= 200 ||
- S.getLangOpts().OpenCLCPlusPlus) &&
+ } else if (S.getLangOpts().getOpenCLCompatibleVersion() >= 200 &&
DS.isTypeSpecPipe()) {
S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
<< DS.getSourceRange();
"__cl_clang_variadic_functions", S.getLangOpts()) &&
!(D.getIdentifier() &&
((D.getIdentifier()->getName() == "printf" &&
- (LangOpts.OpenCLCPlusPlus || LangOpts.OpenCLVersion >= 120)) ||
+ LangOpts.getOpenCLCompatibleVersion() >= 120) ||
D.getIdentifier()->getName().startswith("__")))) {
S.Diag(D.getIdentifierLoc(), diag::err_opencl_variadic_function);
D.setInvalidType(true);