clang 23.0.0git
ErrorBuilder.h
Go to the documentation of this file.
1//===- ErrorBuilder.h - Fluent API for contextual errors --------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the ErrorBuilder class, which provides a fluent API for
10// constructing contextual error messages with layered context information.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_ANALYSIS_SCALABLE_SUPPORT_ERRORBUILDER_H
15#define LLVM_CLANG_ANALYSIS_SCALABLE_SUPPORT_ERRORBUILDER_H
16
17#include "llvm/Support/Error.h"
18#include "llvm/Support/FormatVariadic.h"
19#include <optional>
20#include <string>
21#include <system_error>
22#include <vector>
23
24namespace clang::ssaf {
25
26/// Fluent API for constructing contextual errors.
27///
28/// ErrorBuilder allows building error messages with layered context
29/// information. Context is added innermost to outermost, and the final
30/// error message presents the context in reverse order (outermost first).
31///
32/// Example usage:
33/// \code
34/// return ErrorBuilder::create(std::errc::invalid_argument,
35/// "invalid value {0}", value)
36/// .context("processing field '{0}'", fieldName)
37/// .context("reading configuration")
38/// .build();
39/// \endcode
40class ErrorBuilder {
41 std::error_code Code;
42 std::vector<std::string> ContextStack;
43
44 explicit ErrorBuilder(std::error_code EC) : Code(EC) {}
45
46 void pushContext(std::string Msg) {
47 if (!Msg.empty()) {
48 ContextStack.push_back(std::move(Msg));
49 }
50 }
51
52 template <typename... Args>
53 static std::string formatErrorMessage(const char *Fmt, Args &&...ArgVals) {
54 return llvm::formatv(Fmt, std::forward<Args>(ArgVals)...).str();
55 }
56
57 template <typename... Args>
58 void addFormattedContext(const char *Fmt, Args &&...ArgVals) {
59 pushContext(formatErrorMessage(Fmt, std::forward<Args>(ArgVals)...));
60 }
61
62public:
63 /// Create an ErrorBuilder with an error code and formatted message.
64 ///
65 /// \param EC The error code for this error.
66 /// \param Fmt Format string for the error message (using llvm::formatv).
67 /// \param ArgVals Arguments for the format string.
68 /// \returns A new ErrorBuilder with the initial error message.
69 ///
70 /// Example:
71 /// \code
72 /// return ErrorBuilder::create(std::errc::invalid_argument,
73 /// "invalid value: {0}", 42)
74 /// .build();
75 /// \endcode
76 template <typename... Args>
77 static ErrorBuilder create(std::error_code EC, const char *Fmt,
78 Args &&...ArgVals) {
79 ErrorBuilder Builder(EC);
80 Builder.addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
81 return Builder;
82 }
83
84 /// Convenience overload that accepts std::errc instead of std::error_code.
85 ///
86 /// \param EC The error condition for this error.
87 /// \param Fmt Format string for the error message.
88 /// \param ArgVals Arguments for the format string.
89 /// \returns A new ErrorBuilder with the initial error message.
90 template <typename... Args>
91 static ErrorBuilder create(std::errc EC, const char *Fmt, Args &&...ArgVals) {
92 return create(std::make_error_code(EC), Fmt,
93 std::forward<Args>(ArgVals)...);
94 }
95
96 /// Wrap an existing error and optionally add context.
97 ///
98 /// Extracts the error code and message(s) from the given error. If multiple
99 /// errors are joined (via llvm::joinErrors), their messages are combined
100 /// using " + " separator.
101 ///
102 /// \param E The error to wrap. Must be a failure (cannot be success).
103 /// \returns A new ErrorBuilder containing the wrapped error information.
104 ///
105 /// \pre E must evaluate to true (i.e., must be a failure). Wrapping
106 /// Error::success() is a programming error and will trigger an
107 /// assertion failure in debug builds.
108 ///
109 /// Example:
110 /// \code
111 /// if (auto Err = foo())
112 /// return ErrorBuilder::wrap(std::move(Err))
113 /// .context("while processing file")
114 /// .build();
115 /// \endcode
116 static ErrorBuilder wrap(llvm::Error E);
117
118 /// Add context information as a plain string.
119 ///
120 /// Empty strings are ignored and not added to the context stack.
121 ///
122 /// \param Msg Context message to add. Must be a null-terminated string.
123 /// \returns Reference to this ErrorBuilder for method chaining.
124 ///
125 /// Example:
126 /// \code
127 /// return ErrorBuilder::create(...)
128 /// .context("reading configuration file")
129 /// .build();
130 /// \endcode
131 ErrorBuilder &context(const char *Msg);
132
133 /// Add context information with formatted string.
134 ///
135 /// Uses llvm::formatv for formatting. Empty messages (after formatting)
136 /// are ignored and not added to the context stack.
137 ///
138 /// \param Fmt Format string (using llvm::formatv syntax).
139 /// \param ArgVals Arguments for the format string.
140 /// \returns Reference to this ErrorBuilder for method chaining.
141 ///
142 /// Example:
143 /// \code
144 /// return ErrorBuilder::create(...)
145 /// .context("processing field '{0}'", fieldName)
146 /// .context("at line {0}, column {1}", line, col)
147 /// .build();
148 /// \endcode
149 template <typename... Args>
150 ErrorBuilder &context(const char *Fmt, Args &&...ArgVals) {
151 addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
152 return *this;
153 }
154
155 /// Build and return the final error.
156 ///
157 /// Constructs an llvm::Error with all accumulated context. The context
158 /// is presented in reverse order: most recent context first, original
159 /// error message last. Each context layer is separated by a newline.
160 ///
161 /// \returns An llvm::Error containing the error code and formatted message.
162 /// Even if no context was added (empty context stack), an error
163 /// with the stored error code is returned.
164 ///
165 /// \pre The ErrorBuilder must have been created via \c create() or \c wrap().
166 /// Constructing an ErrorBuilder directly is not supported.
167 ///
168 /// Example output:
169 /// \code
170 /// ErrorBuilder::create(errc::invalid_argument, "value is 42")
171 /// .context("processing field 'age'")
172 /// .context("reading config")
173 /// .build();
174 ///
175 /// // Produces:
176 /// // "reading config
177 /// // processing field 'age'
178 /// // value is 42"
179 /// \endcode
180 llvm::Error build() const;
181
182 /// Report a fatal error with formatted message and terminate execution.
183 ///
184 /// Combines llvm::formatv and llvm::report_fatal_error. This is a static
185 /// utility method for reporting unrecoverable errors that indicate bugs
186 /// or corrupted data.
187 ///
188 /// \param Fmt Format string for the error message (using llvm::formatv).
189 /// \param ArgVals Arguments for the format string.
190 ///
191 /// \pre \p Fmt must be a valid llvm::formatv format string with the correct
192 /// number and types of arguments. An invalid format string is undefined
193 /// behaviour.
194 ///
195 /// Example:
196 /// \code
197 /// ErrorBuilder::fatal("Entity {0} with {1} linkage already exists",
198 /// entityId, linkageType);
199 /// \endcode
200 template <typename... Args>
201 [[noreturn]] static void fatal(const char *Fmt, Args &&...ArgVals) {
202 llvm::report_fatal_error(llvm::StringRef(
203 formatErrorMessage(Fmt, std::forward<Args>(ArgVals)...)));
204 }
205};
206
207} // namespace clang::ssaf
208
209#endif // LLVM_CLANG_ANALYSIS_SCALABLE_SUPPORT_ERRORBUILDER_H
Fluent API for constructing contextual errors.
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
static void fatal(const char *Fmt, Args &&...ArgVals)
Report a fatal error with formatted message and terminate execution.
static ErrorBuilder create(std::errc EC, const char *Fmt, Args &&...ArgVals)
Convenience overload that accepts std::errc instead of std::error_code.
ErrorBuilder & context(const char *Fmt, Args &&...ArgVals)
Add context information with formatted string.
ErrorBuilder & context(const char *Msg)
Add context information as a plain string.
llvm::Error build() const
Build and return the final error.
static ErrorBuilder wrap(llvm::Error E)
Wrap an existing error and optionally add context.
#define noreturn
Definition stdnoreturn.h:17