P4C
The P4 Compiler
Loading...
Searching...
No Matches
lib/exceptions.h
1/*
2Copyright 2013-present Barefoot Networks, Inc.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17/* -*-c++-*- */
18
19#ifndef LIB_EXCEPTIONS_H_
20#define LIB_EXCEPTIONS_H_
21
22#include <unistd.h>
23
24#include <exception>
25
26#include <boost/format.hpp>
27
28#include "absl/strings/str_cat.h"
29#include "lib/bug_helper.h"
30
31namespace P4::Util {
32
33// colors to pretty print messages
34// \e is non-standard escape sequence, use codepoint \33 instead
35constexpr char ANSI_RED[] = "\33[31m";
36constexpr char ANSI_BLUE[] = "\33[34m";
37constexpr char ANSI_CLR[] = "\33[0m";
38
41inline bool is_cerr_redirected() {
42 static bool initialized(false);
43 static bool is_redir;
44 if (!initialized) {
45 initialized = true;
46 is_redir = ttyname(fileno(stderr)) == nullptr; // NOLINT(runtime/threadsafe_fn)
47 }
48 return is_redir;
49}
50
52inline const char *cerr_colorize(const char *color) {
53 if (is_cerr_redirected()) {
54 return "";
55 }
56 return color;
57}
58
60inline const char *cerr_clear_colors() {
61 if (is_cerr_redirected()) {
62 return "";
63 }
64 return ANSI_CLR;
65}
66
70class P4CExceptionBase : public std::exception {
71 protected:
72 std::string message;
73 void traceCreation() {}
74
75 public:
76 template <typename... Args>
77 explicit P4CExceptionBase(const char *format, Args &&...args) {
78 traceCreation();
79 boost::format fmt(format);
80 // FIXME: This will implicitly take location of the first argument having
81 // SourceInfo. Not sure if this always desireable or not.
82 message = ::P4::bug_helper(fmt, "", "", std::forward<Args>(args)...);
83 }
84
85 const char *what() const noexcept override { return message.c_str(); }
86};
87
89class CompilerBug final : public P4CExceptionBase {
90 public:
91 template <typename... Args>
92 explicit CompilerBug(const char *format, Args &&...args)
93 : P4CExceptionBase(format, std::forward<Args>(args)...) {
94 // Check if output is redirected and if so, then don't color text so that
95 // escape characters are not present
96 message = absl::StrCat(cerr_colorize(ANSI_RED), "Compiler Bug", cerr_clear_colors(), ":\n",
97 message);
98 }
99
100 template <typename... Args>
101 CompilerBug(int line, const char *file, const char *format, Args &&...args)
102 : P4CExceptionBase(format, std::forward<Args>(args)...) {
103 message = absl::StrCat("In file: ", file, ":", line, "\n", cerr_colorize(ANSI_RED),
104 "Compiler Bug", cerr_clear_colors(), ": ", message);
105 }
106};
107
109class CompilerUnimplemented final : public P4CExceptionBase {
110 public:
111 template <typename... Args>
112 explicit CompilerUnimplemented(const char *format, Args &&...args)
113 : P4CExceptionBase(format, std::forward<Args>(args)...) {
114 // Do not add colors when redirecting to stderr
115 message = absl::StrCat(cerr_colorize(ANSI_BLUE), "Not yet implemented", cerr_clear_colors(),
116 ":\n", message);
117 }
118
119 template <typename... Args>
120 CompilerUnimplemented(int line, const char *file, const char *format, Args &&...args)
121 : P4CExceptionBase(format, std::forward<Args>(args)...) {
122 message =
123 absl::StrCat("In file: ", file, ":", line, "\n", cerr_colorize(ANSI_BLUE),
124 "Unimplemented compiler support", cerr_clear_colors(), ": ", message);
125 }
126};
127
130class CompilationError : public P4CExceptionBase {
131 public:
132 template <typename... Args>
133 explicit CompilationError(const char *format, Args &&...args)
134 : P4CExceptionBase(format, std::forward<Args>(args)...) {}
135};
136
138#define BUG(...) \
139 do { \
140 throw P4::Util::CompilerBug(__LINE__, __FILE__, __VA_ARGS__); \
141 } while (0)
142#define BUG_CHECK(e, ...) \
143 do { \
144 if (!(e)) BUG(__VA_ARGS__); \
145 } while (0)
146#define P4C_UNIMPLEMENTED(...) \
147 do { \
148 throw P4::Util::CompilerUnimplemented(__LINE__, __FILE__, __VA_ARGS__); \
149 } while (0)
150
151} // namespace P4::Util
152
154#define FATAL_ERROR(...) \
155 do { \
156 throw P4::Util::CompilationError(__VA_ARGS__); \
157 } while (0)
158
159#endif /* LIB_EXCEPTIONS_H_ */