https://github.com/jthackray updated 
https://github.com/llvm/llvm-project/pull/197640

>From b85fb447b6afdb741bb4f3da46db1c33a9299856 Mon Sep 17 00:00:00 2001
From: Jonathan Thackray <[email protected]>
Date: Wed, 13 May 2026 21:46:34 +0100
Subject: [PATCH] [AArch64][clang] Improve -mcpu= and -mtune= error messages
 too

Similar to my previous change improving the error message for
`-march=` in #197441, this changes `-mcpu=` and `-mtune=` arguments
to only report the invalid feature flag, rather than the entire
string.

This is a much clearer error message for the user.
---
 clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 60 +++++++++++---------
 clang/test/Driver/aarch64-march.c            | 13 +++++
 2 files changed, 47 insertions(+), 26 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp 
b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index f42465da14a71..7ed4002e53420 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -137,10 +137,9 @@ aarch64::getAArch64TargetTuneCPU(const llvm::opt::ArgList 
&Args,
 }
 
 // Decode AArch64 features from string like +[no]featureA+[no]featureB+...
-static bool
-DecodeAArch64Features(const Driver &D, StringRef text,
-                      llvm::AArch64::ExtensionSet &Extensions,
-                      std::optional<std::string> *InvalidArg = nullptr) {
+static bool DecodeAArch64Features(const Driver &D, StringRef text,
+                                  llvm::AArch64::ExtensionSet &Extensions,
+                                  std::optional<std::string> &InvalidArg) {
   SmallVector<StringRef, 8> Split;
   text.split(Split, StringRef("+"), -1, false);
 
@@ -150,8 +149,7 @@ DecodeAArch64Features(const Driver &D, StringRef text,
       continue;
     }
     if (!Extensions.parseModifier(Feature)) {
-      if (InvalidArg)
-        InvalidArg->emplace(("+" + Feature).str());
+      InvalidArg.emplace(("+" + Feature).str());
       return false;
     }
   }
@@ -180,7 +178,8 @@ static bool 
DecodeAArch64HostFeatures(llvm::AArch64::ExtensionSet &Extensions) {
 // Check if the CPU name and feature modifiers in -mcpu are legal. If yes,
 // decode CPU and feature.
 static bool DecodeAArch64Mcpu(const Driver &D, StringRef Mcpu,
-                              llvm::AArch64::ExtensionSet &Extensions) {
+                              llvm::AArch64::ExtensionSet &Extensions,
+                              std::optional<std::string> &InvalidArg) {
   std::pair<StringRef, StringRef> Split = Mcpu.split("+");
   StringRef CPU = Split.first;
   const bool IsNative = CPU == "native";
@@ -190,8 +189,10 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef 
Mcpu,
 
   const std::optional<llvm::AArch64::CpuInfo> CpuInfo =
       llvm::AArch64::parseCpu(CPU);
-  if (!CpuInfo)
+  if (!CpuInfo) {
+    InvalidArg.emplace(Split.first.str());
     return false;
+  }
 
   Extensions.addCPUDefaults(*CpuInfo);
 
@@ -199,7 +200,7 @@ static bool DecodeAArch64Mcpu(const Driver &D, StringRef 
Mcpu,
     return false;
 
   if (Split.second.size() &&
-      !DecodeAArch64Features(D, Split.second, Extensions))
+      !DecodeAArch64Features(D, Split.second, Extensions, InvalidArg))
     return false;
 
   return true;
@@ -214,7 +215,7 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef 
March,
   std::pair<StringRef, StringRef> Split = StringRef(MarchLowerCase).split("+");
 
   if (Split.first == "native")
-    return DecodeAArch64Mcpu(D, MarchLowerCase, Extensions);
+    return DecodeAArch64Mcpu(D, MarchLowerCase, Extensions, InvalidArg);
 
   const llvm::AArch64::ArchInfo *ArchInfo =
       llvm::AArch64::parseArch(Split.first);
@@ -226,7 +227,7 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, StringRef 
March,
   Extensions.addArchDefaults(*ArchInfo);
 
   if ((Split.second.size() &&
-       !DecodeAArch64Features(D, Split.second, Extensions, &InvalidArg)))
+       !DecodeAArch64Features(D, Split.second, Extensions, InvalidArg)))
     return false;
 
   return true;
@@ -235,23 +236,27 @@ getAArch64ArchFeaturesFromMarch(const Driver &D, 
StringRef March,
 static bool
 getAArch64ArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
                                const ArgList &Args,
-                               llvm::AArch64::ExtensionSet &Extensions) {
+                               llvm::AArch64::ExtensionSet &Extensions,
+                               std::optional<std::string> &InvalidArg) {
   std::string McpuLowerCase = Mcpu.lower();
-  return DecodeAArch64Mcpu(D, McpuLowerCase, Extensions);
+  return DecodeAArch64Mcpu(D, McpuLowerCase, Extensions, InvalidArg);
 }
 
-static bool getAArch64MicroArchFeaturesFromMtune(const Driver &D,
-                                                 StringRef Mtune,
-                                                 const ArgList &Args) {
+static bool
+getAArch64MicroArchFeaturesFromMtune(const Driver &D, StringRef Mtune,
+                                     const ArgList &Args,
+                                     std::optional<std::string> &InvalidArg) {
   // Check CPU name is valid, but ignore any extensions on it.
   std::string MtuneLowerCase = Mtune.lower();
   llvm::AArch64::ExtensionSet Extensions;
-  return DecodeAArch64Mcpu(D, MtuneLowerCase, Extensions);
+  return DecodeAArch64Mcpu(D, MtuneLowerCase, Extensions, InvalidArg);
 }
 
-static bool getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef 
Mcpu,
-                                                const ArgList &Args) {
-  return getAArch64MicroArchFeaturesFromMtune(D, Mcpu, Args);
+static bool
+getAArch64MicroArchFeaturesFromMcpu(const Driver &D, StringRef Mcpu,
+                                    const ArgList &Args,
+                                    std::optional<std::string> &InvalidArg) {
+  return getAArch64MicroArchFeaturesFromMtune(D, Mcpu, Args, InvalidArg);
 }
 
 void aarch64::getAArch64TargetFeatures(const Driver &D,
@@ -280,23 +285,26 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
     success = getAArch64ArchFeaturesFromMarch(D, A->getValue(), Args,
                                               Extensions, InvalidArg);
   else if ((A = Args.getLastArg(options::OPT_mcpu_EQ)))
-    success =
-        getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, Extensions);
+    success = getAArch64ArchFeaturesFromMcpu(D, A->getValue(), Args, 
Extensions,
+                                             InvalidArg);
   else if (isCPUDeterminedByTriple(Triple))
     success = getAArch64ArchFeaturesFromMcpu(
-        D, getAArch64TargetCPUByTriple(Triple), Args, Extensions);
+        D, getAArch64TargetCPUByTriple(Triple), Args, Extensions, InvalidArg);
   else
     // Default to 'A' profile if the architecture is not specified.
     success = getAArch64ArchFeaturesFromMarch(D, "armv8-a", Args, Extensions,
                                               InvalidArg);
 
   if (success && (A = Args.getLastArg(options::OPT_mtune_EQ)))
-    success = getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args);
+    success = getAArch64MicroArchFeaturesFromMtune(D, A->getValue(), Args,
+                                                   InvalidArg);
   else if (success && (A = Args.getLastArg(options::OPT_mcpu_EQ)))
