P4C
The P4 Compiler
Loading...
Searching...
No Matches
bug_helper.h
1/*
2Licensed under the Apache License, Version 2.0 (the "License");
3you may not use this file except in compliance with the License.
4You may obtain a copy of the License at
5
6 http://www.apache.org/licenses/LICENSE-2.0
7
8Unless required by applicable law or agreed to in writing, software
9distributed under the License is distributed on an "AS IS" BASIS,
10WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11See the License for the specific language governing permissions and
12limitations under the License.
13*/
14
15/* -*-c++-*- */
16
17#ifndef LIB_BUG_HELPER_H_
18#define LIB_BUG_HELPER_H_
19
20#include <ostream>
21#include <sstream>
22#include <string>
23#include <string_view>
24#include <utility>
25
26#include <boost/format.hpp>
27
28#include "absl/strings/str_cat.h"
29#include "cstring.h"
30#include "source_file.h"
31#include "stringify.h"
32
33namespace P4 {
34namespace detail {
35
36static inline std::pair<std::string_view, std::string> getPositionTail(const Util::SourceInfo &info,
37 std::string_view position,
38 std::string_view tail) {
39 std::string_view posString = info.toPositionString().string_view();
40 std::string outTail(tail);
41 if (position.empty()) {
42 position = posString;
43 } else {
44 outTail.append(posString);
45 if (!posString.empty()) outTail.append("\n");
46 }
47 outTail += info.toSourceFragment();
48
49 return std::pair(position, outTail);
50}
51
52template <typename T>
53std::pair<std::string_view, std::string> maybeAddSourceInfo(const T &t, std::string_view position,
54 std::string_view tail) {
55 if constexpr (Util::has_SourceInfo_v<T>)
56 return getPositionTail(t.getSourceInfo(), position, tail);
57
58 (void)position;
59 (void)tail;
60 return {"", ""};
61}
62
63static inline std::string bug_helper(boost::format &f, std::string_view position,
64 std::string_view tail) {
65 return absl::StrCat(position, position.empty() ? "" : ": ", boost::str(f), "\n", tail);
66}
67
68template <typename T, class... Args>
69auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T *t,
70 Args &&...args);
71
72template <typename T, class... Args>
73auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T &t,
74 Args &&...args) -> std::enable_if_t<!std::is_pointer_v<T>, std::string>;
75
76template <class... Args>
77std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail,
78 const char *t, Args &&...args) {
79 return bug_helper(f % t, position, tail, std::forward<Args>(args)...);
80}
81
82template <class... Args>
83std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail,
84 const Util::SourceInfo &info, Args &&...args) {
85 auto [outPos, outTail] = detail::getPositionTail(info, position, tail);
86 return bug_helper(f % "", outPos, outTail, std::forward<Args>(args)...);
87}
88
89template <class T>
91 const T *val;
92};
93
94template <class T>
95std::ostream &operator<<(std::ostream &os, const DbprintDispatchPtr<T> &dispatch) {
96 if constexpr (has_dbprint_v<T>) {
97 dispatch.val->dbprint(os);
98 } else {
99 static_assert(has_ostream_operator_v<decltype(dispatch.val)>,
100 "cannot debug print this type, implement dbprint method");
101 os << dispatch.val;
102 }
103
104 return os;
105}
106
107template <typename T, class... Args>
108auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T *t,
109 Args &&...args) {
110 if (t == nullptr) return bug_helper(f, position, tail, std::forward<Args>(args)...);
111
112 auto [outPos, outTail] = maybeAddSourceInfo(*t, position, tail);
113 return bug_helper(f % DbprintDispatchPtr<T>{t}, outPos, outTail, std::forward<Args>(args)...);
114}
115
116template <class T>
118 const T &val;
119};
120
121template <class T>
122std::ostream &operator<<(std::ostream &os, const DbprintDispatchRef<T> &dispatch) {
123 if constexpr (has_dbprint_v<T>) {
124 dispatch.val.dbprint(os);
125 } else {
126 static_assert(has_ostream_operator_v<decltype(dispatch.val)>,
127 "cannot debug print this type, implement dbprint method");
128 os << dispatch.val;
129 }
130
131 return os;
132}
133
134template <typename T, class... Args>
135auto bug_helper(boost::format &f, std::string_view position, std::string_view tail, const T &t,
136 Args &&...args) -> std::enable_if_t<!std::is_pointer_v<T>, std::string> {
137 auto [outPos, outTail] = maybeAddSourceInfo(t, position, tail);
138 return bug_helper(f % DbprintDispatchRef<T>{t}, outPos, outTail, std::forward<Args>(args)...);
139}
140} // namespace detail
141
142// Most direct invocations of bug_helper usually only reduce arguments
143template <class... Args>
144std::string bug_helper(boost::format &f, std::string_view position, std::string_view tail,
145 Args &&...args) {
146 return detail::bug_helper(f, position, tail, std::forward<Args>(args)...);
147}
148
149} // namespace P4
150
151#endif /* LIB_BUG_HELPER_H_ */
TODO: this is not really specific to BMV2, it should reside somewhere else.
Definition applyOptionsPragmas.cpp:24
void info(const int kind, const char *format, const T *node, Args &&...args)
Report info messages of type kind. Requires that the node argument have source info.
Definition error.h:148
Definition bug_helper.h:90
Definition bug_helper.h:117