1//===- ErrorBuilder.cpp ---------------------------------------------------===//
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#include "clang/Analysis/Scalable/Support/ErrorBuilder.h"
10#include "llvm/ADT/STLExtras.h"
11#include "llvm/ADT/StringExtras.h"
12#include <cassert>
13
14namespace clang::ssaf {
15
16static constexpr llvm::StringLiteral ErrorSeparator = " + ";
17static constexpr llvm::StringLiteral ContextSeparator = "\n";
18
19ErrorBuilder ErrorBuilder::wrap(llvm::Error E) {
20 assert(
21 E &&
22 "Cannot wrap a success error - check for success before calling wrap()");
23
24 std::optional<std::error_code> EC;
25 std::vector<std::string> Messages;
26
27 llvm::handleAllErrors(E: std::move(E), Handlers: [&](const llvm::ErrorInfoBase &EI) {
28 // Capture error code from the first error only.
29 if (!EC)
30 EC = EI.convertToErrorCode();
31
32 // Collect messages from all errors.
33 std::string ErrorMsg = EI.message();
34 if (!ErrorMsg.empty())
35 Messages.push_back(x: std::move(ErrorMsg));
36 });
37
38 assert(EC && "wrap() called with a non-success error but no handler fired - "
39 "indicates a bug in handleAllErrors");
40
41 ErrorBuilder Builder(*EC);
42
43 // Combine all messages with " + " and push as a single context entry.
44 Builder.pushContext(Msg: llvm::join(R&: Messages, Separator: ErrorSeparator));
45
46 return Builder;
47}
48
49ErrorBuilder &ErrorBuilder::context(const char *Msg) {
50 pushContext(Msg: std::string(Msg));
51 return *this;
52}
53
54llvm::Error ErrorBuilder::build() const {
55 // Reverse the context stack so that the most recent context appears first
56 // and the wrapped error (if any) appears last.
57 // Note: Even if ContextStack is empty, we create an error with the stored
58 // error code and an empty message (this is valid in LLVM).
59 return llvm::createStringError(
60 Msg: llvm::join(R: llvm::reverse(C: ContextStack), Separator: ContextSeparator), EC: Code);
61}
62
63} // namespace clang::ssaf
64