[clang-tools-extra] ff94ba6 - [clang-doc] Refactor error handling to use ExitOnError (#141699)

via cfe-commits cfe-commits at lists.llvm.org
Fri May 30 13:34:18 PDT 2025


Author: Samarth Narang
Date: 2025-05-30T13:34:15-07:00
New Revision: ff94ba613e2fab918d5d96c57833ee3f6e3f3015

URL: https://github.com/llvm/llvm-project/commit/ff94ba613e2fab918d5d96c57833ee3f6e3f3015
DIFF: https://github.com/llvm/llvm-project/commit/ff94ba613e2fab918d5d96c57833ee3f6e3f3015.diff

LOG: [clang-doc] Refactor error handling to use ExitOnError (#141699)

This patch refactors the clang-doc tool to replace manual error handling
(e.g., checking error codes and calling exit()) with llvm::ExitOnError.

Fixes #140085

Added: 
    clang-tools-extra/test/clang-doc/invalid-options.cpp

Modified: 
    clang-tools-extra/clang-doc/tool/ClangDocMain.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
index 41fbe87a713d9..8253ef298db4d 100644
--- a/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ b/clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -118,6 +118,8 @@ static llvm::cl::opt<OutputFormatTy> FormatEnum(
                                 "Documentation in mustache HTML format")),
     llvm::cl::init(OutputFormatTy::yaml), llvm::cl::cat(ClangDocCategory));
 
+static llvm::ExitOnError ExitOnErr;
+
 static std::string getFormatString() {
   switch (FormatEnum) {
   case OutputFormatTy::yaml:
@@ -245,10 +247,30 @@ sortUsrToInfo(llvm::StringMap<std::unique_ptr<doc::Info>> &USRToInfo) {
   }
 }
 
+static llvm::Error handleMappingFailures(llvm::Error Err) {
+  if (!Err)
+    return llvm::Error::success();
+  if (IgnoreMappingFailures) {
+    llvm::errs() << "Error mapping decls in files. Clang-doc will ignore these "
+                    "files and continue:\n"
+                 << toString(std::move(Err)) << "\n";
+    return llvm::Error::success();
+  }
+  return Err;
+}
+
+static llvm::Error createDirectories(llvm::StringRef OutDirectory) {
+  if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory))
+    return llvm::createFileError(OutDirectory, Err);
+  return llvm::Error::success();
+}
+
 int main(int argc, const char **argv) {
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
   std::error_code OK;
 
+  ExitOnErr.setBanner("clang-doc error: ");
+
   const char *Overview =
       R"(Generates documentation from source code and comments.
 
@@ -261,22 +283,13 @@ Example usage for a project using a compile commands database:
   $ clang-doc --executor=all-TUs compile_commands.json
 )";
 
-  auto Executor = clang::tooling::createExecutorFromCommandLineArgs(
-      argc, argv, ClangDocCategory, Overview);
-
-  if (!Executor) {
-    llvm::errs() << toString(Executor.takeError()) << "\n";
-    return 1;
-  }
+  auto Executor = ExitOnErr(clang::tooling::createExecutorFromCommandLineArgs(
+      argc, argv, ClangDocCategory, Overview));
 
   // Fail early if an invalid format was provided.
   std::string Format = getFormatString();
   llvm::outs() << "Emiting docs in " << Format << " format.\n";
-  auto G = doc::findGeneratorByName(Format);
-  if (!G) {
-    llvm::errs() << toString(G.takeError()) << "\n";
-    return 1;
-  }
+  auto G = ExitOnErr(doc::findGeneratorByName(Format));
 
   ArgumentsAdjuster ArgAdjuster;
   if (!DoxygenOnly)
@@ -286,7 +299,7 @@ Example usage for a project using a compile commands database:
         ArgAdjuster);
 
   clang::doc::ClangDocContext CDCtx = {
-      Executor->get()->getExecutionContext(),
+      Executor->getExecutionContext(),
       ProjectName,
       PublicOnly,
       OutDirectory,
@@ -297,40 +310,24 @@ Example usage for a project using a compile commands database:
       {UserStylesheets.begin(), UserStylesheets.end()}};
 
   if (Format == "html") {
-    if (auto Err = getHtmlAssetFiles(argv[0], CDCtx)) {
-      llvm::errs() << toString(std::move(Err)) << "\n";
-      return 1;
-    }
+    ExitOnErr(getHtmlAssetFiles(argv[0], CDCtx));
   }
 
   if (Format == "mustache") {
-    if (auto Err = getMustacheHtmlFiles(argv[0], CDCtx)) {
-      llvm::errs() << toString(std::move(Err)) << "\n";
-      return 1;
-    }
+    ExitOnErr(getMustacheHtmlFiles(argv[0], CDCtx));
   }
 
   // Mapping phase
   llvm::outs() << "Mapping decls...\n";
-  auto Err =
-      Executor->get()->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster);
-  if (Err) {
-    if (IgnoreMappingFailures)
-      llvm::errs() << "Error mapping decls in files. Clang-doc will ignore "
-                      "these files and continue:\n"
-                   << toString(std::move(Err)) << "\n";
-    else {
-      llvm::errs() << toString(std::move(Err)) << "\n";
-      return 1;
-    }
-  }
+  ExitOnErr(handleMappingFailures(
+      Executor->execute(doc::newMapperActionFactory(CDCtx), ArgAdjuster)));
 
   // Collect values into output by key.
   // In ToolResults, the Key is the hashed USR and the value is the
   // bitcode-encoded representation of the Info object.
   llvm::outs() << "Collecting infos...\n";
   llvm::StringMap<std::vector<StringRef>> USRToBitcode;
-  Executor->get()->getToolResults()->forEachResult(
+  Executor->getToolResults()->forEachResult(
       [&](StringRef Key, StringRef Value) {
         USRToBitcode[Key].emplace_back(Value);
       });
@@ -391,25 +388,13 @@ Example usage for a project using a compile commands database:
   sortUsrToInfo(USRToInfo);
 
   // Ensure the root output directory exists.
-  if (std::error_code Err = llvm::sys::fs::create_directories(OutDirectory);
-      Err != std::error_code()) {
-    llvm::errs() << "Failed to create directory '" << OutDirectory << "'\n";
-    return 1;
-  }
+  ExitOnErr(createDirectories(OutDirectory));
 
   // Run the generator.
   llvm::outs() << "Generating docs...\n";
-  if (auto Err =
-          G->get()->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx)) {
-    llvm::errs() << toString(std::move(Err)) << "\n";
-    return 1;
-  }
-
+  ExitOnErr(G->generateDocs(OutDirectory, std::move(USRToInfo), CDCtx));
   llvm::outs() << "Generating assets for docs...\n";
-  Err = G->get()->createResources(CDCtx);
-  if (Err) {
-    llvm::outs() << "warning: " << toString(std::move(Err)) << "\n";
-  }
+  ExitOnErr(G->createResources(CDCtx));
 
   return 0;
 }

diff  --git a/clang-tools-extra/test/clang-doc/invalid-options.cpp b/clang-tools-extra/test/clang-doc/invalid-options.cpp
new file mode 100644
index 0000000000000..c8a4cef8364eb
--- /dev/null
+++ b/clang-tools-extra/test/clang-doc/invalid-options.cpp
@@ -0,0 +1,29 @@
+/// Invalid output path (%t is a file, not a directory).
+// RUN: rm -rf %t && touch %t
+// RUN: not clang-doc %s -output=%t/subdir 2>&1 | FileCheck %s --check-prefix=OUTPUT-FAIL
+// OUTPUT-FAIL: clang-doc error:
+// OUTPUT-FAIL: {{(Not a directory|no such file or directory)}}
+
+/// Invalid format option.
+// RUN: rm -rf %t && mkdir %t && touch %t/file
+// RUN: not clang-doc %s --output=%t/file -format=badformat 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
+// BAD-FORMAT: clang-doc: for the --format option: Cannot find option named 'badformat'!
+
+/// Missing HTML asset directory (warning only).
+// RUN: clang-doc %s -format=html -asset=%t/nonexistent-assets 2>&1 | FileCheck %s --check-prefix=ASSET-WARN
+// ASSET-WARN: Asset path supply is not a directory
+
+/// Mapping failure (with --ignore-map-errors=false).
+// RUN: not clang-doc %t/nonexistent.cpp -ignore-map-errors=false 2>&1 | FileCheck %s --check-prefix=MAP-FAIL
+// MAP-FAIL: clang-doc error: Failed to run action
+
+/// Mapping failure (with --ignore-map-errors=true).
+// RUN: clang-doc %t/nonexistent.cpp 2>&1 | FileCheck %s --check-prefix=MAP-WARN
+// MAP-WARN: Error mapping decls in files. Clang-doc will ignore these files and continue
+
+///Invalid executor type
+// RUN: not clang-doc --executor=invalid %s 2>&1 | FileCheck %s --check-prefix=EXECUTOR-FAIL
+// EXECUTOR-FAIL: clang-doc error:
+// EXECUTOR-FAIL: Executor "invalid" is not registered
+
+///TODO: Add tests for failures in generateDocs() and in createResources().


        


More information about the cfe-commits mailing list