Index: include/clang/Basic/Cuda.h =================================================================== --- include/clang/Basic/Cuda.h +++ include/clang/Basic/Cuda.h @@ -46,6 +46,7 @@ SM_62, SM_70, SM_72, + LAST, }; const char *CudaArchToString(CudaArch A); Index: include/clang/Basic/DiagnosticCommonKinds.td =================================================================== --- include/clang/Basic/DiagnosticCommonKinds.td +++ include/clang/Basic/DiagnosticCommonKinds.td @@ -188,6 +188,7 @@ def err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; +def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< "micromips is not supported for target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; Index: include/clang/Basic/TargetInfo.h =================================================================== --- include/clang/Basic/TargetInfo.h +++ include/clang/Basic/TargetInfo.h @@ -867,6 +867,9 @@ return false; } + /// Fill a SmallVectorImpl with the valid values to setCPU. + virtual void fillValidCPUList(SmallVectorImpl &Values) const {} + /// brief Determine whether this TargetInfo supports the given CPU name. virtual bool isValidCPUName(StringRef Name) const { return true; Index: lib/Basic/Cuda.cpp =================================================================== --- lib/Basic/Cuda.cpp +++ lib/Basic/Cuda.cpp @@ -26,6 +26,8 @@ const char *CudaArchToString(CudaArch A) { switch (A) { + case CudaArch::LAST: + break; case CudaArch::UNKNOWN: return "unknown"; case CudaArch::SM_20: @@ -133,6 +135,8 @@ CudaVirtualArch VirtualArchForCudaArch(CudaArch A) { switch (A) { + case CudaArch::LAST: + break; case CudaArch::UNKNOWN: return CudaVirtualArch::UNKNOWN; case CudaArch::SM_20: @@ -168,6 +172,8 @@ CudaVersion MinVersionForCudaArch(CudaArch A) { switch (A) { + case CudaArch::LAST: + break; case CudaArch::UNKNOWN: return CudaVersion::UNKNOWN; case CudaArch::SM_20: Index: lib/Basic/Targets.cpp =================================================================== --- lib/Basic/Targets.cpp +++ lib/Basic/Targets.cpp @@ -38,6 +38,7 @@ #include "Targets/X86.h" #include "Targets/XCore.h" #include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" using namespace clang; @@ -607,6 +608,10 @@ // 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; } Index: lib/Basic/Targets/AArch64.h =================================================================== --- lib/Basic/Targets/AArch64.h +++ lib/Basic/Targets/AArch64.h @@ -46,6 +46,7 @@ bool setABI(const std::string &Name) override; bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; bool setCPU(const std::string &Name) override; bool useFP16ConversionIntrinsics() const override { Index: lib/Basic/Targets/AArch64.cpp =================================================================== --- lib/Basic/Targets/AArch64.cpp +++ lib/Basic/Targets/AArch64.cpp @@ -101,6 +101,11 @@ return isValidCPUName(Name); } +void AArch64TargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + llvm::AArch64::fillValidCPUArchList(Values); +} + void AArch64TargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("__ARM_FEATURE_QRDMX", "1"); Index: lib/Basic/Targets/AMDGPU.h =================================================================== --- lib/Basic/Targets/AMDGPU.h +++ lib/Basic/Targets/AMDGPU.h @@ -219,6 +219,8 @@ return GK_NONE != parseR600Name(Name); } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { if (getTriple().getArch() == llvm::Triple::amdgcn) GPU = parseAMDGCNName(Name); Index: lib/Basic/Targets/AMDGPU.cpp =================================================================== --- lib/Basic/Targets/AMDGPU.cpp +++ lib/Basic/Targets/AMDGPU.cpp @@ -296,6 +296,24 @@ .Default(GK_NONE); } +void AMDGPUTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + if (getTriple().getArch() == llvm::Triple::amdgcn) + Values.append({"gfx600", "tahiti", "gfx601", "pitcairn", "verde", + "oland", "hainan", "gfx700", "bonaire", "kaveri", + "gfx701", "hawaii", "gfx702", "gfx703", "kabini", + "mullins", "gfx800", "iceland", "gfx801", "carrizo", + "gfx802", "tonga", "gfx803", "fiji", "polaris10", + "polaris11", "gfx804", "gfx810", "stoney", "gfx900", + "gfx901", "gfx902", "gfx903"}); + else + Values.append({"r600", "rv610", "rv620", "rv630", "rv635", + "rs780", "rs880", "rv670", "rv710", "rv730", + "rv740", "rv770", "palm", "cedar", "sumo", + "sumo2", "redwood", "juniper", "hemlock", "cypress", + "barts", "turks", "caicos", "cayman", "aruba"}); +} + void AMDGPUTargetInfo::setAddressSpaceMap(bool DefaultIsPrivate) { if (isGenericZero(getTriple())) { AddrSpaceMap = DefaultIsPrivate ? &AMDGPUGenIsZeroDefIsPrivMap Index: lib/Basic/Targets/ARM.h =================================================================== --- lib/Basic/Targets/ARM.h +++ lib/Basic/Targets/ARM.h @@ -122,6 +122,8 @@ bool hasFeature(StringRef Feature) const override; bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override; bool setFPMath(StringRef Name) override; Index: lib/Basic/Targets/ARM.cpp =================================================================== --- lib/Basic/Targets/ARM.cpp +++ lib/Basic/Targets/ARM.cpp @@ -478,6 +478,10 @@ llvm::ARM::parseCPUArch(Name) != llvm::ARM::ArchKind::INVALID; } +void ARMTargetInfo::fillValidCPUList(SmallVectorImpl &Values) const { + llvm::ARM::fillValidCPUArchList(Values); +} + bool ARMTargetInfo::setCPU(const std::string &Name) { if (Name != "generic") setArchInfo(llvm::ARM::parseCPUArch(Name)); Index: lib/Basic/Targets/AVR.h =================================================================== --- lib/Basic/Targets/AVR.h +++ lib/Basic/Targets/AVR.h @@ -167,6 +167,7 @@ } bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; bool setCPU(const std::string &Name) override { bool isValid = isValidCPUName(Name); if (isValid) Index: lib/Basic/Targets/AVR.cpp =================================================================== --- lib/Basic/Targets/AVR.cpp +++ lib/Basic/Targets/AVR.cpp @@ -302,6 +302,13 @@ return IsFamily || IsMCU; } +void AVRTargetInfo::fillValidCPUList(SmallVectorImpl &Values) const { + Values.append({"avr1", "avr2", "avr25", "avr3", "avr31", "avr35", "avr4", + "avr5", "avr51", "avr6", "avrxmega1", "avrxmega2", "avrxmega3", + "avrxmega4", "avrxmega5", "avrxmega6", "avrxmega7", + "avrtiny"}); +} + void AVRTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { Builder.defineMacro("AVR"); Index: lib/Basic/Targets/BPF.h =================================================================== --- lib/Basic/Targets/BPF.h +++ lib/Basic/Targets/BPF.h @@ -84,6 +84,10 @@ return false; } + void fillValidCPUList(SmallVectorImpl &Values) const override { + Values.append({"generic", "v1", "v2", "probe"}); + } + bool setCPU(const std::string &Name) override { StringRef CPUName(Name); return isValidCPUName(CPUName); Index: lib/Basic/Targets/Hexagon.h =================================================================== --- lib/Basic/Targets/Hexagon.h +++ lib/Basic/Targets/Hexagon.h @@ -112,6 +112,8 @@ return getHexagonCPUSuffix(Name); } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { if (!isValidCPUName(Name)) return false; Index: lib/Basic/Targets/Hexagon.cpp =================================================================== --- lib/Basic/Targets/Hexagon.cpp +++ lib/Basic/Targets/Hexagon.cpp @@ -152,6 +152,12 @@ .Default(nullptr); } +void HexagonTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append({"hexagonv4", "hexagonv5", "hexagonv55", "hexagonv60", + "hexagonv62", "hexagonv65"}); +} + ArrayRef HexagonTargetInfo::getTargetBuiltins() const { return llvm::makeArrayRef(BuiltinInfo, clang::Hexagon::LastTSBuiltin - Builtin::FirstTSBuiltin); Index: lib/Basic/Targets/Lanai.h =================================================================== --- lib/Basic/Targets/Lanai.h +++ lib/Basic/Targets/Lanai.h @@ -65,6 +65,8 @@ bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override; bool hasFeature(StringRef Feature) const override; Index: lib/Basic/Targets/Lanai.cpp =================================================================== --- lib/Basic/Targets/Lanai.cpp +++ lib/Basic/Targets/Lanai.cpp @@ -40,6 +40,10 @@ bool LanaiTargetInfo::isValidCPUName(StringRef Name) const { return llvm::StringSwitch(Name).Case("v11", true).Default(false); } +void LanaiTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.emplace_back("v11"); +} bool LanaiTargetInfo::setCPU(const std::string &Name) { CPU = llvm::StringSwitch(Name).Case("v11", CK_V11).Default(CK_NONE); Index: lib/Basic/Targets/Mips.h =================================================================== --- lib/Basic/Targets/Mips.h +++ lib/Basic/Targets/Mips.h @@ -161,6 +161,7 @@ } bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; bool setCPU(const std::string &Name) override { CPU = Name; Index: lib/Basic/Targets/Mips.cpp =================================================================== --- lib/Basic/Targets/Mips.cpp +++ lib/Basic/Targets/Mips.cpp @@ -66,6 +66,14 @@ .Default(false); } +void MipsTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append({"mips1", "mips2", "mips3", "mips4", "mips5", "mips32", + "mips32r2", "mips32r3", "mips32r5", "mips32r6", "mips64", + "mips64r2", "mips64r3", "mips64r5", "mips64r6", "octeon", + "p5600"}); +} + void MipsTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { if (BigEndian) { Index: lib/Basic/Targets/NVPTX.h =================================================================== --- lib/Basic/Targets/NVPTX.h +++ lib/Basic/Targets/NVPTX.h @@ -98,6 +98,12 @@ return StringToCudaArch(Name) != CudaArch::UNKNOWN; } + void fillValidCPUList(SmallVectorImpl &Values) const override { + for (int i = static_cast(CudaArch::SM_20); + i < static_cast(CudaArch::LAST); ++i) + Values.emplace_back(CudaArchToString(static_cast(i))); + } + bool setCPU(const std::string &Name) override { GPU = StringToCudaArch(Name); return GPU != CudaArch::UNKNOWN; Index: lib/Basic/Targets/NVPTX.cpp =================================================================== --- lib/Basic/Targets/NVPTX.cpp +++ lib/Basic/Targets/NVPTX.cpp @@ -157,6 +157,8 @@ // Set __CUDA_ARCH__ for the GPU specified. std::string CUDAArchCode = [this] { switch (GPU) { + case CudaArch::LAST: + break; case CudaArch::UNKNOWN: assert(false && "No GPU arch when compiling CUDA device code."); return ""; Index: lib/Basic/Targets/Nios2.h =================================================================== --- lib/Basic/Targets/Nios2.h +++ lib/Basic/Targets/Nios2.h @@ -56,6 +56,10 @@ return Name == "nios2r1" || Name == "nios2r2"; } + void fillValidCPUList(SmallVectorImpl &Values) const override { + Values.append({"nios2r1", "nios2r2"}); + } + bool setCPU(const std::string &Name) override { if (isValidCPUName(Name)) { CPU = Name; Index: lib/Basic/Targets/PPC.h =================================================================== --- lib/Basic/Targets/PPC.h +++ lib/Basic/Targets/PPC.h @@ -86,6 +86,7 @@ // 821, 823, 8540, 8548, e300c2, e300c3, e500mc64, e6500, 860, cell, // titan, rs64. bool isValidCPUName(StringRef Name) const override; + void fillValidCPUList(SmallVectorImpl &Values) const override; bool setCPU(const std::string &Name) override { bool CPUKnown = isValidCPUName(Name); Index: lib/Basic/Targets/PPC.cpp =================================================================== --- lib/Basic/Targets/PPC.cpp +++ lib/Basic/Targets/PPC.cpp @@ -532,6 +532,18 @@ .Default(false); } +void PPCTargetInfo::fillValidCPUList(SmallVectorImpl &Values) const { + Values.append( + {"generic", "440", "450", "601", "602", "603", + "603e", "603ev", "604", "604e", "620", "630", + "g3", "7400", "g4", "7450", "g4+", "750", + "970", "g5", "a2", "a2q", "e500mc", "e5500", + "power3", "pwr3", "power4", "pwr4", "power5", "pwr5", + "power5x", "pwr5x", "power6", "pwr6", "power6x", "pwr6x", + "power7", "pwr7", "power8", "pwr8", "power9", "pwr9", + "powerpc", "ppc", "powerpc64", "ppc64", "powerpc64le", "ppc64le"}); +} + void PPCTargetInfo::adjust(LangOptions &Opts) { if (HasAltivec) Opts.AltiVec = 1; Index: lib/Basic/Targets/Sparc.h =================================================================== --- lib/Basic/Targets/Sparc.h +++ lib/Basic/Targets/Sparc.h @@ -180,6 +180,8 @@ return getCPUKind(Name) != CK_GENERIC; } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { CPU = getCPUKind(Name); return CPU != CK_GENERIC; @@ -259,6 +261,8 @@ return getCPUGeneration(SparcTargetInfo::getCPUKind(Name)) == CG_V9; } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { if (!SparcTargetInfo::setCPU(Name)) return false; Index: lib/Basic/Targets/Sparc.cpp =================================================================== --- lib/Basic/Targets/Sparc.cpp +++ lib/Basic/Targets/Sparc.cpp @@ -96,6 +96,19 @@ .Default(CK_GENERIC); } +void SparcTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append( + {"v8", "supersparc", "sparclite", "f934", "hypersparc", + "sparclite86x", "sparclet", "tsc701", "v9", "ultrasparc", + "ultrasparc3", "niagara", "niagara2", "niagara3", "niagara4", + "ma2100", "ma2150", "ma2155", "ma2450", "ma2455", + "ma2x5x", "ma2080", "ma2085", "ma2480", "ma2485", + "ma2x8x", "myriad2", "myriad2.1", "myriad2.2", "myriad2.3", + "leon2", "at697e", "at697f", "leon3", "ut699", + "gr712rc", "leon4", "gr740"}); +} + void SparcTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { DefineStd(Builder, "sparc", Opts); @@ -195,3 +208,8 @@ Builder.defineMacro("__sparcv9__"); } } +void SparcV9TargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append({"v9", "ultrasparc", "ultrasparc3", "niagra", "niagra2", + "niagra3", "niagra4"}); +} Index: lib/Basic/Targets/SystemZ.h =================================================================== --- lib/Basic/Targets/SystemZ.h +++ lib/Basic/Targets/SystemZ.h @@ -82,6 +82,8 @@ return getISARevision(Name) != -1; } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { CPU = Name; ISARevision = getISARevision(CPU); Index: lib/Basic/Targets/SystemZ.cpp =================================================================== --- lib/Basic/Targets/SystemZ.cpp +++ lib/Basic/Targets/SystemZ.cpp @@ -93,6 +93,12 @@ .Default(-1); } +void SystemZTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append({"arch8", "arch9", "arch10", "arch11", "arch12", "z10", "z196", + "zEC12", "z13", "z14"}); +} + bool SystemZTargetInfo::hasFeature(StringRef Feature) const { return llvm::StringSwitch(Feature) .Case("systemz", true) Index: lib/Basic/Targets/WebAssembly.h =================================================================== --- lib/Basic/Targets/WebAssembly.h +++ lib/Basic/Targets/WebAssembly.h @@ -74,6 +74,7 @@ DiagnosticsEngine &Diags) final; bool isValidCPUName(StringRef Name) const final; + void fillValidCPUList(SmallVectorImpl &Values) const final; bool setCPU(const std::string &Name) final { return isValidCPUName(Name); } Index: lib/Basic/Targets/WebAssembly.cpp =================================================================== --- lib/Basic/Targets/WebAssembly.cpp +++ lib/Basic/Targets/WebAssembly.cpp @@ -45,6 +45,11 @@ .Default(false); } +void WebAssemblyTargetInfo::fillValidCPUList( + SmallVectorImpl &Values) const { + Values.append({"mvp", "bleeding-edge", "generic"}); +} + void WebAssemblyTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { defineCPUMacros(Builder, "wasm", /*Tuning=*/false); Index: lib/Basic/Targets/X86.h =================================================================== --- lib/Basic/Targets/X86.h +++ lib/Basic/Targets/X86.h @@ -264,6 +264,8 @@ return checkCPUKind(getCPUKind(Name)); } + void fillValidCPUList(SmallVectorImpl &Values) const override; + bool setCPU(const std::string &Name) override { return checkCPUKind(CPU = getCPUKind(Name)); } Index: lib/Basic/Targets/X86.cpp =================================================================== --- lib/Basic/Targets/X86.cpp +++ lib/Basic/Targets/X86.cpp @@ -15,6 +15,7 @@ #include "clang/Basic/Builtins.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/TargetBuiltins.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/TargetParser.h" @@ -1648,8 +1649,6 @@ bool X86TargetInfo::checkCPUKind(CPUKind Kind) const { // Perform any per-CPU checks necessary to determine if this CPU is // acceptable. - // FIXME: This results in terrible diagnostics. Clang just says the CPU is - // invalid without explaining *why*. switch (Kind) { case CK_Generic: // No processor selected! @@ -1662,6 +1661,12 @@ llvm_unreachable("Unhandled CPU kind"); } +void X86TargetInfo::fillValidCPUList(SmallVectorImpl &Values) const { +#define PROC(ENUM, STRING, IS64BIT) Values.emplace_back(STRING); +#define PROC_ALIAS(ENUM, ALIAS) Values.emplace_back(ALIAS); +#include "clang/Basic/X86Target.def" +} + X86TargetInfo::CPUKind X86TargetInfo::getCPUKind(StringRef CPU) const { return llvm::StringSwitch(CPU) #define PROC(ENUM, STRING, IS64BIT) .Case(STRING, CK_##ENUM) Index: test/Misc/target-parser.c =================================================================== --- test/Misc/target-parser.c +++ test/Misc/target-parser.c @@ -1,2 +1,3 @@ // RUN: not %clang_cc1 -triple armv7--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s // CHECK: error: unknown target CPU 'not-a-cpu' +// //CHECK: note: valid target CPU values are: