//===--- Targets.cpp - Implement target feature support -------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements construction of a TargetInfo object from a // target triple. // //===----------------------------------------------------------------------===// #include "Targets.h" #include "Targets/AArch64.h" #include "Targets/AMDGPU.h" #include "Targets/ARC.h" #include "Targets/ARM.h" #include "Targets/AVR.h" #include "Targets/BPF.h" #include "Targets/CSKY.h" #include "Targets/DirectX.h" #include "Targets/Hexagon.h" #include "Targets/Lanai.h" #include "Targets/Le64.h" #include "Targets/LoongArch.h" #include "Targets/M68k.h" #include "Targets/MSP430.h" #include "Targets/Mips.h" #include "Targets/NVPTX.h" #include "Targets/OSTargets.h" #include "Targets/PNaCl.h" #include "Targets/PPC.h" #include "Targets/RISCV.h" #include "Targets/SPIR.h" #include "Targets/Sparc.h" #include "Targets/SystemZ.h" #include "Targets/TCE.h" #include "Targets/VE.h" #include "Targets/WebAssembly.h" #include "Targets/X86.h" #include "Targets/XCore.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticFrontend.h" #include "llvm/ADT/StringExtras.h" #include "llvm/TargetParser/Triple.h" using namespace clang; namespace clang { namespace targets { //===----------------------------------------------------------------------===// // Common code shared among targets. //===----------------------------------------------------------------------===// /// DefineStd - Define a macro name and standard variants. For example if /// MacroName is "unix", then this will define "__unix", "__unix__", and "unix" /// when in GNU mode. void DefineStd(MacroBuilder &Builder, StringRef MacroName, const LangOptions &Opts) { assert(MacroName[0] != '_' && "Identifier should be in the user's namespace"); // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier // in the user's namespace. if (Opts.GNUMode) Builder.defineMacro(MacroName); // Define __unix. Builder.defineMacro("__" + MacroName); // Define __unix__. Builder.defineMacro("__" + MacroName + "__"); } void defineCPUMacros(MacroBuilder &Builder, StringRef CPUName, bool Tuning) { Builder.defineMacro("__" + CPUName); Builder.defineMacro("__" + CPUName + "__"); if (Tuning) Builder.defineMacro("__tune_" + CPUName + "__"); } void addCygMingDefines(const LangOptions &Opts, MacroBuilder &Builder) { // Mingw and cygwin define __declspec(a) to __attribute__((a)). Clang // supports __declspec natively under -fdeclspec (also enabled with // -fms-extensions), but we define a no-op __declspec macro anyway for // pre-processor compatibility. if (Opts.DeclSpecKeyword) Builder.defineMacro("__declspec", "__declspec"); else Builder.defineMacro("__declspec(a)", "__attribute__((a))"); if (!Opts.MicrosoftExt) { // Provide macros for all the calling convention keywords. Provide both // single and double underscore prefixed variants. These are available on // x64 as well as x86, even though they have no effect. const char *CCs[] = {"cdecl", "stdcall", "fastcall", "thiscall", "pascal"}; for (const char *CC : CCs) { std::string GCCSpelling = "__attribute__((__"; GCCSpelling += CC; GCCSpelling += "__))"; Builder.defineMacro(Twine("_") + CC, GCCSpelling); Builder.defineMacro(Twine("__") + CC, GCCSpelling); } } } //===----------------------------------------------------------------------===// // Driver code //===----------------------------------------------------------------------===// std::unique_ptr AllocateTarget(const llvm::Triple &Triple, const TargetOptions &Opts) { llvm::Triple::OSType os = Triple.getOS(); switch (Triple.getArch()) { default: return nullptr; case llvm::Triple::arc: return std::make_unique(Triple, Opts); case llvm::Triple::xcore: return std::make_unique(Triple, Opts); case llvm::Triple::hexagon: if (os == llvm::Triple::Linux && Triple.getEnvironment() == llvm::Triple::Musl) return std::make_unique>(Triple, Opts); return std::make_unique(Triple, Opts); case llvm::Triple::lanai: return std::make_unique(Triple, Opts); case llvm::Triple::aarch64_32: if (Triple.isOSDarwin()) return std::make_unique(Triple, Opts); return nullptr; case llvm::Triple::aarch64: if (Triple.isOSDarwin()) return std::make_unique(Triple, Opts); switch (os) { case llvm::Triple::CloudABI: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Fuchsia: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenHOS: return std::make_unique>(Triple, Opts); } case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Win32: switch (Triple.getEnvironment()) { case llvm::Triple::GNU: return std::make_unique(Triple, Opts); case llvm::Triple::MSVC: default: // Assume MSVC for unknown environments return std::make_unique(Triple, Opts); } default: return std::make_unique(Triple, Opts); } case llvm::Triple::aarch64_be: switch (os) { case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Fuchsia: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::arm: case llvm::Triple::thumb: if (Triple.isOSBinFormatMachO()) return std::make_unique(Triple, Opts); switch (os) { case llvm::Triple::CloudABI: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenHOS: return std::make_unique>(Triple, Opts); } case llvm::Triple::LiteOS: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); case llvm::Triple::Win32: switch (Triple.getEnvironment()) { case llvm::Triple::Cygnus: return std::make_unique(Triple, Opts); case llvm::Triple::GNU: return std::make_unique(Triple, Opts); case llvm::Triple::Itanium: return std::make_unique(Triple, Opts); case llvm::Triple::MSVC: default: // Assume MSVC for unknown environments return std::make_unique(Triple, Opts); } default: return std::make_unique(Triple, Opts); } case llvm::Triple::armeb: case llvm::Triple::thumbeb: if (Triple.isOSDarwin()) return std::make_unique(Triple, Opts); switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::avr: return std::make_unique(Triple, Opts); case llvm::Triple::bpfeb: case llvm::Triple::bpfel: return std::make_unique(Triple, Opts); case llvm::Triple::msp430: return std::make_unique(Triple, Opts); case llvm::Triple::mips: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::mipsel: switch (os) { case llvm::Triple::Linux: switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenHOS: return std::make_unique>(Triple, Opts); } case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::mips64: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::mips64el: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::m68k: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::le32: switch (os) { case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); default: return nullptr; } case llvm::Triple::le64: return std::make_unique(Triple, Opts); case llvm::Triple::ppc: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); case llvm::Triple::AIX: return std::make_unique(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::ppcle: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::ppc64: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::Lv2: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::AIX: return std::make_unique(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::ppc64le: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::nvptx: return std::make_unique(Triple, Opts, /*TargetPointerWidth=*/32); case llvm::Triple::nvptx64: return std::make_unique(Triple, Opts, /*TargetPointerWidth=*/64); case llvm::Triple::amdgcn: case llvm::Triple::r600: return std::make_unique(Triple, Opts); case llvm::Triple::riscv32: // TODO: add cases for NetBSD, RTEMS once tested. switch (os) { case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::riscv64: // TODO: add cases for NetBSD, RTEMS once tested. switch (os) { case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Fuchsia: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenHOS: return std::make_unique>(Triple, Opts); } default: return std::make_unique(Triple, Opts); } case llvm::Triple::sparc: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } // The 'sparcel' architecture copies all the above cases except for Solaris. case llvm::Triple::sparcel: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::sparcv9: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::systemz: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); case llvm::Triple::ZOS: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::tce: return std::make_unique(Triple, Opts); case llvm::Triple::tcele: return std::make_unique(Triple, Opts); case llvm::Triple::x86: if (Triple.isOSDarwin()) return std::make_unique(Triple, Opts); switch (os) { case llvm::Triple::Ananas: return std::make_unique>(Triple, Opts); case llvm::Triple::CloudABI: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: { switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::Android: return std::make_unique(Triple, Opts); } } case llvm::Triple::DragonFly: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Fuchsia: return std::make_unique>(Triple, Opts); case llvm::Triple::KFreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Minix: return std::make_unique>(Triple, Opts); case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); case llvm::Triple::Win32: { switch (Triple.getEnvironment()) { case llvm::Triple::Cygnus: return std::make_unique(Triple, Opts); case llvm::Triple::GNU: return std::make_unique(Triple, Opts); case llvm::Triple::Itanium: case llvm::Triple::MSVC: default: // Assume MSVC for unknown environments return std::make_unique(Triple, Opts); } } case llvm::Triple::Haiku: return std::make_unique(Triple, Opts); case llvm::Triple::RTEMS: return std::make_unique(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); case llvm::Triple::ELFIAMCU: return std::make_unique(Triple, Opts); case llvm::Triple::Hurd: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::x86_64: if (Triple.isOSDarwin() || Triple.isOSBinFormatMachO()) return std::make_unique(Triple, Opts); switch (os) { case llvm::Triple::Ananas: return std::make_unique>(Triple, Opts); case llvm::Triple::CloudABI: return std::make_unique>(Triple, Opts); case llvm::Triple::Linux: { switch (Triple.getEnvironment()) { default: return std::make_unique>(Triple, Opts); case llvm::Triple::Android: return std::make_unique(Triple, Opts); case llvm::Triple::OpenHOS: return std::make_unique(Triple, Opts); } } case llvm::Triple::DragonFly: return std::make_unique>(Triple, Opts); case llvm::Triple::NetBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::OpenBSD: return std::make_unique(Triple, Opts); case llvm::Triple::FreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Fuchsia: return std::make_unique>(Triple, Opts); case llvm::Triple::KFreeBSD: return std::make_unique>(Triple, Opts); case llvm::Triple::Solaris: return std::make_unique>(Triple, Opts); case llvm::Triple::Win32: { switch (Triple.getEnvironment()) { case llvm::Triple::Cygnus: return std::make_unique(Triple, Opts); case llvm::Triple::GNU: return std::make_unique(Triple, Opts); case llvm::Triple::MSVC: default: // Assume MSVC for unknown environments return std::make_unique(Triple, Opts); } } case llvm::Triple::Haiku: return std::make_unique>(Triple, Opts); case llvm::Triple::NaCl: return std::make_unique>(Triple, Opts); case llvm::Triple::PS4: return std::make_unique>(Triple, Opts); case llvm::Triple::PS5: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::spir: { if (os != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return nullptr; return std::make_unique(Triple, Opts); } case llvm::Triple::spir64: { if (os != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return nullptr; return std::make_unique(Triple, Opts); } case llvm::Triple::spirv32: { if (os != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return nullptr; return std::make_unique(Triple, Opts); } case llvm::Triple::spirv64: { if (os != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) return nullptr; return std::make_unique(Triple, Opts); } case llvm::Triple::wasm32: if (Triple.getSubArch() != llvm::Triple::NoSubArch || Triple.getVendor() != llvm::Triple::UnknownVendor || !Triple.isOSBinFormatWasm()) return nullptr; switch (os) { case llvm::Triple::WASI: return std::make_unique>(Triple, Opts); case llvm::Triple::Emscripten: return std::make_unique>( Triple, Opts); case llvm::Triple::UnknownOS: return std::make_unique>( Triple, Opts); default: return nullptr; } case llvm::Triple::wasm64: if (Triple.getSubArch() != llvm::Triple::NoSubArch || Triple.getVendor() != llvm::Triple::UnknownVendor || !Triple.isOSBinFormatWasm()) return nullptr; switch (os) { case llvm::Triple::WASI: return std::make_unique>(Triple, Opts); case llvm::Triple::Emscripten: return std::make_unique>( Triple, Opts); case llvm::Triple::UnknownOS: return std::make_unique>( Triple, Opts); default: return nullptr; } case llvm::Triple::dxil: return std::make_unique(Triple, Opts); case llvm::Triple::renderscript32: return std::make_unique>(Triple, Opts); case llvm::Triple::renderscript64: return std::make_unique>(Triple, Opts); case llvm::Triple::ve: return std::make_unique>(Triple, Opts); case llvm::Triple::csky: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::loongarch32: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } case llvm::Triple::loongarch64: switch (os) { case llvm::Triple::Linux: return std::make_unique>(Triple, Opts); default: return std::make_unique(Triple, Opts); } } } } // namespace targets } // namespace clang using namespace clang::targets; /// CreateTargetInfo - Return the target info object for the specified target /// options. TargetInfo * TargetInfo::CreateTargetInfo(DiagnosticsEngine &Diags, const std::shared_ptr &Opts) { llvm::Triple Triple(Opts->Triple); // Construct the target std::unique_ptr Target = AllocateTarget(Triple, *Opts); if (!Target) { Diags.Report(diag::err_target_unknown_triple) << Triple.str(); return nullptr; } Target->TargetOpts = Opts; // Set the target CPU if specified. if (!Opts->CPU.empty() && !Target->setCPU(Opts->CPU)) { Diags.Report(diag::err_target_unknown_cpu) << Opts->CPU; SmallVector ValidList; Target->fillValidCPUList(ValidList); if (!ValidList.empty()) Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", "); return nullptr; } // Check the TuneCPU name if specified. if (!Opts->TuneCPU.empty() && !Target->isValidTuneCPUName(Opts->TuneCPU)) { Diags.Report(diag::err_target_unknown_cpu) << Opts->TuneCPU; SmallVector ValidList; Target->fillValidTuneCPUList(ValidList); if (!ValidList.empty()) Diags.Report(diag::note_valid_options) << llvm::join(ValidList, ", "); return nullptr; } // Set the target ABI if specified. if (!Opts->ABI.empty() && !Target->setABI(Opts->ABI)) { Diags.Report(diag::err_target_unknown_abi) << Opts->ABI; return nullptr; } // Set the fp math unit. if (!Opts->FPMath.empty() && !Target->setFPMath(Opts->FPMath)) { Diags.Report(diag::err_target_unknown_fpmath) << Opts->FPMath; return nullptr; } // Compute the default target features, we need the target to handle this // because features may have dependencies on one another. llvm::erase_if(Opts->FeaturesAsWritten, [&](StringRef Name) { if (Target->isReadOnlyFeature(Name.substr(1))) { Diags.Report(diag::warn_fe_backend_readonly_feature_flag) << Name; return true; } return false; }); if (!Target->initFeatureMap(Opts->FeatureMap, Diags, Opts->CPU, Opts->FeaturesAsWritten)) return nullptr; // Add the features to the compile options. Opts->Features.clear(); for (const auto &F : Opts->FeatureMap) Opts->Features.push_back((F.getValue() ? "+" : "-") + F.getKey().str()); // Sort here, so we handle the features in a predictable order. (This matters // when we're dealing with features that overlap.) llvm::sort(Opts->Features); if (!Target->handleTargetFeatures(Opts->Features, Diags)) return nullptr; Target->setSupportedOpenCLOpts(); Target->setCommandLineOpenCLOpts(); Target->setMaxAtomicWidth(); if (!Opts->DarwinTargetVariantTriple.empty()) Target->DarwinTargetVariantTriple = llvm::Triple(Opts->DarwinTargetVariantTriple); if (!Target->validateTarget(Diags)) return nullptr; Target->CheckFixedPointBits(); return Target.release(); } /// validateOpenCLTarget - Check that OpenCL target has valid /// options setting based on OpenCL version. bool TargetInfo::validateOpenCLTarget(const LangOptions &Opts, DiagnosticsEngine &Diags) const { const llvm::StringMap &OpenCLFeaturesMap = getSupportedOpenCLOpts(); auto diagnoseNotSupportedCore = [&](llvm::StringRef Name, auto... OptArgs) { if (OpenCLOptions::isOpenCLOptionCoreIn(Opts, OptArgs...) && !hasFeatureEnabled(OpenCLFeaturesMap, Name)) Diags.Report(diag::warn_opencl_unsupported_core_feature) << Name << Opts.OpenCLCPlusPlus << Opts.getOpenCLVersionTuple().getAsString(); }; #define OPENCL_GENERIC_EXTENSION(Ext, ...) \ diagnoseNotSupportedCore(#Ext, __VA_ARGS__); #include "clang/Basic/OpenCLExtensions.def" // Validate that feature macros are set properly for OpenCL C 3.0. // In other cases assume that target is always valid. if (Opts.getOpenCLCompatibleVersion() < 300) return true; return OpenCLOptions::diagnoseUnsupportedFeatureDependencies(*this, Diags) && OpenCLOptions::diagnoseFeatureExtensionDifferences(*this, Diags); }