@@ -75,6 +75,15 @@ class NodeExtractor {
7575 auto ExtractTupleLikeType (std::index_sequence<Index...> /* indices*/ ,
7676 std::tuple<U...>* /* type*/ ) -> std::optional<T>;
7777
78+ // Split out trace logic. The noinline saves a few seconds on compilation.
79+ template <typename ... ArgT>
80+ [[clang::noinline]] auto MaybeTrace (llvm::StringLiteral format,
81+ ArgT... args) const -> void {
82+ if (trace_) {
83+ *trace_ << llvm::formatv (format.data (), args...);
84+ }
85+ }
86+
7887 private:
7988 const TreeAndSubtrees* tree_;
8089 const Lex::TokenizedBuffer* tokens_;
@@ -113,34 +122,25 @@ template <>
113122struct Extractable <NodeId> {
114123 static auto Extract (NodeExtractor& extractor) -> std::optional<NodeId> {
115124 if (extractor.at_end ()) {
116- if (auto * trace = extractor.trace ()) {
117- *trace << " NodeId error: no more children\n " ;
118- }
125+ extractor.MaybeTrace (" NodeId error: no more children\n " );
119126 return std::nullopt ;
120127 }
121- if (auto * trace = extractor.trace ()) {
122- *trace << " NodeId: " << extractor.kind () << " consumed\n " ;
123- }
128+ extractor.MaybeTrace (" NodeId: {0} consumed\n " , extractor.kind ());
124129 return extractor.ExtractNode ();
125130 }
126131};
127132
128133auto NodeExtractor::MatchesNodeIdForKind (NodeKind expected_kind) const -> bool {
129- if (at_end () || kind () != expected_kind) {
130- if (trace_) {
131- if (at_end ()) {
132- *trace_ << " NodeIdForKind error: no more children, expected "
133- << expected_kind << " \n " ;
134- } else {
135- *trace_ << " NodeIdForKind error: wrong kind " << kind () << " , expected "
136- << expected_kind << " \n " ;
137- }
138- }
134+ if (at_end ()) {
135+ MaybeTrace (" NodeIdForKind error: no more children, expected {0}\n " ,
136+ expected_kind);
137+ return false ;
138+ } else if (kind () != expected_kind) {
139+ MaybeTrace (" NodeIdForKind error: wrong kind {0}, expected {1}\n " , kind (),
140+ expected_kind);
139141 return false ;
140142 }
141- if (trace_) {
142- *trace_ << " NodeIdForKind: " << expected_kind << " consumed\n " ;
143- }
143+ MaybeTrace (" NodeIdForKind: {0} consumed\n " , expected_kind);
144144 return true ;
145145}
146146
@@ -160,21 +160,15 @@ struct Extractable<NodeIdForKind<Kind>> {
160160
161161auto NodeExtractor::MatchesNodeIdInCategory (NodeCategory category) const
162162 -> bool {
163- if (at_end () || !kind ().category ().HasAnyOf (category)) {
164- if (trace_) {
165- *trace_ << " NodeIdInCategory " << category << " error: " ;
166- if (at_end ()) {
167- *trace_ << " no more children\n " ;
168- } else {
169- *trace_ << " kind " << kind () << " doesn't match\n " ;
170- }
171- }
163+ if (at_end ()) {
164+ MaybeTrace (" NodeIdInCategory {0} error: no more children\n " , category);
165+ return false ;
166+ } else if (!kind ().category ().HasAnyOf (category)) {
167+ MaybeTrace (" NodeIdInCategory {0} error: kind {1} doesn't match\n " , category,
168+ kind ());
172169 return false ;
173170 }
174- if (trace_) {
175- *trace_ << " NodeIdInCategory " << category << " : kind " << kind ()
176- << " consumed\n " ;
177- }
171+ MaybeTrace (" NodeIdInCategory {0}: kind {1} consumed\n " , category, kind ());
178172 return true ;
179173}
180174
@@ -200,19 +194,18 @@ auto NodeExtractor::MatchesNodeIdOneOf(
200194 }
201195 };
202196 auto node_kind = kind ();
203- if (at_end () ||
204- std::find (kinds.begin (), kinds.end (), node_kind) == kinds.end ()) {
197+ if (at_end ()) {
205198 if (trace_) {
206- if ( at_end ()) {
207- *trace_ << " NodeIdOneOf error: no more children, expected " ;
208- trace_kinds () ;
209- *trace_ << " \n " ;
210- } else {
211- *trace_ << " NodeIdOneOf error: wrong kind " << node_kind
212- << " , expected " ;
213- trace_kinds () ;
214- *trace_ << " \n " ;
215- }
199+ *trace_ << " NodeIdOneOf error: no more children, expected " ;
200+ trace_kinds () ;
201+ *trace_ << " \n " ;
202+ }
203+ return false ;
204+ } else if ( std::find (kinds. begin (), kinds. end (), node_kind) == kinds. end ()) {
205+ if (trace_) {
206+ *trace_ << " NodeIdOneOf error: wrong kind " << node_kind << " , expected " ;
207+ trace_kinds () ;
208+ *trace_ << " \n " ;
216209 }
217210 return false ;
218211 }
@@ -242,20 +235,17 @@ struct Extractable<NodeIdOneOf<T...>> {
242235template <typename T>
243236struct Extractable <NodeIdNot<T>> {
244237 static auto Extract (NodeExtractor& extractor) -> std::optional<NodeIdNot<T>> {
245- if (extractor.at_end () || extractor.kind () == T::Kind) {
246- if (auto * trace = extractor.trace ()) {
247- if (extractor.at_end ()) {
248- *trace << " NodeIdNot " << T::Kind << " error: no more children\n " ;
249- } else {
250- *trace << " NodeIdNot error: unexpected " << T::Kind << " \n " ;
251- }
252- }
238+ // This converts NodeKind::Definition to NodeKind.
239+ constexpr NodeKind Kind = T::Kind;
240+ if (extractor.at_end ()) {
241+ extractor.MaybeTrace (" NodeIdNot {0} error: no more children\n " , Kind);
242+ return std::nullopt ;
243+ } else if (extractor.kind () == Kind) {
244+ extractor.MaybeTrace (" NodeIdNot error: unexpected {0}\n " , Kind);
253245 return std::nullopt ;
254246 }
255- if (auto * trace = extractor.trace ()) {
256- *trace << " NodeIdNot " << T::Kind << " : " << extractor.kind ()
257- << " consumed\n " ;
258- }
247+ extractor.MaybeTrace (" NodeIdNot {0}: {1} consumed\n " , Kind,
248+ extractor.kind ());
259249 return NodeIdNot<T>(extractor.ExtractNode ());
260250 }
261251};
@@ -265,9 +255,7 @@ template <typename T>
265255struct Extractable <llvm::SmallVector<T>> {
266256 static auto Extract (NodeExtractor& extractor)
267257 -> std::optional<llvm::SmallVector<T>> {
268- if (auto * trace = extractor.trace ()) {
269- *trace << " Vector: begin\n " ;
270- }
258+ extractor.MaybeTrace (" Vector: begin\n " );
271259 llvm::SmallVector<T> result;
272260 while (!extractor.at_end ()) {
273261 auto checkpoint = extractor.Checkpoint ();
@@ -279,9 +267,7 @@ struct Extractable<llvm::SmallVector<T>> {
279267 result.push_back (*item);
280268 }
281269 std::reverse (result.begin (), result.end ());
282- if (auto * trace = extractor.trace ()) {
283- *trace << " Vector: end\n " ;
284- }
270+ extractor.MaybeTrace (" Vector: end\n " );
285271 return result;
286272 }
287273};
@@ -292,32 +278,23 @@ template <typename T>
292278struct Extractable <std::optional<T>> {
293279 static auto Extract (NodeExtractor& extractor)
294280 -> std::optional<std::optional<T>> {
295- if (auto * trace = extractor.trace ()) {
296- *trace << " Optional " << typeid (T).name () << " : begin\n " ;
297- }
281+ extractor.MaybeTrace (" Optional {0}: begin\n " , typeid (T).name ());
298282 auto checkpoint = extractor.Checkpoint ();
299283 std::optional<T> value = Extractable<T>::Extract (extractor);
300284 if (value) {
301- if (auto * trace = extractor.trace ()) {
302- *trace << " Optional " << typeid (T).name () << " : found\n " ;
303- }
304- return value;
305- }
306- if (auto * trace = extractor.trace ()) {
307- *trace << " Optional " << typeid (T).name () << " : missing\n " ;
285+ extractor.MaybeTrace (" Optional {0}: found\n " , typeid (T).name ());
286+ } else {
287+ extractor.MaybeTrace (" Optional {0}: missing\n " , typeid (T).name ());
288+ extractor.RestoreCheckpoint (checkpoint);
308289 }
309- extractor.RestoreCheckpoint (checkpoint);
310290 return value;
311291 }
312292};
313293
314294auto NodeExtractor::MatchesTokenKind (Lex::TokenKind expected_kind) const
315295 -> bool {
316296 if (!node_id_.is_valid ()) {
317- if (trace_) {
318- *trace_ << " Token " << expected_kind
319- << " expected but processing root node\n " ;
320- }
297+ MaybeTrace (" Token {0} expected but processing root node\n " , expected_kind);
321298 return false ;
322299 }
323300 if (token_kind () != expected_kind) {
@@ -350,9 +327,7 @@ struct Extractable<Lex::TokenIndex> {
350327 static auto Extract (NodeExtractor& extractor)
351328 -> std::optional<Lex::TokenIndex> {
352329 if (!extractor.has_token ()) {
353- if (auto * trace = extractor.trace ()) {
354- *trace << " Token expected but processing root node\n " ;
355- }
330+ extractor.MaybeTrace (" Token expected but processing root node\n " );
356331 return std::nullopt ;
357332 }
358333 return extractor.token ();
@@ -364,9 +339,7 @@ auto NodeExtractor::ExtractTupleLikeType(
364339 std::index_sequence<Index...> /* indices*/ , std::tuple<U...>* /* type*/ )
365340 -> std::optional<T> {
366341 std::tuple<std::optional<U>...> fields;
367- if (trace_) {
368- *trace_ << " Aggregate " << typeid (T).name () << " : begin\n " ;
369- }
342+ MaybeTrace (" Aggregate {0}: begin\n " , typeid (T).name ());
370343 // Use a fold over the `=` operator to parse fields from right to left.
371344 [[maybe_unused]] int unused;
372345 bool ok = true ;
@@ -375,15 +348,11 @@ auto NodeExtractor::ExtractTupleLikeType(
375348 .has_value ()),
376349 unused) = ... = 0 ));
377350 if (!ok) {
378- if (trace_) {
379- *trace_ << " Aggregate " << typeid (T).name () << " : error\n " ;
380- }
351+ MaybeTrace (" Aggregate {0}: error\n " , typeid (T).name ());
381352 return std::nullopt ;
382353 }
383354
384- if (trace_) {
385- *trace_ << " Aggregate " << typeid (T).name () << " : success\n " ;
386- }
355+ MaybeTrace (" Aggregate {0}: success\n " , typeid (T).name ());
387356 return T{std::move (std::get<Index>(fields).value ())...};
388357}
389358
0 commit comments