-    success = getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args);
+    success =
+        getAArch64MicroArchFeaturesFromMcpu(D, A->getValue(), Args, 
InvalidArg);
   else if (success) {
     if (auto TuneCPU = getAArch64TargetTuneCPUByTriple(Triple))
-      success = getAArch64MicroArchFeaturesFromMtune(D, *TuneCPU, Args);
+      success =
+          getAArch64MicroArchFeaturesFromMtune(D, *TuneCPU, Args, InvalidArg);
   }
 
   if (!success) {
diff --git a/clang/test/Driver/aarch64-march.c 
b/clang/test/Driver/aarch64-march.c
index d2cea0e50def3..5a0dba3a7e7b7 100644
--- a/clang/test/Driver/aarch64-march.c
+++ b/clang/test/Driver/aarch64-march.c
@@ -36,3 +36,16 @@
 // INVALID-EXT: error: unsupported argument '+badfeature' to option '-march='
 // INVALID-EXT-NOT: 
armv9.6-a+sme2+sme2p1+sve2+sve2p1+badfeature+aes+sha2+memtag+bf16
 // INVALID-ARCH: error: unsupported argument 'notanarch' to option '-march='
+
+// ================== Check whether -mcpu diagnoses the first invalid argument.
+// RUN: not %clang --target=aarch64 -mcpu=generic+sme2+badfeature+aes %s -### 
-c 2>&1 | FileCheck -check-prefix=INVALID-MCPU-EXT %s
+// RUN: not %clang --target=aarch64 -mcpu=notacpu+sme2 %s -### -c 2>&1 | 
FileCheck -check-prefix=INVALID-MCPU %s
+// INVALID-MCPU-EXT: error: unsupported argument '+badfeature' to option 
'-mcpu='
+// INVALID-MCPU-EXT-NOT: generic+sme2+badfeature+aes
+// INVALID-MCPU: error: unsupported argument 'notacpu' to option '-mcpu='
+
+// ================== Check whether -mtune diagnoses the first invalid 
argument.
+// RUN: not %clang --target=aarch64 -mtune=generic+sme2+badfeature+aes %s -### 
-c 2>&1 | FileCheck -check-prefix=INVALID-MTUNE-EXT %s
+// RUN: not %clang --target=aarch64 -mtune=notacpu+sme2 %s -### -c 2>&1 | 
FileCheck -check-prefix=INVALID-MTUNE %s
+// INVALID-MTUNE-EXT: error: unsupported argument '+badfeature' to option 
'-mtune='
+// INVALID-MTUNE: error: unsupported argument 'notacpu' to option '-mtune='

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to