diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -444,6 +444,9 @@ /// 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; diff --git a/clang/include/clang/Basic/OpenCLOptions.h b/clang/include/clang/Basic/OpenCLOptions.h --- a/clang/include/clang/Basic/OpenCLOptions.h +++ b/clang/include/clang/Basic/OpenCLOptions.h @@ -58,7 +58,7 @@ // 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; } @@ -79,7 +79,7 @@ // 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)); } @@ -115,8 +115,7 @@ // 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. diff --git a/clang/lib/Basic/Builtins.cpp b/clang/lib/Basic/Builtins.cpp --- a/clang/lib/Basic/Builtins.cpp +++ b/clang/lib/Basic/Builtins.cpp @@ -72,7 +72,7 @@ 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); diff --git a/clang/lib/Basic/LangOptions.cpp b/clang/lib/Basic/LangOptions.cpp --- a/clang/lib/Basic/LangOptions.cpp +++ b/clang/lib/Basic/LangOptions.cpp @@ -52,6 +52,16 @@ 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)) diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -745,7 +745,7 @@ // 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) && diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -733,8 +733,9 @@ 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)), @@ -827,9 +828,8 @@ 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)), diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -504,7 +504,7 @@ // 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); @@ -3174,9 +3174,8 @@ 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) { diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3985,8 +3985,8 @@ 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(); @@ -5171,8 +5171,8 @@ // 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. @@ -5702,8 +5702,8 @@ 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) diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -631,8 +631,7 @@ 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; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -330,7 +330,7 @@ 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) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8834,8 +8834,7 @@ // 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; @@ -10017,7 +10016,7 @@ // 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()) { QualType ElemTy = PipeTy->getElementType(); if (ElemTy->isReferenceType() || ElemTy->isPointerType()) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7519,7 +7519,7 @@ } 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 diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -12263,7 +12263,7 @@ return computeResultTy(); } - if (getLangOpts().OpenCLVersion >= 200 || getLangOpts().OpenCLCPlusPlus) { + if (getLangOpts().getOpenCLCompatibleVersion() >= 200) { if (LHSType->isClkEventT() && RHSType->isClkEventT()) { return computeResultTy(); } @@ -12522,8 +12522,9 @@ /*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 @@ -14974,8 +14975,7 @@ } } 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()->getElementType(); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1369,8 +1369,7 @@ // 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(); @@ -5093,7 +5092,7 @@ "__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);