xref: /aosp_15_r20/external/stg/error.h (revision 9e3b08ae94a55201065475453d799e8b1378bea6)
1*9e3b08aeSAndroid Build Coastguard Worker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2*9e3b08aeSAndroid Build Coastguard Worker // -*- mode: C++ -*-
3*9e3b08aeSAndroid Build Coastguard Worker //
4*9e3b08aeSAndroid Build Coastguard Worker // Copyright 2021-2024 Google LLC
5*9e3b08aeSAndroid Build Coastguard Worker //
6*9e3b08aeSAndroid Build Coastguard Worker // Licensed under the Apache License v2.0 with LLVM Exceptions (the
7*9e3b08aeSAndroid Build Coastguard Worker // "License"); you may not use this file except in compliance with the
8*9e3b08aeSAndroid Build Coastguard Worker // License.  You may obtain a copy of the License at
9*9e3b08aeSAndroid Build Coastguard Worker //
10*9e3b08aeSAndroid Build Coastguard Worker //     https://llvm.org/LICENSE.txt
11*9e3b08aeSAndroid Build Coastguard Worker //
12*9e3b08aeSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
13*9e3b08aeSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
14*9e3b08aeSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15*9e3b08aeSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
16*9e3b08aeSAndroid Build Coastguard Worker // limitations under the License.
17*9e3b08aeSAndroid Build Coastguard Worker //
18*9e3b08aeSAndroid Build Coastguard Worker // Author: Giuliano Procida
19*9e3b08aeSAndroid Build Coastguard Worker 
20*9e3b08aeSAndroid Build Coastguard Worker #ifndef STG_ERROR_H_
21*9e3b08aeSAndroid Build Coastguard Worker #define STG_ERROR_H_
22*9e3b08aeSAndroid Build Coastguard Worker 
23*9e3b08aeSAndroid Build Coastguard Worker #include <exception>
24*9e3b08aeSAndroid Build Coastguard Worker #include <iostream>
25*9e3b08aeSAndroid Build Coastguard Worker #include <optional>
26*9e3b08aeSAndroid Build Coastguard Worker #include <ostream>
27*9e3b08aeSAndroid Build Coastguard Worker #include <sstream>
28*9e3b08aeSAndroid Build Coastguard Worker #include <string>
29*9e3b08aeSAndroid Build Coastguard Worker #include <system_error>
30*9e3b08aeSAndroid Build Coastguard Worker 
31*9e3b08aeSAndroid Build Coastguard Worker namespace stg {
32*9e3b08aeSAndroid Build Coastguard Worker 
33*9e3b08aeSAndroid Build Coastguard Worker class Exception : public std::exception {
34*9e3b08aeSAndroid Build Coastguard Worker  public:
Exception(const std::string & message)35*9e3b08aeSAndroid Build Coastguard Worker   explicit Exception(const std::string& message) {
36*9e3b08aeSAndroid Build Coastguard Worker     Add(message);
37*9e3b08aeSAndroid Build Coastguard Worker   }
38*9e3b08aeSAndroid Build Coastguard Worker 
what()39*9e3b08aeSAndroid Build Coastguard Worker   const char* what() const noexcept(true) final {
40*9e3b08aeSAndroid Build Coastguard Worker     return message_.c_str();
41*9e3b08aeSAndroid Build Coastguard Worker   }
42*9e3b08aeSAndroid Build Coastguard Worker 
Add(const std::string & message)43*9e3b08aeSAndroid Build Coastguard Worker   void Add(const std::string& message) {
44*9e3b08aeSAndroid Build Coastguard Worker     (message_ += message) += '\n';
45*9e3b08aeSAndroid Build Coastguard Worker   }
46*9e3b08aeSAndroid Build Coastguard Worker 
47*9e3b08aeSAndroid Build Coastguard Worker  private:
48*9e3b08aeSAndroid Build Coastguard Worker   std::string message_;
49*9e3b08aeSAndroid Build Coastguard Worker };
50*9e3b08aeSAndroid Build Coastguard Worker 
51*9e3b08aeSAndroid Build Coastguard Worker // Coded to give compilers a chance of making `Check(ok) << foo;` as efficient
52*9e3b08aeSAndroid Build Coastguard Worker // as `if (!ok) { Die() << foo; }`.
53*9e3b08aeSAndroid Build Coastguard Worker class Check {
54*9e3b08aeSAndroid Build Coastguard Worker  public:
55*9e3b08aeSAndroid Build Coastguard Worker   // These functions are all small and inlinable.
Check(bool ok)56*9e3b08aeSAndroid Build Coastguard Worker   explicit Check(bool ok)
57*9e3b08aeSAndroid Build Coastguard Worker       : os_(ok ? std::optional<std::ostringstream>()
58*9e3b08aeSAndroid Build Coastguard Worker                : std::make_optional<std::ostringstream>()) {}
noexcept(false)59*9e3b08aeSAndroid Build Coastguard Worker   ~Check() noexcept(false) {
60*9e3b08aeSAndroid Build Coastguard Worker     if (os_) {
61*9e3b08aeSAndroid Build Coastguard Worker       Throw(*os_);
62*9e3b08aeSAndroid Build Coastguard Worker     }
63*9e3b08aeSAndroid Build Coastguard Worker   }
64*9e3b08aeSAndroid Build Coastguard Worker 
65*9e3b08aeSAndroid Build Coastguard Worker   template <typename T>
66*9e3b08aeSAndroid Build Coastguard Worker   Check& operator<<(const T& t) {
67*9e3b08aeSAndroid Build Coastguard Worker     if (os_) {
68*9e3b08aeSAndroid Build Coastguard Worker       *os_ << t;
69*9e3b08aeSAndroid Build Coastguard Worker     }
70*9e3b08aeSAndroid Build Coastguard Worker     return *this;
71*9e3b08aeSAndroid Build Coastguard Worker   }
72*9e3b08aeSAndroid Build Coastguard Worker 
73*9e3b08aeSAndroid Build Coastguard Worker  private:
74*9e3b08aeSAndroid Build Coastguard Worker   std::optional<std::ostringstream> os_;
75*9e3b08aeSAndroid Build Coastguard Worker 
76*9e3b08aeSAndroid Build Coastguard Worker   // This helper is too large to inline.
Throw(const std::ostringstream & os)77*9e3b08aeSAndroid Build Coastguard Worker   [[noreturn]] static void Throw(const std::ostringstream& os) {
78*9e3b08aeSAndroid Build Coastguard Worker     throw Exception(os.str());
79*9e3b08aeSAndroid Build Coastguard Worker   }
80*9e3b08aeSAndroid Build Coastguard Worker };
81*9e3b08aeSAndroid Build Coastguard Worker 
82*9e3b08aeSAndroid Build Coastguard Worker class Die {
83*9e3b08aeSAndroid Build Coastguard Worker  public:
~Die()84*9e3b08aeSAndroid Build Coastguard Worker   [[noreturn]] ~Die() noexcept(false) {
85*9e3b08aeSAndroid Build Coastguard Worker     throw Exception(os_.str());
86*9e3b08aeSAndroid Build Coastguard Worker   }
87*9e3b08aeSAndroid Build Coastguard Worker 
88*9e3b08aeSAndroid Build Coastguard Worker   template <typename T>
89*9e3b08aeSAndroid Build Coastguard Worker   Die& operator<<(const T& t) {
90*9e3b08aeSAndroid Build Coastguard Worker     os_ << t;
91*9e3b08aeSAndroid Build Coastguard Worker     return *this;
92*9e3b08aeSAndroid Build Coastguard Worker   }
93*9e3b08aeSAndroid Build Coastguard Worker 
94*9e3b08aeSAndroid Build Coastguard Worker  private:
95*9e3b08aeSAndroid Build Coastguard Worker   std::ostringstream os_;
96*9e3b08aeSAndroid Build Coastguard Worker };
97*9e3b08aeSAndroid Build Coastguard Worker 
98*9e3b08aeSAndroid Build Coastguard Worker class Warn {
99*9e3b08aeSAndroid Build Coastguard Worker  public:
~Warn()100*9e3b08aeSAndroid Build Coastguard Worker   ~Warn() {
101*9e3b08aeSAndroid Build Coastguard Worker     std::cerr << "warning: " << os_.str() << '\n';
102*9e3b08aeSAndroid Build Coastguard Worker   }
103*9e3b08aeSAndroid Build Coastguard Worker 
104*9e3b08aeSAndroid Build Coastguard Worker   template <typename T>
105*9e3b08aeSAndroid Build Coastguard Worker   Warn& operator<<(const T& t) {
106*9e3b08aeSAndroid Build Coastguard Worker     os_ << t;
107*9e3b08aeSAndroid Build Coastguard Worker     return *this;
108*9e3b08aeSAndroid Build Coastguard Worker   }
109*9e3b08aeSAndroid Build Coastguard Worker 
110*9e3b08aeSAndroid Build Coastguard Worker  private:
111*9e3b08aeSAndroid Build Coastguard Worker   std::ostringstream os_;
112*9e3b08aeSAndroid Build Coastguard Worker };
113*9e3b08aeSAndroid Build Coastguard Worker 
114*9e3b08aeSAndroid Build Coastguard Worker struct Error {
ErrorError115*9e3b08aeSAndroid Build Coastguard Worker   explicit Error(int number) : number(number) {}
116*9e3b08aeSAndroid Build Coastguard Worker   int number;
117*9e3b08aeSAndroid Build Coastguard Worker };
118*9e3b08aeSAndroid Build Coastguard Worker 
119*9e3b08aeSAndroid Build Coastguard Worker inline std::ostream& operator<<(std::ostream& os, Error error) {
120*9e3b08aeSAndroid Build Coastguard Worker   return os << std::system_error(error.number, std::generic_category()).what();
121*9e3b08aeSAndroid Build Coastguard Worker }
122*9e3b08aeSAndroid Build Coastguard Worker 
123*9e3b08aeSAndroid Build Coastguard Worker }  // namespace stg
124*9e3b08aeSAndroid Build Coastguard Worker 
125*9e3b08aeSAndroid Build Coastguard Worker #endif  // STG_ERROR_H_
126