[clang] [clang-tools-extra] [clang][clang-tools-extra] Consume CommonOptionsParser errors in tools (PR #193675)

Zeyi Xu via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 23 00:14:17 PDT 2026


https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/193675

>From 6410444529314150244a4d2ad10c606064a62f1e Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Thu, 23 Apr 2026 14:59:34 +0800
Subject: [PATCH 1/2] [clang][clang-tools-extra] Consume CommonOptionsParser
 errors in tools

---
 .../tool/ClangChangeNamespace.cpp                   |  2 +-
 .../find-all-symbols/tool/FindAllSymbolsMain.cpp    |  2 +-
 .../clang-include-fixer/tool/ClangIncludeFixer.cpp  |  2 +-
 clang-tools-extra/clang-move/tool/ClangMove.cpp     |  2 +-
 .../tool/ClangReorderFields.cpp                     |  2 +-
 clang-tools-extra/docs/ReleaseNotes.rst             |  8 +++++---
 .../test/argument-parsing-error-no-abort.cpp        | 13 +++++++++++++
 clang/include/clang/Tooling/CommonOptionsParser.h   |  2 +-
 .../Refactor/argument-parsing-error-no-abort.cpp    |  2 ++
 .../Tooling/argument-parsing-error-no-abort.cpp     |  4 ++++
 clang/tools/clang-check/ClangCheck.cpp              |  2 +-
 clang/tools/clang-refactor/ClangRefactor.cpp        |  2 +-
 12 files changed, 32 insertions(+), 11 deletions(-)
 create mode 100644 clang-tools-extra/test/argument-parsing-error-no-abort.cpp
 create mode 100644 clang/test/Refactor/argument-parsing-error-no-abort.cpp
 create mode 100644 clang/test/Tooling/argument-parsing-error-no-abort.cpp

diff --git a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
index 2efdd9223dfba..e5bd971a68c1e 100644
--- a/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
+++ b/clang-tools-extra/clang-change-namespace/tool/ClangChangeNamespace.cpp
@@ -102,7 +102,7 @@ int main(int argc, const char **argv) {
   auto ExpectedParser =
       tooling::CommonOptionsParser::create(argc, argv, ChangeNamespaceCategory);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
   tooling::CommonOptionsParser &OptionsParser = ExpectedParser.get();
diff --git a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
index 6bac717bbb013..995006e183569 100644
--- a/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
+++ b/clang-tools-extra/clang-include-fixer/find-all-symbols/tool/FindAllSymbolsMain.cpp
@@ -131,7 +131,7 @@ int main(int argc, const char **argv) {
   auto ExpectedParser =
       CommonOptionsParser::create(argc, argv, FindAllSymbolsCategory);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
 
diff --git a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
index 568cb2b83d79a..f983b9d590542 100644
--- a/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
+++ b/clang-tools-extra/clang-include-fixer/tool/ClangIncludeFixer.cpp
@@ -264,7 +264,7 @@ int includeFixerMain(int argc, const char **argv) {
   auto ExpectedParser =
       tooling::CommonOptionsParser::create(argc, argv, IncludeFixerCategory);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
   tooling::CommonOptionsParser &options = ExpectedParser.get();
diff --git a/clang-tools-extra/clang-move/tool/ClangMove.cpp b/clang-tools-extra/clang-move/tool/ClangMove.cpp
index 1be3cb1e3b9ca..d36ce89b611f5 100644
--- a/clang-tools-extra/clang-move/tool/ClangMove.cpp
+++ b/clang-tools-extra/clang-move/tool/ClangMove.cpp
@@ -99,7 +99,7 @@ int main(int argc, const char **argv) {
   auto ExpectedParser =
       tooling::CommonOptionsParser::create(argc, argv, ClangMoveCategory);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
   tooling::CommonOptionsParser &OptionsParser = ExpectedParser.get();
diff --git a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
index fbfce07bb7512..33b49f20afa86 100644
--- a/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
+++ b/clang-tools-extra/clang-reorder-fields/tool/ClangReorderFields.cpp
@@ -53,7 +53,7 @@ int main(int argc, const char **argv) {
   auto ExpectedParser = tooling::CommonOptionsParser::create(
       argc, argv, ClangReorderFieldsCategory, cl::OneOrMore, Usage);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
 
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index f70bf9e9f9eb8..cf195ba58df70 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -337,9 +337,9 @@ Changes in existing checks
 
 - Improved :doc:`cppcoreguidelines-missing-std-forward
   <clang-tidy/checks/cppcoreguidelines/missing-std-forward>` check:
-  
+
   - Fixed false positive for constrained template parameters
-  
+
   - Fixed false positive with ``std::forward`` in brace-init and paren-init
     lambda captures such as ``[t{std::forward<T>(t)}]``.
 
@@ -508,7 +508,7 @@ Changes in existing checks
 
   - Fixed incorrect naming style application to C++17 structured bindings.
 
-  - Fixed a false positive where function templates could be diagnosed as generic 
+  - Fixed a false positive where function templates could be diagnosed as generic
     identifiers when `DefaultCase` was enabled.
 
 - Improved :doc:`readability-implicit-bool-conversion
@@ -576,6 +576,8 @@ Improvements to include-fixer
 Improvements to clang-include-fixer
 -----------------------------------
 
+- Fixed crashes when command-line argument parsing failed at unknown tool options.
+
 Improvements to modularize
 --------------------------
 
diff --git a/clang-tools-extra/test/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..fa192e14b49d9
--- /dev/null
+++ b/clang-tools-extra/test/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,13 @@
+// RUN: not clang-move --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-MOVE
+// RUN: not clang-reorder-fields --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-REORDER-FIELDS
+// RUN: not clang-change-namespace --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-CHANGE-NAMESPACE
+// RUN: not clang-include-fixer --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-INCLUDE-FIXER
+// RUN: not find-all-symbols --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=FIND-ALL-SYMBOLS
+
+// CLANG-MOVE: clang-move: Unknown command line argument '--nonsense'
+// CLANG-REORDER-FIELDS: clang-reorder-fields: Unknown command line argument '--nonsense'
+// CLANG-CHANGE-NAMESPACE: clang-change-namespace: Unknown command line argument '--nonsense'
+// CLANG-INCLUDE-FIXER: clang-include-fixer: Unknown command line argument '--nonsense'
+// FIND-ALL-SYMBOLS: find-all-symbols: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang/include/clang/Tooling/CommonOptionsParser.h b/clang/include/clang/Tooling/CommonOptionsParser.h
index 5e2cdc6ac4589..09310fd9d2d4e 100644
--- a/clang/include/clang/Tooling/CommonOptionsParser.h
+++ b/clang/include/clang/Tooling/CommonOptionsParser.h
@@ -57,7 +57,7 @@ namespace tooling {
 ///   auto ExpectedParser =
 ///       CommonOptionsParser::create(argc, argv, MyToolCategory);
 ///   if (!ExpectedParser) {
-///     llvm::errs() << ExpectedParser.takeError();
+///     llvm::errs() << llvm::toString(ExpectedParser.takeError());
 ///     return 1;
 ///   }
 ///   CommonOptionsParser& OptionsParser = ExpectedParser.get();
diff --git a/clang/test/Refactor/argument-parsing-error-no-abort.cpp b/clang/test/Refactor/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..50c84df0b8dfd
--- /dev/null
+++ b/clang/test/Refactor/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,2 @@
+// RUN: not clang-refactor --nonsense 2>&1 | FileCheck %s
+// CHECK: clang-refactor: Unknown command line argument '--nonsense'
diff --git a/clang/test/Tooling/argument-parsing-error-no-abort.cpp b/clang/test/Tooling/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..20e7b1bf3ea6c
--- /dev/null
+++ b/clang/test/Tooling/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not clang-check --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: clang-check: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang/tools/clang-check/ClangCheck.cpp b/clang/tools/clang-check/ClangCheck.cpp
index 80255c647b98f..7672b59b35482 100644
--- a/clang/tools/clang-check/ClangCheck.cpp
+++ b/clang/tools/clang-check/ClangCheck.cpp
@@ -203,7 +203,7 @@ int main(int argc, const char **argv) {
   auto ExpectedParser =
       CommonOptionsParser::create(argc, argv, ClangCheckCategory);
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
   CommonOptionsParser &OptionsParser = ExpectedParser.get();
diff --git a/clang/tools/clang-refactor/ClangRefactor.cpp b/clang/tools/clang-refactor/ClangRefactor.cpp
index a92b3f91beaed..d011bf30a7c5c 100644
--- a/clang/tools/clang-refactor/ClangRefactor.cpp
+++ b/clang/tools/clang-refactor/ClangRefactor.cpp
@@ -617,7 +617,7 @@ int main(int argc, const char **argv) {
       argc, argv, cl::getGeneralCategory(), cl::ZeroOrMore,
       "Clang-based refactoring tool for C, C++ and Objective-C");
   if (!ExpectedParser) {
-    llvm::errs() << ExpectedParser.takeError();
+    llvm::errs() << llvm::toString(ExpectedParser.takeError());
     return 1;
   }
   CommonOptionsParser &Options = ExpectedParser.get();

>From 3cb03537d6295d1cf954d7e2a97c8fbe4e338a04 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Thu, 23 Apr 2026 15:13:57 +0800
Subject: [PATCH 2/2] fixup

---
 .../test/argument-parsing-error-no-abort.cpp        | 13 -------------
 .../argument-parsing-error-no-abort.cpp             |  4 ++++
 .../argument-parsing-error-no-abort.cpp             |  4 ++++
 .../argument-parsing-error-no-abort.cpp             |  4 ++++
 .../clang-move/argument-parsing-error-no-abort.cpp  |  4 ++++
 .../argument-parsing-error-no-abort.cpp             |  4 ++++
 6 files changed, 20 insertions(+), 13 deletions(-)
 delete mode 100644 clang-tools-extra/test/argument-parsing-error-no-abort.cpp
 create mode 100644 clang-tools-extra/test/clang-change-namespace/argument-parsing-error-no-abort.cpp
 create mode 100644 clang-tools-extra/test/clang-include-fixer/argument-parsing-error-no-abort.cpp
 create mode 100644 clang-tools-extra/test/clang-include-fixer/find-all-symbols/argument-parsing-error-no-abort.cpp
 create mode 100644 clang-tools-extra/test/clang-move/argument-parsing-error-no-abort.cpp
 create mode 100644 clang-tools-extra/test/clang-reorder-fields/argument-parsing-error-no-abort.cpp

diff --git a/clang-tools-extra/test/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/argument-parsing-error-no-abort.cpp
deleted file mode 100644
index fa192e14b49d9..0000000000000
--- a/clang-tools-extra/test/argument-parsing-error-no-abort.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-// RUN: not clang-move --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-MOVE
-// RUN: not clang-reorder-fields --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-REORDER-FIELDS
-// RUN: not clang-change-namespace --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-CHANGE-NAMESPACE
-// RUN: not clang-include-fixer --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=CLANG-INCLUDE-FIXER
-// RUN: not find-all-symbols --nonsense %s -- 2>&1 | FileCheck %s --check-prefix=FIND-ALL-SYMBOLS
-
-// CLANG-MOVE: clang-move: Unknown command line argument '--nonsense'
-// CLANG-REORDER-FIELDS: clang-reorder-fields: Unknown command line argument '--nonsense'
-// CLANG-CHANGE-NAMESPACE: clang-change-namespace: Unknown command line argument '--nonsense'
-// CLANG-INCLUDE-FIXER: clang-include-fixer: Unknown command line argument '--nonsense'
-// FIND-ALL-SYMBOLS: find-all-symbols: Unknown command line argument '--nonsense'
-
-int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-change-namespace/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/clang-change-namespace/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..2ec529eadf2a5
--- /dev/null
+++ b/clang-tools-extra/test/clang-change-namespace/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not clang-change-namespace --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: clang-change-namespace: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-include-fixer/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/clang-include-fixer/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..2079ee22deb46
--- /dev/null
+++ b/clang-tools-extra/test/clang-include-fixer/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not clang-include-fixer --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: clang-include-fixer: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-include-fixer/find-all-symbols/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/clang-include-fixer/find-all-symbols/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..89a19eb7644cf
--- /dev/null
+++ b/clang-tools-extra/test/clang-include-fixer/find-all-symbols/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not find-all-symbols --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: find-all-symbols: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-move/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/clang-move/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..7efda7ee06405
--- /dev/null
+++ b/clang-tools-extra/test/clang-move/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not clang-move --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: clang-move: Unknown command line argument '--nonsense'
+
+int main() { return 0; }
diff --git a/clang-tools-extra/test/clang-reorder-fields/argument-parsing-error-no-abort.cpp b/clang-tools-extra/test/clang-reorder-fields/argument-parsing-error-no-abort.cpp
new file mode 100644
index 0000000000000..195e1f1ba4a9f
--- /dev/null
+++ b/clang-tools-extra/test/clang-reorder-fields/argument-parsing-error-no-abort.cpp
@@ -0,0 +1,4 @@
+// RUN: not clang-reorder-fields --nonsense %s -- 2>&1 | FileCheck %s
+// CHECK: clang-reorder-fields: Unknown command line argument '--nonsense'
+
+int main() { return 0; }



More information about the cfe-commits mailing list