1*9356374aSAndroid Build Coastguard Worker // Copyright 2024 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/internal/demangle_rust.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <cstddef>
18*9356374aSAndroid Build Coastguard Worker #include <cstdint>
19*9356374aSAndroid Build Coastguard Worker #include <cstring>
20*9356374aSAndroid Build Coastguard Worker #include <limits>
21*9356374aSAndroid Build Coastguard Worker
22*9356374aSAndroid Build Coastguard Worker #include "absl/base/attributes.h"
23*9356374aSAndroid Build Coastguard Worker #include "absl/base/config.h"
24*9356374aSAndroid Build Coastguard Worker #include "absl/debugging/internal/decode_rust_punycode.h"
25*9356374aSAndroid Build Coastguard Worker
26*9356374aSAndroid Build Coastguard Worker namespace absl {
27*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN
28*9356374aSAndroid Build Coastguard Worker namespace debugging_internal {
29*9356374aSAndroid Build Coastguard Worker
30*9356374aSAndroid Build Coastguard Worker namespace {
31*9356374aSAndroid Build Coastguard Worker
32*9356374aSAndroid Build Coastguard Worker // Same step limit as the C++ demangler in demangle.cc uses.
33*9356374aSAndroid Build Coastguard Worker constexpr int kMaxReturns = 1 << 17;
34*9356374aSAndroid Build Coastguard Worker
IsDigit(char c)35*9356374aSAndroid Build Coastguard Worker bool IsDigit(char c) { return '0' <= c && c <= '9'; }
IsLower(char c)36*9356374aSAndroid Build Coastguard Worker bool IsLower(char c) { return 'a' <= c && c <= 'z'; }
IsUpper(char c)37*9356374aSAndroid Build Coastguard Worker bool IsUpper(char c) { return 'A' <= c && c <= 'Z'; }
IsAlpha(char c)38*9356374aSAndroid Build Coastguard Worker bool IsAlpha(char c) { return IsLower(c) || IsUpper(c); }
IsIdentifierChar(char c)39*9356374aSAndroid Build Coastguard Worker bool IsIdentifierChar(char c) { return IsAlpha(c) || IsDigit(c) || c == '_'; }
IsLowerHexDigit(char c)40*9356374aSAndroid Build Coastguard Worker bool IsLowerHexDigit(char c) { return IsDigit(c) || ('a' <= c && c <= 'f'); }
41*9356374aSAndroid Build Coastguard Worker
BasicTypeName(char c)42*9356374aSAndroid Build Coastguard Worker const char* BasicTypeName(char c) {
43*9356374aSAndroid Build Coastguard Worker switch (c) {
44*9356374aSAndroid Build Coastguard Worker case 'a': return "i8";
45*9356374aSAndroid Build Coastguard Worker case 'b': return "bool";
46*9356374aSAndroid Build Coastguard Worker case 'c': return "char";
47*9356374aSAndroid Build Coastguard Worker case 'd': return "f64";
48*9356374aSAndroid Build Coastguard Worker case 'e': return "str";
49*9356374aSAndroid Build Coastguard Worker case 'f': return "f32";
50*9356374aSAndroid Build Coastguard Worker case 'h': return "u8";
51*9356374aSAndroid Build Coastguard Worker case 'i': return "isize";
52*9356374aSAndroid Build Coastguard Worker case 'j': return "usize";
53*9356374aSAndroid Build Coastguard Worker case 'l': return "i32";
54*9356374aSAndroid Build Coastguard Worker case 'm': return "u32";
55*9356374aSAndroid Build Coastguard Worker case 'n': return "i128";
56*9356374aSAndroid Build Coastguard Worker case 'o': return "u128";
57*9356374aSAndroid Build Coastguard Worker case 'p': return "_";
58*9356374aSAndroid Build Coastguard Worker case 's': return "i16";
59*9356374aSAndroid Build Coastguard Worker case 't': return "u16";
60*9356374aSAndroid Build Coastguard Worker case 'u': return "()";
61*9356374aSAndroid Build Coastguard Worker case 'v': return "...";
62*9356374aSAndroid Build Coastguard Worker case 'x': return "i64";
63*9356374aSAndroid Build Coastguard Worker case 'y': return "u64";
64*9356374aSAndroid Build Coastguard Worker case 'z': return "!";
65*9356374aSAndroid Build Coastguard Worker }
66*9356374aSAndroid Build Coastguard Worker return nullptr;
67*9356374aSAndroid Build Coastguard Worker }
68*9356374aSAndroid Build Coastguard Worker
69*9356374aSAndroid Build Coastguard Worker // Parser for Rust symbol mangling v0, whose grammar is defined here:
70*9356374aSAndroid Build Coastguard Worker //
71*9356374aSAndroid Build Coastguard Worker // https://doc.rust-lang.org/rustc/symbol-mangling/v0.html#symbol-grammar-summary
72*9356374aSAndroid Build Coastguard Worker class RustSymbolParser {
73*9356374aSAndroid Build Coastguard Worker public:
74*9356374aSAndroid Build Coastguard Worker // Prepares to demangle the given encoding, a Rust symbol name starting with
75*9356374aSAndroid Build Coastguard Worker // _R, into the output buffer [out, out_end). The caller is expected to
76*9356374aSAndroid Build Coastguard Worker // continue by calling the new object's Parse function.
RustSymbolParser(const char * encoding,char * out,char * const out_end)77*9356374aSAndroid Build Coastguard Worker RustSymbolParser(const char* encoding, char* out, char* const out_end)
78*9356374aSAndroid Build Coastguard Worker : encoding_(encoding), out_(out), out_end_(out_end) {
79*9356374aSAndroid Build Coastguard Worker if (out_ != out_end_) *out_ = '\0';
80*9356374aSAndroid Build Coastguard Worker }
81*9356374aSAndroid Build Coastguard Worker
82*9356374aSAndroid Build Coastguard Worker // Parses the constructor's encoding argument, writing output into the range
83*9356374aSAndroid Build Coastguard Worker // [out, out_end). Returns true on success and false for input whose
84*9356374aSAndroid Build Coastguard Worker // structure was not recognized or exceeded implementation limits, such as by
85*9356374aSAndroid Build Coastguard Worker // nesting structures too deep. In either case *this should not be used
86*9356374aSAndroid Build Coastguard Worker // again.
Parse()87*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool Parse() && {
88*9356374aSAndroid Build Coastguard Worker // Recursively parses the grammar production named by callee, then resumes
89*9356374aSAndroid Build Coastguard Worker // execution at the next statement.
90*9356374aSAndroid Build Coastguard Worker //
91*9356374aSAndroid Build Coastguard Worker // Recursive-descent parsing is a beautifully readable translation of a
92*9356374aSAndroid Build Coastguard Worker // grammar, but it risks stack overflow if implemented by naive recursion on
93*9356374aSAndroid Build Coastguard Worker // the C++ call stack. So we simulate recursion by goto and switch instead,
94*9356374aSAndroid Build Coastguard Worker // keeping a bounded stack of "return addresses" in the recursion_stack_
95*9356374aSAndroid Build Coastguard Worker // member.
96*9356374aSAndroid Build Coastguard Worker //
97*9356374aSAndroid Build Coastguard Worker // The callee argument is a statement label. We goto that label after
98*9356374aSAndroid Build Coastguard Worker // saving the "return address" on recursion_stack_. The next continue
99*9356374aSAndroid Build Coastguard Worker // statement in the for loop below "returns" from this "call".
100*9356374aSAndroid Build Coastguard Worker //
101*9356374aSAndroid Build Coastguard Worker // The caller argument names the return point. Each value of caller must
102*9356374aSAndroid Build Coastguard Worker // appear in only one ABSL_DEMANGLER_RECURSE call and be listed in the
103*9356374aSAndroid Build Coastguard Worker // definition of enum ReturnAddress. The switch implements the control
104*9356374aSAndroid Build Coastguard Worker // transfer from the end of a "called" subroutine back to the statement
105*9356374aSAndroid Build Coastguard Worker // after the "call".
106*9356374aSAndroid Build Coastguard Worker //
107*9356374aSAndroid Build Coastguard Worker // Note that not all the grammar productions have to be packed into the
108*9356374aSAndroid Build Coastguard Worker // switch, but only those which appear in a cycle in the grammar. Anything
109*9356374aSAndroid Build Coastguard Worker // acyclic can be written as ordinary functions and function calls, e.g.,
110*9356374aSAndroid Build Coastguard Worker // ParseIdentifier.
111*9356374aSAndroid Build Coastguard Worker #define ABSL_DEMANGLER_RECURSE(callee, caller) \
112*9356374aSAndroid Build Coastguard Worker do { \
113*9356374aSAndroid Build Coastguard Worker if (recursion_depth_ == kStackSize) return false; \
114*9356374aSAndroid Build Coastguard Worker /* The next continue will switch on this saved value ... */ \
115*9356374aSAndroid Build Coastguard Worker recursion_stack_[recursion_depth_++] = caller; \
116*9356374aSAndroid Build Coastguard Worker goto callee; \
117*9356374aSAndroid Build Coastguard Worker /* ... and will land here, resuming the suspended code. */ \
118*9356374aSAndroid Build Coastguard Worker case caller: {} \
119*9356374aSAndroid Build Coastguard Worker } while (0)
120*9356374aSAndroid Build Coastguard Worker
121*9356374aSAndroid Build Coastguard Worker // Parse the encoding, counting completed recursive calls to guard against
122*9356374aSAndroid Build Coastguard Worker // excessively complex input and infinite-loop bugs.
123*9356374aSAndroid Build Coastguard Worker int iter = 0;
124*9356374aSAndroid Build Coastguard Worker goto whole_encoding;
125*9356374aSAndroid Build Coastguard Worker for (; iter < kMaxReturns && recursion_depth_ > 0; ++iter) {
126*9356374aSAndroid Build Coastguard Worker // This switch resumes the code path most recently suspended by
127*9356374aSAndroid Build Coastguard Worker // ABSL_DEMANGLER_RECURSE.
128*9356374aSAndroid Build Coastguard Worker switch (recursion_stack_[--recursion_depth_]) {
129*9356374aSAndroid Build Coastguard Worker //
130*9356374aSAndroid Build Coastguard Worker // symbol-name ->
131*9356374aSAndroid Build Coastguard Worker // _R decimal-number? path instantiating-crate? vendor-specific-suffix?
132*9356374aSAndroid Build Coastguard Worker whole_encoding:
133*9356374aSAndroid Build Coastguard Worker if (!Eat('_') || !Eat('R')) return false;
134*9356374aSAndroid Build Coastguard Worker // decimal-number? is always empty today, so proceed to path, which
135*9356374aSAndroid Build Coastguard Worker // can't start with a decimal digit.
136*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kInstantiatingCrate);
137*9356374aSAndroid Build Coastguard Worker if (IsAlpha(Peek())) {
138*9356374aSAndroid Build Coastguard Worker ++silence_depth_; // Print nothing more from here on.
139*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kVendorSpecificSuffix);
140*9356374aSAndroid Build Coastguard Worker }
141*9356374aSAndroid Build Coastguard Worker switch (Take()) {
142*9356374aSAndroid Build Coastguard Worker case '.': case '$': case '\0': return true;
143*9356374aSAndroid Build Coastguard Worker }
144*9356374aSAndroid Build Coastguard Worker return false; // unexpected trailing content
145*9356374aSAndroid Build Coastguard Worker
146*9356374aSAndroid Build Coastguard Worker // path -> crate-root | inherent-impl | trait-impl | trait-definition |
147*9356374aSAndroid Build Coastguard Worker // nested-path | generic-args | backref
148*9356374aSAndroid Build Coastguard Worker //
149*9356374aSAndroid Build Coastguard Worker // Note that ABSL_DEMANGLER_RECURSE does not work inside a nested switch
150*9356374aSAndroid Build Coastguard Worker // (which would hide the generated case label). Thus we jump out of the
151*9356374aSAndroid Build Coastguard Worker // inner switch with gotos before performing any fake recursion.
152*9356374aSAndroid Build Coastguard Worker path:
153*9356374aSAndroid Build Coastguard Worker switch (Take()) {
154*9356374aSAndroid Build Coastguard Worker case 'C': goto crate_root;
155*9356374aSAndroid Build Coastguard Worker case 'M': goto inherent_impl;
156*9356374aSAndroid Build Coastguard Worker case 'X': goto trait_impl;
157*9356374aSAndroid Build Coastguard Worker case 'Y': goto trait_definition;
158*9356374aSAndroid Build Coastguard Worker case 'N': goto nested_path;
159*9356374aSAndroid Build Coastguard Worker case 'I': goto generic_args;
160*9356374aSAndroid Build Coastguard Worker case 'B': goto path_backref;
161*9356374aSAndroid Build Coastguard Worker default: return false;
162*9356374aSAndroid Build Coastguard Worker }
163*9356374aSAndroid Build Coastguard Worker
164*9356374aSAndroid Build Coastguard Worker // crate-root -> C identifier (C consumed above)
165*9356374aSAndroid Build Coastguard Worker crate_root:
166*9356374aSAndroid Build Coastguard Worker if (!ParseIdentifier()) return false;
167*9356374aSAndroid Build Coastguard Worker continue;
168*9356374aSAndroid Build Coastguard Worker
169*9356374aSAndroid Build Coastguard Worker // inherent-impl -> M impl-path type (M already consumed)
170*9356374aSAndroid Build Coastguard Worker inherent_impl:
171*9356374aSAndroid Build Coastguard Worker if (!Emit("<")) return false;
172*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(impl_path, kInherentImplType);
173*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kInherentImplEnding);
174*9356374aSAndroid Build Coastguard Worker if (!Emit(">")) return false;
175*9356374aSAndroid Build Coastguard Worker continue;
176*9356374aSAndroid Build Coastguard Worker
177*9356374aSAndroid Build Coastguard Worker // trait-impl -> X impl-path type path (X already consumed)
178*9356374aSAndroid Build Coastguard Worker trait_impl:
179*9356374aSAndroid Build Coastguard Worker if (!Emit("<")) return false;
180*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(impl_path, kTraitImplType);
181*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kTraitImplInfix);
182*9356374aSAndroid Build Coastguard Worker if (!Emit(" as ")) return false;
183*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kTraitImplEnding);
184*9356374aSAndroid Build Coastguard Worker if (!Emit(">")) return false;
185*9356374aSAndroid Build Coastguard Worker continue;
186*9356374aSAndroid Build Coastguard Worker
187*9356374aSAndroid Build Coastguard Worker // impl-path -> disambiguator? path (but never print it!)
188*9356374aSAndroid Build Coastguard Worker impl_path:
189*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
190*9356374aSAndroid Build Coastguard Worker {
191*9356374aSAndroid Build Coastguard Worker int ignored_disambiguator;
192*9356374aSAndroid Build Coastguard Worker if (!ParseDisambiguator(ignored_disambiguator)) return false;
193*9356374aSAndroid Build Coastguard Worker }
194*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kImplPathEnding);
195*9356374aSAndroid Build Coastguard Worker --silence_depth_;
196*9356374aSAndroid Build Coastguard Worker continue;
197*9356374aSAndroid Build Coastguard Worker
198*9356374aSAndroid Build Coastguard Worker // trait-definition -> Y type path (Y already consumed)
199*9356374aSAndroid Build Coastguard Worker trait_definition:
200*9356374aSAndroid Build Coastguard Worker if (!Emit("<")) return false;
201*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kTraitDefinitionInfix);
202*9356374aSAndroid Build Coastguard Worker if (!Emit(" as ")) return false;
203*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kTraitDefinitionEnding);
204*9356374aSAndroid Build Coastguard Worker if (!Emit(">")) return false;
205*9356374aSAndroid Build Coastguard Worker continue;
206*9356374aSAndroid Build Coastguard Worker
207*9356374aSAndroid Build Coastguard Worker // nested-path -> N namespace path identifier (N already consumed)
208*9356374aSAndroid Build Coastguard Worker // namespace -> lower | upper
209*9356374aSAndroid Build Coastguard Worker nested_path:
210*9356374aSAndroid Build Coastguard Worker // Uppercase namespaces must be saved on a stack so we can print
211*9356374aSAndroid Build Coastguard Worker // ::{closure#0} or ::{shim:vtable#0} or ::{X:name#0} as needed.
212*9356374aSAndroid Build Coastguard Worker if (IsUpper(Peek())) {
213*9356374aSAndroid Build Coastguard Worker if (!PushNamespace(Take())) return false;
214*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kIdentifierInUppercaseNamespace);
215*9356374aSAndroid Build Coastguard Worker if (!Emit("::")) return false;
216*9356374aSAndroid Build Coastguard Worker if (!ParseIdentifier(PopNamespace())) return false;
217*9356374aSAndroid Build Coastguard Worker continue;
218*9356374aSAndroid Build Coastguard Worker }
219*9356374aSAndroid Build Coastguard Worker
220*9356374aSAndroid Build Coastguard Worker // Lowercase namespaces, however, are never represented in the output;
221*9356374aSAndroid Build Coastguard Worker // they all emit just ::name.
222*9356374aSAndroid Build Coastguard Worker if (IsLower(Take())) {
223*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kIdentifierInLowercaseNamespace);
224*9356374aSAndroid Build Coastguard Worker if (!Emit("::")) return false;
225*9356374aSAndroid Build Coastguard Worker if (!ParseIdentifier()) return false;
226*9356374aSAndroid Build Coastguard Worker continue;
227*9356374aSAndroid Build Coastguard Worker }
228*9356374aSAndroid Build Coastguard Worker
229*9356374aSAndroid Build Coastguard Worker // Neither upper or lower
230*9356374aSAndroid Build Coastguard Worker return false;
231*9356374aSAndroid Build Coastguard Worker
232*9356374aSAndroid Build Coastguard Worker // type -> basic-type | array-type | slice-type | tuple-type |
233*9356374aSAndroid Build Coastguard Worker // ref-type | mut-ref-type | const-ptr-type | mut-ptr-type |
234*9356374aSAndroid Build Coastguard Worker // fn-type | dyn-trait-type | path | backref
235*9356374aSAndroid Build Coastguard Worker //
236*9356374aSAndroid Build Coastguard Worker // We use ifs instead of switch (Take()) because the default case jumps
237*9356374aSAndroid Build Coastguard Worker // to path, which will need to see the first character not yet Taken
238*9356374aSAndroid Build Coastguard Worker // from the input. Because we do not use a nested switch here,
239*9356374aSAndroid Build Coastguard Worker // ABSL_DEMANGLER_RECURSE works fine in the 'S' case.
240*9356374aSAndroid Build Coastguard Worker type:
241*9356374aSAndroid Build Coastguard Worker if (IsLower(Peek())) {
242*9356374aSAndroid Build Coastguard Worker const char* type_name = BasicTypeName(Take());
243*9356374aSAndroid Build Coastguard Worker if (type_name == nullptr || !Emit(type_name)) return false;
244*9356374aSAndroid Build Coastguard Worker continue;
245*9356374aSAndroid Build Coastguard Worker }
246*9356374aSAndroid Build Coastguard Worker if (Eat('A')) {
247*9356374aSAndroid Build Coastguard Worker // array-type = A type const
248*9356374aSAndroid Build Coastguard Worker if (!Emit("[")) return false;
249*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kArraySize);
250*9356374aSAndroid Build Coastguard Worker if (!Emit("; ")) return false;
251*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(constant, kFinishArray);
252*9356374aSAndroid Build Coastguard Worker if (!Emit("]")) return false;
253*9356374aSAndroid Build Coastguard Worker continue;
254*9356374aSAndroid Build Coastguard Worker }
255*9356374aSAndroid Build Coastguard Worker if (Eat('S')) {
256*9356374aSAndroid Build Coastguard Worker if (!Emit("[")) return false;
257*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kSliceEnding);
258*9356374aSAndroid Build Coastguard Worker if (!Emit("]")) return false;
259*9356374aSAndroid Build Coastguard Worker continue;
260*9356374aSAndroid Build Coastguard Worker }
261*9356374aSAndroid Build Coastguard Worker if (Eat('T')) goto tuple_type;
262*9356374aSAndroid Build Coastguard Worker if (Eat('R')) {
263*9356374aSAndroid Build Coastguard Worker if (!Emit("&")) return false;
264*9356374aSAndroid Build Coastguard Worker if (!ParseOptionalLifetime()) return false;
265*9356374aSAndroid Build Coastguard Worker goto type;
266*9356374aSAndroid Build Coastguard Worker }
267*9356374aSAndroid Build Coastguard Worker if (Eat('Q')) {
268*9356374aSAndroid Build Coastguard Worker if (!Emit("&mut ")) return false;
269*9356374aSAndroid Build Coastguard Worker if (!ParseOptionalLifetime()) return false;
270*9356374aSAndroid Build Coastguard Worker goto type;
271*9356374aSAndroid Build Coastguard Worker }
272*9356374aSAndroid Build Coastguard Worker if (Eat('P')) {
273*9356374aSAndroid Build Coastguard Worker if (!Emit("*const ")) return false;
274*9356374aSAndroid Build Coastguard Worker goto type;
275*9356374aSAndroid Build Coastguard Worker }
276*9356374aSAndroid Build Coastguard Worker if (Eat('O')) {
277*9356374aSAndroid Build Coastguard Worker if (!Emit("*mut ")) return false;
278*9356374aSAndroid Build Coastguard Worker goto type;
279*9356374aSAndroid Build Coastguard Worker }
280*9356374aSAndroid Build Coastguard Worker if (Eat('F')) goto fn_type;
281*9356374aSAndroid Build Coastguard Worker if (Eat('D')) goto dyn_trait_type;
282*9356374aSAndroid Build Coastguard Worker if (Eat('B')) goto type_backref;
283*9356374aSAndroid Build Coastguard Worker goto path;
284*9356374aSAndroid Build Coastguard Worker
285*9356374aSAndroid Build Coastguard Worker // tuple-type -> T type* E (T already consumed)
286*9356374aSAndroid Build Coastguard Worker tuple_type:
287*9356374aSAndroid Build Coastguard Worker if (!Emit("(")) return false;
288*9356374aSAndroid Build Coastguard Worker
289*9356374aSAndroid Build Coastguard Worker // The toolchain should call the unit type u instead of TE, but the
290*9356374aSAndroid Build Coastguard Worker // grammar and other demanglers also recognize TE, so we do too.
291*9356374aSAndroid Build Coastguard Worker if (Eat('E')) {
292*9356374aSAndroid Build Coastguard Worker if (!Emit(")")) return false;
293*9356374aSAndroid Build Coastguard Worker continue;
294*9356374aSAndroid Build Coastguard Worker }
295*9356374aSAndroid Build Coastguard Worker
296*9356374aSAndroid Build Coastguard Worker // A tuple with one element is rendered (type,) instead of (type).
297*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kAfterFirstTupleElement);
298*9356374aSAndroid Build Coastguard Worker if (Eat('E')) {
299*9356374aSAndroid Build Coastguard Worker if (!Emit(",)")) return false;
300*9356374aSAndroid Build Coastguard Worker continue;
301*9356374aSAndroid Build Coastguard Worker }
302*9356374aSAndroid Build Coastguard Worker
303*9356374aSAndroid Build Coastguard Worker // A tuple with two elements is of course (x, y).
304*9356374aSAndroid Build Coastguard Worker if (!Emit(", ")) return false;
305*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kAfterSecondTupleElement);
306*9356374aSAndroid Build Coastguard Worker if (Eat('E')) {
307*9356374aSAndroid Build Coastguard Worker if (!Emit(")")) return false;
308*9356374aSAndroid Build Coastguard Worker continue;
309*9356374aSAndroid Build Coastguard Worker }
310*9356374aSAndroid Build Coastguard Worker
311*9356374aSAndroid Build Coastguard Worker // And (x, y, z) for three elements.
312*9356374aSAndroid Build Coastguard Worker if (!Emit(", ")) return false;
313*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kAfterThirdTupleElement);
314*9356374aSAndroid Build Coastguard Worker if (Eat('E')) {
315*9356374aSAndroid Build Coastguard Worker if (!Emit(")")) return false;
316*9356374aSAndroid Build Coastguard Worker continue;
317*9356374aSAndroid Build Coastguard Worker }
318*9356374aSAndroid Build Coastguard Worker
319*9356374aSAndroid Build Coastguard Worker // For longer tuples we write (x, y, z, ...), printing none of the
320*9356374aSAndroid Build Coastguard Worker // content of the fourth and later types. Thus we avoid exhausting
321*9356374aSAndroid Build Coastguard Worker // output buffers and human readers' patience when some library has a
322*9356374aSAndroid Build Coastguard Worker // long tuple as an implementation detail, without having to
323*9356374aSAndroid Build Coastguard Worker // completely obfuscate all tuples.
324*9356374aSAndroid Build Coastguard Worker if (!Emit(", ...)")) return false;
325*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
326*9356374aSAndroid Build Coastguard Worker while (!Eat('E')) {
327*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kAfterSubsequentTupleElement);
328*9356374aSAndroid Build Coastguard Worker }
329*9356374aSAndroid Build Coastguard Worker --silence_depth_;
330*9356374aSAndroid Build Coastguard Worker continue;
331*9356374aSAndroid Build Coastguard Worker
332*9356374aSAndroid Build Coastguard Worker // fn-type -> F fn-sig (F already consumed)
333*9356374aSAndroid Build Coastguard Worker // fn-sig -> binder? U? (K abi)? type* E type
334*9356374aSAndroid Build Coastguard Worker // abi -> C | undisambiguated-identifier
335*9356374aSAndroid Build Coastguard Worker //
336*9356374aSAndroid Build Coastguard Worker // We follow the C++ demangler in suppressing details of function
337*9356374aSAndroid Build Coastguard Worker // signatures. Every function type is rendered "fn...".
338*9356374aSAndroid Build Coastguard Worker fn_type:
339*9356374aSAndroid Build Coastguard Worker if (!Emit("fn...")) return false;
340*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
341*9356374aSAndroid Build Coastguard Worker if (!ParseOptionalBinder()) return false;
342*9356374aSAndroid Build Coastguard Worker (void)Eat('U');
343*9356374aSAndroid Build Coastguard Worker if (Eat('K')) {
344*9356374aSAndroid Build Coastguard Worker if (!Eat('C') && !ParseUndisambiguatedIdentifier()) return false;
345*9356374aSAndroid Build Coastguard Worker }
346*9356374aSAndroid Build Coastguard Worker while (!Eat('E')) {
347*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kContinueParameterList);
348*9356374aSAndroid Build Coastguard Worker }
349*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kFinishFn);
350*9356374aSAndroid Build Coastguard Worker --silence_depth_;
351*9356374aSAndroid Build Coastguard Worker continue;
352*9356374aSAndroid Build Coastguard Worker
353*9356374aSAndroid Build Coastguard Worker // dyn-trait-type -> D dyn-bounds lifetime (D already consumed)
354*9356374aSAndroid Build Coastguard Worker // dyn-bounds -> binder? dyn-trait* E
355*9356374aSAndroid Build Coastguard Worker //
356*9356374aSAndroid Build Coastguard Worker // The grammar strangely allows an empty trait list, even though the
357*9356374aSAndroid Build Coastguard Worker // compiler should never output one. We follow existing demanglers in
358*9356374aSAndroid Build Coastguard Worker // rendering DEL_ as "dyn ".
359*9356374aSAndroid Build Coastguard Worker //
360*9356374aSAndroid Build Coastguard Worker // Because auto traits lengthen a type name considerably without
361*9356374aSAndroid Build Coastguard Worker // providing much value to a search for related source code, it would be
362*9356374aSAndroid Build Coastguard Worker // desirable to abbreviate
363*9356374aSAndroid Build Coastguard Worker // dyn main::Trait + std::marker::Copy + std::marker::Send
364*9356374aSAndroid Build Coastguard Worker // to
365*9356374aSAndroid Build Coastguard Worker // dyn main::Trait + ...,
366*9356374aSAndroid Build Coastguard Worker // eliding the auto traits. But it is difficult to do so correctly, in
367*9356374aSAndroid Build Coastguard Worker // part because there is no guarantee that the mangling will list the
368*9356374aSAndroid Build Coastguard Worker // main trait first. So we just print all the traits in their order of
369*9356374aSAndroid Build Coastguard Worker // appearance in the mangled name.
370*9356374aSAndroid Build Coastguard Worker dyn_trait_type:
371*9356374aSAndroid Build Coastguard Worker if (!Emit("dyn ")) return false;
372*9356374aSAndroid Build Coastguard Worker if (!ParseOptionalBinder()) return false;
373*9356374aSAndroid Build Coastguard Worker if (!Eat('E')) {
374*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(dyn_trait, kBeginAutoTraits);
375*9356374aSAndroid Build Coastguard Worker while (!Eat('E')) {
376*9356374aSAndroid Build Coastguard Worker if (!Emit(" + ")) return false;
377*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(dyn_trait, kContinueAutoTraits);
378*9356374aSAndroid Build Coastguard Worker }
379*9356374aSAndroid Build Coastguard Worker }
380*9356374aSAndroid Build Coastguard Worker if (!ParseRequiredLifetime()) return false;
381*9356374aSAndroid Build Coastguard Worker continue;
382*9356374aSAndroid Build Coastguard Worker
383*9356374aSAndroid Build Coastguard Worker // dyn-trait -> path dyn-trait-assoc-binding*
384*9356374aSAndroid Build Coastguard Worker // dyn-trait-assoc-binding -> p undisambiguated-identifier type
385*9356374aSAndroid Build Coastguard Worker //
386*9356374aSAndroid Build Coastguard Worker // We render nonempty binding lists as <>, omitting their contents as
387*9356374aSAndroid Build Coastguard Worker // for generic-args.
388*9356374aSAndroid Build Coastguard Worker dyn_trait:
389*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kContinueDynTrait);
390*9356374aSAndroid Build Coastguard Worker if (Peek() == 'p') {
391*9356374aSAndroid Build Coastguard Worker if (!Emit("<>")) return false;
392*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
393*9356374aSAndroid Build Coastguard Worker while (Eat('p')) {
394*9356374aSAndroid Build Coastguard Worker if (!ParseUndisambiguatedIdentifier()) return false;
395*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kContinueAssocBinding);
396*9356374aSAndroid Build Coastguard Worker }
397*9356374aSAndroid Build Coastguard Worker --silence_depth_;
398*9356374aSAndroid Build Coastguard Worker }
399*9356374aSAndroid Build Coastguard Worker continue;
400*9356374aSAndroid Build Coastguard Worker
401*9356374aSAndroid Build Coastguard Worker // const -> type const-data | p | backref
402*9356374aSAndroid Build Coastguard Worker //
403*9356374aSAndroid Build Coastguard Worker // const is a C++ keyword, so we use the label `constant` instead.
404*9356374aSAndroid Build Coastguard Worker constant:
405*9356374aSAndroid Build Coastguard Worker if (Eat('B')) goto const_backref;
406*9356374aSAndroid Build Coastguard Worker if (Eat('p')) {
407*9356374aSAndroid Build Coastguard Worker if (!Emit("_")) return false;
408*9356374aSAndroid Build Coastguard Worker continue;
409*9356374aSAndroid Build Coastguard Worker }
410*9356374aSAndroid Build Coastguard Worker
411*9356374aSAndroid Build Coastguard Worker // Scan the type without printing it.
412*9356374aSAndroid Build Coastguard Worker //
413*9356374aSAndroid Build Coastguard Worker // The Rust language restricts the type of a const generic argument
414*9356374aSAndroid Build Coastguard Worker // much more than the mangling grammar does. We do not enforce this.
415*9356374aSAndroid Build Coastguard Worker //
416*9356374aSAndroid Build Coastguard Worker // We also do not bother printing false, true, 'A', and '\u{abcd}' for
417*9356374aSAndroid Build Coastguard Worker // the types bool and char. Because we do not print generic-args
418*9356374aSAndroid Build Coastguard Worker // contents, we expect to print constants only in array sizes, and
419*9356374aSAndroid Build Coastguard Worker // those should not be bool or char.
420*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
421*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kConstData);
422*9356374aSAndroid Build Coastguard Worker --silence_depth_;
423*9356374aSAndroid Build Coastguard Worker
424*9356374aSAndroid Build Coastguard Worker // const-data -> n? hex-digit* _
425*9356374aSAndroid Build Coastguard Worker //
426*9356374aSAndroid Build Coastguard Worker // Although the grammar doesn't say this, existing demanglers expect
427*9356374aSAndroid Build Coastguard Worker // that zero is 0, not an empty digit sequence, and no nonzero value
428*9356374aSAndroid Build Coastguard Worker // may have leading zero digits. Also n0_ is accepted and printed as
429*9356374aSAndroid Build Coastguard Worker // -0, though a toolchain will probably never write that encoding.
430*9356374aSAndroid Build Coastguard Worker if (Eat('n') && !EmitChar('-')) return false;
431*9356374aSAndroid Build Coastguard Worker if (!Emit("0x")) return false;
432*9356374aSAndroid Build Coastguard Worker if (Eat('0')) {
433*9356374aSAndroid Build Coastguard Worker if (!EmitChar('0')) return false;
434*9356374aSAndroid Build Coastguard Worker if (!Eat('_')) return false;
435*9356374aSAndroid Build Coastguard Worker continue;
436*9356374aSAndroid Build Coastguard Worker }
437*9356374aSAndroid Build Coastguard Worker while (IsLowerHexDigit(Peek())) {
438*9356374aSAndroid Build Coastguard Worker if (!EmitChar(Take())) return false;
439*9356374aSAndroid Build Coastguard Worker }
440*9356374aSAndroid Build Coastguard Worker if (!Eat('_')) return false;
441*9356374aSAndroid Build Coastguard Worker continue;
442*9356374aSAndroid Build Coastguard Worker
443*9356374aSAndroid Build Coastguard Worker // generic-args -> I path generic-arg* E (I already consumed)
444*9356374aSAndroid Build Coastguard Worker //
445*9356374aSAndroid Build Coastguard Worker // We follow the C++ demangler in omitting all the arguments from the
446*9356374aSAndroid Build Coastguard Worker // output, printing only the list opening and closing tokens.
447*9356374aSAndroid Build Coastguard Worker generic_args:
448*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kBeginGenericArgList);
449*9356374aSAndroid Build Coastguard Worker if (!Emit("::<>")) return false;
450*9356374aSAndroid Build Coastguard Worker ++silence_depth_;
451*9356374aSAndroid Build Coastguard Worker while (!Eat('E')) {
452*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(generic_arg, kContinueGenericArgList);
453*9356374aSAndroid Build Coastguard Worker }
454*9356374aSAndroid Build Coastguard Worker --silence_depth_;
455*9356374aSAndroid Build Coastguard Worker continue;
456*9356374aSAndroid Build Coastguard Worker
457*9356374aSAndroid Build Coastguard Worker // generic-arg -> lifetime | type | K const
458*9356374aSAndroid Build Coastguard Worker generic_arg:
459*9356374aSAndroid Build Coastguard Worker if (Peek() == 'L') {
460*9356374aSAndroid Build Coastguard Worker if (!ParseOptionalLifetime()) return false;
461*9356374aSAndroid Build Coastguard Worker continue;
462*9356374aSAndroid Build Coastguard Worker }
463*9356374aSAndroid Build Coastguard Worker if (Eat('K')) goto constant;
464*9356374aSAndroid Build Coastguard Worker goto type;
465*9356374aSAndroid Build Coastguard Worker
466*9356374aSAndroid Build Coastguard Worker // backref -> B base-62-number (B already consumed)
467*9356374aSAndroid Build Coastguard Worker //
468*9356374aSAndroid Build Coastguard Worker // The BeginBackref call parses and range-checks the base-62-number. We
469*9356374aSAndroid Build Coastguard Worker // always do that much.
470*9356374aSAndroid Build Coastguard Worker //
471*9356374aSAndroid Build Coastguard Worker // The recursive call parses and prints what the backref points at. We
472*9356374aSAndroid Build Coastguard Worker // save CPU and stack by skipping this work if the output would be
473*9356374aSAndroid Build Coastguard Worker // suppressed anyway.
474*9356374aSAndroid Build Coastguard Worker path_backref:
475*9356374aSAndroid Build Coastguard Worker if (!BeginBackref()) return false;
476*9356374aSAndroid Build Coastguard Worker if (silence_depth_ == 0) {
477*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(path, kPathBackrefEnding);
478*9356374aSAndroid Build Coastguard Worker }
479*9356374aSAndroid Build Coastguard Worker EndBackref();
480*9356374aSAndroid Build Coastguard Worker continue;
481*9356374aSAndroid Build Coastguard Worker
482*9356374aSAndroid Build Coastguard Worker // This represents the same backref production as in path_backref but
483*9356374aSAndroid Build Coastguard Worker // parses the target as a type instead of a path.
484*9356374aSAndroid Build Coastguard Worker type_backref:
485*9356374aSAndroid Build Coastguard Worker if (!BeginBackref()) return false;
486*9356374aSAndroid Build Coastguard Worker if (silence_depth_ == 0) {
487*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(type, kTypeBackrefEnding);
488*9356374aSAndroid Build Coastguard Worker }
489*9356374aSAndroid Build Coastguard Worker EndBackref();
490*9356374aSAndroid Build Coastguard Worker continue;
491*9356374aSAndroid Build Coastguard Worker
492*9356374aSAndroid Build Coastguard Worker const_backref:
493*9356374aSAndroid Build Coastguard Worker if (!BeginBackref()) return false;
494*9356374aSAndroid Build Coastguard Worker if (silence_depth_ == 0) {
495*9356374aSAndroid Build Coastguard Worker ABSL_DEMANGLER_RECURSE(constant, kConstantBackrefEnding);
496*9356374aSAndroid Build Coastguard Worker }
497*9356374aSAndroid Build Coastguard Worker EndBackref();
498*9356374aSAndroid Build Coastguard Worker continue;
499*9356374aSAndroid Build Coastguard Worker }
500*9356374aSAndroid Build Coastguard Worker }
501*9356374aSAndroid Build Coastguard Worker
502*9356374aSAndroid Build Coastguard Worker return false; // hit iteration limit or a bug in our stack handling
503*9356374aSAndroid Build Coastguard Worker }
504*9356374aSAndroid Build Coastguard Worker
505*9356374aSAndroid Build Coastguard Worker private:
506*9356374aSAndroid Build Coastguard Worker // Enumerates resumption points for ABSL_DEMANGLER_RECURSE calls.
507*9356374aSAndroid Build Coastguard Worker enum ReturnAddress : uint8_t {
508*9356374aSAndroid Build Coastguard Worker kInstantiatingCrate,
509*9356374aSAndroid Build Coastguard Worker kVendorSpecificSuffix,
510*9356374aSAndroid Build Coastguard Worker kIdentifierInUppercaseNamespace,
511*9356374aSAndroid Build Coastguard Worker kIdentifierInLowercaseNamespace,
512*9356374aSAndroid Build Coastguard Worker kInherentImplType,
513*9356374aSAndroid Build Coastguard Worker kInherentImplEnding,
514*9356374aSAndroid Build Coastguard Worker kTraitImplType,
515*9356374aSAndroid Build Coastguard Worker kTraitImplInfix,
516*9356374aSAndroid Build Coastguard Worker kTraitImplEnding,
517*9356374aSAndroid Build Coastguard Worker kImplPathEnding,
518*9356374aSAndroid Build Coastguard Worker kTraitDefinitionInfix,
519*9356374aSAndroid Build Coastguard Worker kTraitDefinitionEnding,
520*9356374aSAndroid Build Coastguard Worker kArraySize,
521*9356374aSAndroid Build Coastguard Worker kFinishArray,
522*9356374aSAndroid Build Coastguard Worker kSliceEnding,
523*9356374aSAndroid Build Coastguard Worker kAfterFirstTupleElement,
524*9356374aSAndroid Build Coastguard Worker kAfterSecondTupleElement,
525*9356374aSAndroid Build Coastguard Worker kAfterThirdTupleElement,
526*9356374aSAndroid Build Coastguard Worker kAfterSubsequentTupleElement,
527*9356374aSAndroid Build Coastguard Worker kContinueParameterList,
528*9356374aSAndroid Build Coastguard Worker kFinishFn,
529*9356374aSAndroid Build Coastguard Worker kBeginAutoTraits,
530*9356374aSAndroid Build Coastguard Worker kContinueAutoTraits,
531*9356374aSAndroid Build Coastguard Worker kContinueDynTrait,
532*9356374aSAndroid Build Coastguard Worker kContinueAssocBinding,
533*9356374aSAndroid Build Coastguard Worker kConstData,
534*9356374aSAndroid Build Coastguard Worker kBeginGenericArgList,
535*9356374aSAndroid Build Coastguard Worker kContinueGenericArgList,
536*9356374aSAndroid Build Coastguard Worker kPathBackrefEnding,
537*9356374aSAndroid Build Coastguard Worker kTypeBackrefEnding,
538*9356374aSAndroid Build Coastguard Worker kConstantBackrefEnding,
539*9356374aSAndroid Build Coastguard Worker };
540*9356374aSAndroid Build Coastguard Worker
541*9356374aSAndroid Build Coastguard Worker // Element counts for the stack arrays. Larger stack sizes accommodate more
542*9356374aSAndroid Build Coastguard Worker // deeply nested names at the cost of a larger footprint on the C++ call
543*9356374aSAndroid Build Coastguard Worker // stack.
544*9356374aSAndroid Build Coastguard Worker enum {
545*9356374aSAndroid Build Coastguard Worker // Maximum recursive calls outstanding at one time.
546*9356374aSAndroid Build Coastguard Worker kStackSize = 256,
547*9356374aSAndroid Build Coastguard Worker
548*9356374aSAndroid Build Coastguard Worker // Maximum N<uppercase> nested-paths open at once. We do not expect
549*9356374aSAndroid Build Coastguard Worker // closures inside closures inside closures as much as functions inside
550*9356374aSAndroid Build Coastguard Worker // modules inside other modules, so we can use a smaller array here.
551*9356374aSAndroid Build Coastguard Worker kNamespaceStackSize = 64,
552*9356374aSAndroid Build Coastguard Worker
553*9356374aSAndroid Build Coastguard Worker // Maximum number of nested backrefs. We can keep this stack pretty small
554*9356374aSAndroid Build Coastguard Worker // because we do not follow backrefs inside generic-args or other contexts
555*9356374aSAndroid Build Coastguard Worker // that suppress printing, so deep stacking is unlikely in practice.
556*9356374aSAndroid Build Coastguard Worker kPositionStackSize = 16,
557*9356374aSAndroid Build Coastguard Worker };
558*9356374aSAndroid Build Coastguard Worker
559*9356374aSAndroid Build Coastguard Worker // Returns the next input character without consuming it.
Peek() const560*9356374aSAndroid Build Coastguard Worker char Peek() const { return encoding_[pos_]; }
561*9356374aSAndroid Build Coastguard Worker
562*9356374aSAndroid Build Coastguard Worker // Consumes and returns the next input character.
Take()563*9356374aSAndroid Build Coastguard Worker char Take() { return encoding_[pos_++]; }
564*9356374aSAndroid Build Coastguard Worker
565*9356374aSAndroid Build Coastguard Worker // If the next input character is the given character, consumes it and returns
566*9356374aSAndroid Build Coastguard Worker // true; otherwise returns false without consuming a character.
Eat(char want)567*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool Eat(char want) {
568*9356374aSAndroid Build Coastguard Worker if (encoding_[pos_] != want) return false;
569*9356374aSAndroid Build Coastguard Worker ++pos_;
570*9356374aSAndroid Build Coastguard Worker return true;
571*9356374aSAndroid Build Coastguard Worker }
572*9356374aSAndroid Build Coastguard Worker
573*9356374aSAndroid Build Coastguard Worker // Provided there is enough remaining output space, appends c to the output,
574*9356374aSAndroid Build Coastguard Worker // writing a fresh NUL terminator afterward, and returns true. Returns false
575*9356374aSAndroid Build Coastguard Worker // if the output buffer had less than two bytes free.
EmitChar(char c)576*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool EmitChar(char c) {
577*9356374aSAndroid Build Coastguard Worker if (silence_depth_ > 0) return true;
578*9356374aSAndroid Build Coastguard Worker if (out_end_ - out_ < 2) return false;
579*9356374aSAndroid Build Coastguard Worker *out_++ = c;
580*9356374aSAndroid Build Coastguard Worker *out_ = '\0';
581*9356374aSAndroid Build Coastguard Worker return true;
582*9356374aSAndroid Build Coastguard Worker }
583*9356374aSAndroid Build Coastguard Worker
584*9356374aSAndroid Build Coastguard Worker // Provided there is enough remaining output space, appends the C string token
585*9356374aSAndroid Build Coastguard Worker // to the output, followed by a NUL character, and returns true. Returns
586*9356374aSAndroid Build Coastguard Worker // false if not everything fit into the output buffer.
Emit(const char * token)587*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool Emit(const char* token) {
588*9356374aSAndroid Build Coastguard Worker if (silence_depth_ > 0) return true;
589*9356374aSAndroid Build Coastguard Worker const size_t token_length = std::strlen(token);
590*9356374aSAndroid Build Coastguard Worker const size_t bytes_to_copy = token_length + 1; // token and final NUL
591*9356374aSAndroid Build Coastguard Worker if (static_cast<size_t>(out_end_ - out_) < bytes_to_copy) return false;
592*9356374aSAndroid Build Coastguard Worker std::memcpy(out_, token, bytes_to_copy);
593*9356374aSAndroid Build Coastguard Worker out_ += token_length;
594*9356374aSAndroid Build Coastguard Worker return true;
595*9356374aSAndroid Build Coastguard Worker }
596*9356374aSAndroid Build Coastguard Worker
597*9356374aSAndroid Build Coastguard Worker // Provided there is enough remaining output space, appends the decimal form
598*9356374aSAndroid Build Coastguard Worker // of disambiguator (if it's nonnegative) or "?" (if it's negative) to the
599*9356374aSAndroid Build Coastguard Worker // output, followed by a NUL character, and returns true. Returns false if
600*9356374aSAndroid Build Coastguard Worker // not everything fit into the output buffer.
EmitDisambiguator(int disambiguator)601*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool EmitDisambiguator(int disambiguator) {
602*9356374aSAndroid Build Coastguard Worker if (disambiguator < 0) return EmitChar('?'); // parsed but too large
603*9356374aSAndroid Build Coastguard Worker if (disambiguator == 0) return EmitChar('0');
604*9356374aSAndroid Build Coastguard Worker // Convert disambiguator to decimal text. Three digits per byte is enough
605*9356374aSAndroid Build Coastguard Worker // because 999 > 256. The bound will remain correct even if future
606*9356374aSAndroid Build Coastguard Worker // maintenance changes the type of the disambiguator variable.
607*9356374aSAndroid Build Coastguard Worker char digits[3 * sizeof(disambiguator)] = {};
608*9356374aSAndroid Build Coastguard Worker size_t leading_digit_index = sizeof(digits) - 1;
609*9356374aSAndroid Build Coastguard Worker for (; disambiguator > 0; disambiguator /= 10) {
610*9356374aSAndroid Build Coastguard Worker digits[--leading_digit_index] =
611*9356374aSAndroid Build Coastguard Worker static_cast<char>('0' + disambiguator % 10);
612*9356374aSAndroid Build Coastguard Worker }
613*9356374aSAndroid Build Coastguard Worker return Emit(digits + leading_digit_index);
614*9356374aSAndroid Build Coastguard Worker }
615*9356374aSAndroid Build Coastguard Worker
616*9356374aSAndroid Build Coastguard Worker // Consumes an optional disambiguator (s123_) from the input.
617*9356374aSAndroid Build Coastguard Worker //
618*9356374aSAndroid Build Coastguard Worker // On success returns true and fills value with the encoded value if it was
619*9356374aSAndroid Build Coastguard Worker // not too big, otherwise with -1. If the optional disambiguator was omitted,
620*9356374aSAndroid Build Coastguard Worker // value is 0. On parse failure returns false and sets value to -1.
ParseDisambiguator(int & value)621*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseDisambiguator(int& value) {
622*9356374aSAndroid Build Coastguard Worker value = -1;
623*9356374aSAndroid Build Coastguard Worker
624*9356374aSAndroid Build Coastguard Worker // disambiguator = s base-62-number
625*9356374aSAndroid Build Coastguard Worker //
626*9356374aSAndroid Build Coastguard Worker // Disambiguators are optional. An omitted disambiguator is zero.
627*9356374aSAndroid Build Coastguard Worker if (!Eat('s')) {
628*9356374aSAndroid Build Coastguard Worker value = 0;
629*9356374aSAndroid Build Coastguard Worker return true;
630*9356374aSAndroid Build Coastguard Worker }
631*9356374aSAndroid Build Coastguard Worker int base_62_value = 0;
632*9356374aSAndroid Build Coastguard Worker if (!ParseBase62Number(base_62_value)) return false;
633*9356374aSAndroid Build Coastguard Worker value = base_62_value < 0 ? -1 : base_62_value + 1;
634*9356374aSAndroid Build Coastguard Worker return true;
635*9356374aSAndroid Build Coastguard Worker }
636*9356374aSAndroid Build Coastguard Worker
637*9356374aSAndroid Build Coastguard Worker // Consumes a base-62 number like _ or 123_ from the input.
638*9356374aSAndroid Build Coastguard Worker //
639*9356374aSAndroid Build Coastguard Worker // On success returns true and fills value with the encoded value if it was
640*9356374aSAndroid Build Coastguard Worker // not too big, otherwise with -1. On parse failure returns false and sets
641*9356374aSAndroid Build Coastguard Worker // value to -1.
ParseBase62Number(int & value)642*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseBase62Number(int& value) {
643*9356374aSAndroid Build Coastguard Worker value = -1;
644*9356374aSAndroid Build Coastguard Worker
645*9356374aSAndroid Build Coastguard Worker // base-62-number = (digit | lower | upper)* _
646*9356374aSAndroid Build Coastguard Worker //
647*9356374aSAndroid Build Coastguard Worker // An empty base-62 digit sequence means 0.
648*9356374aSAndroid Build Coastguard Worker if (Eat('_')) {
649*9356374aSAndroid Build Coastguard Worker value = 0;
650*9356374aSAndroid Build Coastguard Worker return true;
651*9356374aSAndroid Build Coastguard Worker }
652*9356374aSAndroid Build Coastguard Worker
653*9356374aSAndroid Build Coastguard Worker // A nonempty digit sequence denotes its base-62 value plus 1.
654*9356374aSAndroid Build Coastguard Worker int encoded_number = 0;
655*9356374aSAndroid Build Coastguard Worker bool overflowed = false;
656*9356374aSAndroid Build Coastguard Worker while (IsAlpha(Peek()) || IsDigit(Peek())) {
657*9356374aSAndroid Build Coastguard Worker const char c = Take();
658*9356374aSAndroid Build Coastguard Worker if (encoded_number >= std::numeric_limits<int>::max()/62) {
659*9356374aSAndroid Build Coastguard Worker // If we are close to overflowing an int, keep parsing but stop updating
660*9356374aSAndroid Build Coastguard Worker // encoded_number and remember to return -1 at the end. The point is to
661*9356374aSAndroid Build Coastguard Worker // avoid undefined behavior while parsing crate-root disambiguators,
662*9356374aSAndroid Build Coastguard Worker // which are large in practice but not shown in demangling, while
663*9356374aSAndroid Build Coastguard Worker // successfully computing closure and shim disambiguators, which are
664*9356374aSAndroid Build Coastguard Worker // typically small and are printed out.
665*9356374aSAndroid Build Coastguard Worker overflowed = true;
666*9356374aSAndroid Build Coastguard Worker } else {
667*9356374aSAndroid Build Coastguard Worker int digit;
668*9356374aSAndroid Build Coastguard Worker if (IsDigit(c)) {
669*9356374aSAndroid Build Coastguard Worker digit = c - '0';
670*9356374aSAndroid Build Coastguard Worker } else if (IsLower(c)) {
671*9356374aSAndroid Build Coastguard Worker digit = c - 'a' + 10;
672*9356374aSAndroid Build Coastguard Worker } else {
673*9356374aSAndroid Build Coastguard Worker digit = c - 'A' + 36;
674*9356374aSAndroid Build Coastguard Worker }
675*9356374aSAndroid Build Coastguard Worker encoded_number = 62 * encoded_number + digit;
676*9356374aSAndroid Build Coastguard Worker }
677*9356374aSAndroid Build Coastguard Worker }
678*9356374aSAndroid Build Coastguard Worker
679*9356374aSAndroid Build Coastguard Worker if (!Eat('_')) return false;
680*9356374aSAndroid Build Coastguard Worker if (!overflowed) value = encoded_number + 1;
681*9356374aSAndroid Build Coastguard Worker return true;
682*9356374aSAndroid Build Coastguard Worker }
683*9356374aSAndroid Build Coastguard Worker
684*9356374aSAndroid Build Coastguard Worker // Consumes an identifier from the input, returning true on success.
685*9356374aSAndroid Build Coastguard Worker //
686*9356374aSAndroid Build Coastguard Worker // A nonzero uppercase_namespace specifies the character after the N in a
687*9356374aSAndroid Build Coastguard Worker // nested-identifier, e.g., 'C' for a closure, allowing ParseIdentifier to
688*9356374aSAndroid Build Coastguard Worker // write out the name with the conventional decoration for that namespace.
ParseIdentifier(char uppercase_namespace='\\0')689*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseIdentifier(char uppercase_namespace = '\0') {
690*9356374aSAndroid Build Coastguard Worker // identifier -> disambiguator? undisambiguated-identifier
691*9356374aSAndroid Build Coastguard Worker int disambiguator = 0;
692*9356374aSAndroid Build Coastguard Worker if (!ParseDisambiguator(disambiguator)) return false;
693*9356374aSAndroid Build Coastguard Worker
694*9356374aSAndroid Build Coastguard Worker return ParseUndisambiguatedIdentifier(uppercase_namespace, disambiguator);
695*9356374aSAndroid Build Coastguard Worker }
696*9356374aSAndroid Build Coastguard Worker
697*9356374aSAndroid Build Coastguard Worker // Consumes from the input an identifier with no preceding disambiguator,
698*9356374aSAndroid Build Coastguard Worker // returning true on success.
699*9356374aSAndroid Build Coastguard Worker //
700*9356374aSAndroid Build Coastguard Worker // When ParseIdentifier calls this, it passes the N<namespace> character and
701*9356374aSAndroid Build Coastguard Worker // disambiguator value so that "{closure#42}" and similar forms can be
702*9356374aSAndroid Build Coastguard Worker // rendered correctly.
703*9356374aSAndroid Build Coastguard Worker //
704*9356374aSAndroid Build Coastguard Worker // At other appearances of undisambiguated-identifier in the grammar, this
705*9356374aSAndroid Build Coastguard Worker // treatment is not applicable, and the call site omits both arguments.
ParseUndisambiguatedIdentifier(char uppercase_namespace='\\0',int disambiguator=0)706*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseUndisambiguatedIdentifier(
707*9356374aSAndroid Build Coastguard Worker char uppercase_namespace = '\0', int disambiguator = 0) {
708*9356374aSAndroid Build Coastguard Worker // undisambiguated-identifier -> u? decimal-number _? bytes
709*9356374aSAndroid Build Coastguard Worker const bool is_punycoded = Eat('u');
710*9356374aSAndroid Build Coastguard Worker if (!IsDigit(Peek())) return false;
711*9356374aSAndroid Build Coastguard Worker int num_bytes = 0;
712*9356374aSAndroid Build Coastguard Worker if (!ParseDecimalNumber(num_bytes)) return false;
713*9356374aSAndroid Build Coastguard Worker (void)Eat('_'); // optional separator, needed if a digit follows
714*9356374aSAndroid Build Coastguard Worker if (is_punycoded) {
715*9356374aSAndroid Build Coastguard Worker DecodeRustPunycodeOptions options;
716*9356374aSAndroid Build Coastguard Worker options.punycode_begin = &encoding_[pos_];
717*9356374aSAndroid Build Coastguard Worker options.punycode_end = &encoding_[pos_] + num_bytes;
718*9356374aSAndroid Build Coastguard Worker options.out_begin = out_;
719*9356374aSAndroid Build Coastguard Worker options.out_end = out_end_;
720*9356374aSAndroid Build Coastguard Worker out_ = DecodeRustPunycode(options);
721*9356374aSAndroid Build Coastguard Worker if (out_ == nullptr) return false;
722*9356374aSAndroid Build Coastguard Worker pos_ += static_cast<size_t>(num_bytes);
723*9356374aSAndroid Build Coastguard Worker }
724*9356374aSAndroid Build Coastguard Worker
725*9356374aSAndroid Build Coastguard Worker // Emit the beginnings of braced forms like {shim:vtable#0}.
726*9356374aSAndroid Build Coastguard Worker if (uppercase_namespace != '\0') {
727*9356374aSAndroid Build Coastguard Worker switch (uppercase_namespace) {
728*9356374aSAndroid Build Coastguard Worker case 'C':
729*9356374aSAndroid Build Coastguard Worker if (!Emit("{closure")) return false;
730*9356374aSAndroid Build Coastguard Worker break;
731*9356374aSAndroid Build Coastguard Worker case 'S':
732*9356374aSAndroid Build Coastguard Worker if (!Emit("{shim")) return false;
733*9356374aSAndroid Build Coastguard Worker break;
734*9356374aSAndroid Build Coastguard Worker default:
735*9356374aSAndroid Build Coastguard Worker if (!EmitChar('{') || !EmitChar(uppercase_namespace)) return false;
736*9356374aSAndroid Build Coastguard Worker break;
737*9356374aSAndroid Build Coastguard Worker }
738*9356374aSAndroid Build Coastguard Worker if (num_bytes > 0 && !Emit(":")) return false;
739*9356374aSAndroid Build Coastguard Worker }
740*9356374aSAndroid Build Coastguard Worker
741*9356374aSAndroid Build Coastguard Worker // Emit the name itself.
742*9356374aSAndroid Build Coastguard Worker if (!is_punycoded) {
743*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < num_bytes; ++i) {
744*9356374aSAndroid Build Coastguard Worker const char c = Take();
745*9356374aSAndroid Build Coastguard Worker if (!IsIdentifierChar(c) &&
746*9356374aSAndroid Build Coastguard Worker // The spec gives toolchains the choice of Punycode or raw UTF-8 for
747*9356374aSAndroid Build Coastguard Worker // identifiers containing code points above 0x7f, so accept bytes
748*9356374aSAndroid Build Coastguard Worker // with the high bit set.
749*9356374aSAndroid Build Coastguard Worker (c & 0x80) == 0) {
750*9356374aSAndroid Build Coastguard Worker return false;
751*9356374aSAndroid Build Coastguard Worker }
752*9356374aSAndroid Build Coastguard Worker if (!EmitChar(c)) return false;
753*9356374aSAndroid Build Coastguard Worker }
754*9356374aSAndroid Build Coastguard Worker }
755*9356374aSAndroid Build Coastguard Worker
756*9356374aSAndroid Build Coastguard Worker // Emit the endings of braced forms, e.g., "#42}".
757*9356374aSAndroid Build Coastguard Worker if (uppercase_namespace != '\0') {
758*9356374aSAndroid Build Coastguard Worker if (!EmitChar('#')) return false;
759*9356374aSAndroid Build Coastguard Worker if (!EmitDisambiguator(disambiguator)) return false;
760*9356374aSAndroid Build Coastguard Worker if (!EmitChar('}')) return false;
761*9356374aSAndroid Build Coastguard Worker }
762*9356374aSAndroid Build Coastguard Worker
763*9356374aSAndroid Build Coastguard Worker return true;
764*9356374aSAndroid Build Coastguard Worker }
765*9356374aSAndroid Build Coastguard Worker
766*9356374aSAndroid Build Coastguard Worker // Consumes a decimal number like 0 or 123 from the input. On success returns
767*9356374aSAndroid Build Coastguard Worker // true and fills value with the encoded value. If the encoded value is too
768*9356374aSAndroid Build Coastguard Worker // large or otherwise unparsable, returns false and sets value to -1.
ParseDecimalNumber(int & value)769*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseDecimalNumber(int& value) {
770*9356374aSAndroid Build Coastguard Worker value = -1;
771*9356374aSAndroid Build Coastguard Worker if (!IsDigit(Peek())) return false;
772*9356374aSAndroid Build Coastguard Worker int encoded_number = Take() - '0';
773*9356374aSAndroid Build Coastguard Worker if (encoded_number == 0) {
774*9356374aSAndroid Build Coastguard Worker // Decimal numbers are never encoded with extra leading zeroes.
775*9356374aSAndroid Build Coastguard Worker value = 0;
776*9356374aSAndroid Build Coastguard Worker return true;
777*9356374aSAndroid Build Coastguard Worker }
778*9356374aSAndroid Build Coastguard Worker while (IsDigit(Peek()) &&
779*9356374aSAndroid Build Coastguard Worker // avoid overflow
780*9356374aSAndroid Build Coastguard Worker encoded_number < std::numeric_limits<int>::max()/10) {
781*9356374aSAndroid Build Coastguard Worker encoded_number = 10 * encoded_number + (Take() - '0');
782*9356374aSAndroid Build Coastguard Worker }
783*9356374aSAndroid Build Coastguard Worker if (IsDigit(Peek())) return false; // too big
784*9356374aSAndroid Build Coastguard Worker value = encoded_number;
785*9356374aSAndroid Build Coastguard Worker return true;
786*9356374aSAndroid Build Coastguard Worker }
787*9356374aSAndroid Build Coastguard Worker
788*9356374aSAndroid Build Coastguard Worker // Consumes a binder of higher-ranked lifetimes if one is present. On success
789*9356374aSAndroid Build Coastguard Worker // returns true and discards the encoded lifetime count. On parse failure
790*9356374aSAndroid Build Coastguard Worker // returns false.
ParseOptionalBinder()791*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseOptionalBinder() {
792*9356374aSAndroid Build Coastguard Worker // binder -> G base-62-number
793*9356374aSAndroid Build Coastguard Worker if (!Eat('G')) return true;
794*9356374aSAndroid Build Coastguard Worker int ignored_binding_count;
795*9356374aSAndroid Build Coastguard Worker return ParseBase62Number(ignored_binding_count);
796*9356374aSAndroid Build Coastguard Worker }
797*9356374aSAndroid Build Coastguard Worker
798*9356374aSAndroid Build Coastguard Worker // Consumes a lifetime if one is present.
799*9356374aSAndroid Build Coastguard Worker //
800*9356374aSAndroid Build Coastguard Worker // On success returns true and discards the lifetime index. We do not print
801*9356374aSAndroid Build Coastguard Worker // or even range-check lifetimes because they are a finer detail than other
802*9356374aSAndroid Build Coastguard Worker // things we omit from output, such as the entire contents of generic-args.
803*9356374aSAndroid Build Coastguard Worker //
804*9356374aSAndroid Build Coastguard Worker // On parse failure returns false.
ParseOptionalLifetime()805*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseOptionalLifetime() {
806*9356374aSAndroid Build Coastguard Worker // lifetime -> L base-62-number
807*9356374aSAndroid Build Coastguard Worker if (!Eat('L')) return true;
808*9356374aSAndroid Build Coastguard Worker int ignored_de_bruijn_index;
809*9356374aSAndroid Build Coastguard Worker return ParseBase62Number(ignored_de_bruijn_index);
810*9356374aSAndroid Build Coastguard Worker }
811*9356374aSAndroid Build Coastguard Worker
812*9356374aSAndroid Build Coastguard Worker // Consumes a lifetime just like ParseOptionalLifetime, but returns false if
813*9356374aSAndroid Build Coastguard Worker // there is no lifetime here.
ParseRequiredLifetime()814*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool ParseRequiredLifetime() {
815*9356374aSAndroid Build Coastguard Worker if (Peek() != 'L') return false;
816*9356374aSAndroid Build Coastguard Worker return ParseOptionalLifetime();
817*9356374aSAndroid Build Coastguard Worker }
818*9356374aSAndroid Build Coastguard Worker
819*9356374aSAndroid Build Coastguard Worker // Pushes ns onto the namespace stack and returns true if the stack is not
820*9356374aSAndroid Build Coastguard Worker // full, else returns false.
PushNamespace(char ns)821*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool PushNamespace(char ns) {
822*9356374aSAndroid Build Coastguard Worker if (namespace_depth_ == kNamespaceStackSize) return false;
823*9356374aSAndroid Build Coastguard Worker namespace_stack_[namespace_depth_++] = ns;
824*9356374aSAndroid Build Coastguard Worker return true;
825*9356374aSAndroid Build Coastguard Worker }
826*9356374aSAndroid Build Coastguard Worker
827*9356374aSAndroid Build Coastguard Worker // Pops the last pushed namespace. Requires that the namespace stack is not
828*9356374aSAndroid Build Coastguard Worker // empty (namespace_depth_ > 0).
PopNamespace()829*9356374aSAndroid Build Coastguard Worker char PopNamespace() { return namespace_stack_[--namespace_depth_]; }
830*9356374aSAndroid Build Coastguard Worker
831*9356374aSAndroid Build Coastguard Worker // Pushes position onto the position stack and returns true if the stack is
832*9356374aSAndroid Build Coastguard Worker // not full, else returns false.
PushPosition(int position)833*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool PushPosition(int position) {
834*9356374aSAndroid Build Coastguard Worker if (position_depth_ == kPositionStackSize) return false;
835*9356374aSAndroid Build Coastguard Worker position_stack_[position_depth_++] = position;
836*9356374aSAndroid Build Coastguard Worker return true;
837*9356374aSAndroid Build Coastguard Worker }
838*9356374aSAndroid Build Coastguard Worker
839*9356374aSAndroid Build Coastguard Worker // Pops the last pushed input position. Requires that the position stack is
840*9356374aSAndroid Build Coastguard Worker // not empty (position_depth_ > 0).
PopPosition()841*9356374aSAndroid Build Coastguard Worker int PopPosition() { return position_stack_[--position_depth_]; }
842*9356374aSAndroid Build Coastguard Worker
843*9356374aSAndroid Build Coastguard Worker // Consumes a base-62-number denoting a backref target, pushes the current
844*9356374aSAndroid Build Coastguard Worker // input position on the data stack, and sets the input position to the
845*9356374aSAndroid Build Coastguard Worker // beginning of the backref target. Returns true on success. Returns false
846*9356374aSAndroid Build Coastguard Worker // if parsing failed, the stack is exhausted, or the backref target position
847*9356374aSAndroid Build Coastguard Worker // is out of range.
BeginBackref()848*9356374aSAndroid Build Coastguard Worker ABSL_MUST_USE_RESULT bool BeginBackref() {
849*9356374aSAndroid Build Coastguard Worker // backref = B base-62-number (B already consumed)
850*9356374aSAndroid Build Coastguard Worker //
851*9356374aSAndroid Build Coastguard Worker // Reject backrefs that don't parse, overflow int, or don't point backward.
852*9356374aSAndroid Build Coastguard Worker // If the offset looks fine, adjust it to account for the _R prefix.
853*9356374aSAndroid Build Coastguard Worker int offset = 0;
854*9356374aSAndroid Build Coastguard Worker const int offset_of_this_backref =
855*9356374aSAndroid Build Coastguard Worker pos_ - 2 /* _R */ - 1 /* B already consumed */;
856*9356374aSAndroid Build Coastguard Worker if (!ParseBase62Number(offset) || offset < 0 ||
857*9356374aSAndroid Build Coastguard Worker offset >= offset_of_this_backref) {
858*9356374aSAndroid Build Coastguard Worker return false;
859*9356374aSAndroid Build Coastguard Worker }
860*9356374aSAndroid Build Coastguard Worker offset += 2;
861*9356374aSAndroid Build Coastguard Worker
862*9356374aSAndroid Build Coastguard Worker // Save the old position to restore later.
863*9356374aSAndroid Build Coastguard Worker if (!PushPosition(pos_)) return false;
864*9356374aSAndroid Build Coastguard Worker
865*9356374aSAndroid Build Coastguard Worker // Move the input position to the backref target.
866*9356374aSAndroid Build Coastguard Worker //
867*9356374aSAndroid Build Coastguard Worker // Note that we do not check whether the new position points to the
868*9356374aSAndroid Build Coastguard Worker // beginning of a construct matching the context in which the backref
869*9356374aSAndroid Build Coastguard Worker // appeared. We just jump to it and see whether nested parsing succeeds.
870*9356374aSAndroid Build Coastguard Worker // We therefore accept various wrong manglings, e.g., a type backref
871*9356374aSAndroid Build Coastguard Worker // pointing to an 'l' character inside an identifier, which happens to mean
872*9356374aSAndroid Build Coastguard Worker // i32 when parsed as a type mangling. This saves the complexity and RAM
873*9356374aSAndroid Build Coastguard Worker // footprint of remembering which offsets began which kinds of
874*9356374aSAndroid Build Coastguard Worker // substructures. Existing demanglers take similar shortcuts.
875*9356374aSAndroid Build Coastguard Worker pos_ = offset;
876*9356374aSAndroid Build Coastguard Worker return true;
877*9356374aSAndroid Build Coastguard Worker }
878*9356374aSAndroid Build Coastguard Worker
879*9356374aSAndroid Build Coastguard Worker // Cleans up after a backref production by restoring the previous input
880*9356374aSAndroid Build Coastguard Worker // position from the data stack.
EndBackref()881*9356374aSAndroid Build Coastguard Worker void EndBackref() { pos_ = PopPosition(); }
882*9356374aSAndroid Build Coastguard Worker
883*9356374aSAndroid Build Coastguard Worker // The leftmost recursion_depth_ elements of recursion_stack_ contain the
884*9356374aSAndroid Build Coastguard Worker // ReturnAddresses pushed by ABSL_DEMANGLER_RECURSE calls not yet completed.
885*9356374aSAndroid Build Coastguard Worker ReturnAddress recursion_stack_[kStackSize] = {};
886*9356374aSAndroid Build Coastguard Worker int recursion_depth_ = 0;
887*9356374aSAndroid Build Coastguard Worker
888*9356374aSAndroid Build Coastguard Worker // The leftmost namespace_depth_ elements of namespace_stack_ contain the
889*9356374aSAndroid Build Coastguard Worker // uppercase namespace identifiers for open nested-paths, e.g., 'C' for a
890*9356374aSAndroid Build Coastguard Worker // closure.
891*9356374aSAndroid Build Coastguard Worker char namespace_stack_[kNamespaceStackSize] = {};
892*9356374aSAndroid Build Coastguard Worker int namespace_depth_ = 0;
893*9356374aSAndroid Build Coastguard Worker
894*9356374aSAndroid Build Coastguard Worker // The leftmost position_depth_ elements of position_stack_ contain the input
895*9356374aSAndroid Build Coastguard Worker // positions to return to after fully printing the targets of backrefs.
896*9356374aSAndroid Build Coastguard Worker int position_stack_[kPositionStackSize] = {};
897*9356374aSAndroid Build Coastguard Worker int position_depth_ = 0;
898*9356374aSAndroid Build Coastguard Worker
899*9356374aSAndroid Build Coastguard Worker // Anything parsed while silence_depth_ > 0 contributes nothing to the
900*9356374aSAndroid Build Coastguard Worker // demangled output. For constructs omitted from the demangling, such as
901*9356374aSAndroid Build Coastguard Worker // impl-path and the contents of generic-args, we will increment
902*9356374aSAndroid Build Coastguard Worker // silence_depth_ on the way in and decrement silence_depth_ on the way out.
903*9356374aSAndroid Build Coastguard Worker int silence_depth_ = 0;
904*9356374aSAndroid Build Coastguard Worker
905*9356374aSAndroid Build Coastguard Worker // Input: encoding_ points to a Rust mangled symbol, and encoding_[pos_] is
906*9356374aSAndroid Build Coastguard Worker // the next input character to be scanned.
907*9356374aSAndroid Build Coastguard Worker int pos_ = 0;
908*9356374aSAndroid Build Coastguard Worker const char* encoding_ = nullptr;
909*9356374aSAndroid Build Coastguard Worker
910*9356374aSAndroid Build Coastguard Worker // Output: *out_ is where the next output character should be written, and
911*9356374aSAndroid Build Coastguard Worker // out_end_ points past the last byte of available space.
912*9356374aSAndroid Build Coastguard Worker char* out_ = nullptr;
913*9356374aSAndroid Build Coastguard Worker char* out_end_ = nullptr;
914*9356374aSAndroid Build Coastguard Worker };
915*9356374aSAndroid Build Coastguard Worker
916*9356374aSAndroid Build Coastguard Worker } // namespace
917*9356374aSAndroid Build Coastguard Worker
DemangleRustSymbolEncoding(const char * mangled,char * out,size_t out_size)918*9356374aSAndroid Build Coastguard Worker bool DemangleRustSymbolEncoding(const char* mangled, char* out,
919*9356374aSAndroid Build Coastguard Worker size_t out_size) {
920*9356374aSAndroid Build Coastguard Worker return RustSymbolParser(mangled, out, out + out_size).Parse();
921*9356374aSAndroid Build Coastguard Worker }
922*9356374aSAndroid Build Coastguard Worker
923*9356374aSAndroid Build Coastguard Worker } // namespace debugging_internal
924*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END
925*9356374aSAndroid Build Coastguard Worker } // namespace absl
926