diff options
author | Chris Mihelich <cmihelic@google.com> | 2024-05-21 15:00:10 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2024-05-21 15:01:12 -0700 |
commit | 7a730c1b22702b931431c84fe8e42b9c4b0051a0 (patch) | |
tree | 796a0f228fd26312724c8035df09f8617cd2bcda /absl/debugging | |
parent | 22108fae90c4edd0e50cb8546b0a883ca4558e0c (diff) | |
download | abseil-7a730c1b22702b931431c84fe8e42b9c4b0051a0.tar.gz abseil-7a730c1b22702b931431c84fe8e42b9c4b0051a0.tar.bz2 abseil-7a730c1b22702b931431c84fe8e42b9c4b0051a0.zip |
Recognize const and array-type in Rust mangled names.
PiperOrigin-RevId: 635938476
Change-Id: I49cba8789452f13cfeb4a24203b3b46624aa7269
Diffstat (limited to 'absl/debugging')
-rw-r--r-- | absl/debugging/internal/demangle_rust.cc | 67 | ||||
-rw-r--r-- | absl/debugging/internal/demangle_rust_test.cc | 54 |
2 files changed, 119 insertions, 2 deletions
diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc index fd205924..20b812a4 100644 --- a/absl/debugging/internal/demangle_rust.cc +++ b/absl/debugging/internal/demangle_rust.cc @@ -36,6 +36,7 @@ bool IsLower(char c) { return 'a' <= c && c <= 'z'; } bool IsUpper(char c) { return 'A' <= c && c <= 'Z'; } bool IsAlpha(char c) { return IsLower(c) || IsUpper(c); } bool IsIdentifierChar(char c) { return IsAlpha(c) || IsDigit(c) || c == '_'; } +bool IsLowerHexDigit(char c) { return IsDigit(c) || ('a' <= c && c <= 'f'); } const char* BasicTypeName(char c) { switch (c) { @@ -212,7 +213,15 @@ class RustSymbolParser { if (type_name == nullptr || !Emit(type_name)) return false; continue; } - if (Eat('A')) return false; // array-type not yet implemented + if (Eat('A')) { + // array-type = A type const + if (!Emit("[")) return false; + ABSL_DEMANGLER_RECURSE(type, kArraySize); + if (!Emit("; ")) return false; + ABSL_DEMANGLER_RECURSE(constant, kFinishArray); + if (!Emit("]")) return false; + continue; + } if (Eat('S')) { if (!Emit("[")) return false; ABSL_DEMANGLER_RECURSE(type, kSliceEnding); @@ -290,6 +299,48 @@ class RustSymbolParser { --silence_depth_; continue; + // const -> type const-data | p | backref + // + // const is a C++ keyword, so we use the label `constant` instead. + constant: + if (Eat('B')) goto const_backref; + if (Eat('p')) { + if (!Emit("_")) return false; + continue; + } + + // Scan the type without printing it. + // + // The Rust language restricts the type of a const generic argument + // much more than the mangling grammar does. We do not enforce this. + // + // We also do not bother printing false, true, 'A', and '\u{abcd}' for + // the types bool and char. Because we do not print generic-args + // contents, we expect to print constants only in array sizes, and + // those should not be bool or char. + ++silence_depth_; + ABSL_DEMANGLER_RECURSE(type, kConstData); + --silence_depth_; + + // const-data -> n? hex-digit* _ + // + // Although the grammar doesn't say this, existing demanglers expect + // that zero is 0, not an empty digit sequence, and no nonzero value + // may have leading zero digits. Also n0_ is accepted and printed as + // -0, though a toolchain will probably never write that encoding. + if (Eat('n') && !EmitChar('-')) return false; + if (!Emit("0x")) return false; + if (Eat('0')) { + if (!EmitChar('0')) return false; + if (!Eat('_')) return false; + continue; + } + while (IsLowerHexDigit(Peek())) { + if (!EmitChar(Take())) return false; + } + if (!Eat('_')) return false; + continue; + // generic-args -> I path generic-arg* E (I already consumed) // // We follow the C++ demangler in omitting all the arguments from the @@ -307,7 +358,7 @@ class RustSymbolParser { // generic-arg -> lifetime | type | K const generic_arg: if (Eat('L')) return false; // lifetime not yet implemented - if (Eat('K')) return false; // const not yet implemented + if (Eat('K')) goto constant; goto type; // backref -> B base-62-number (B already consumed) @@ -335,6 +386,14 @@ class RustSymbolParser { } EndBackref(); continue; + + const_backref: + if (!BeginBackref()) return false; + if (silence_depth_ == 0) { + ABSL_DEMANGLER_RECURSE(constant, kConstantBackrefEnding); + } + EndBackref(); + continue; } } @@ -350,15 +409,19 @@ class RustSymbolParser { kIdentifierInLowercaseNamespace, kTraitDefinitionInfix, kTraitDefinitionEnding, + kArraySize, + kFinishArray, kSliceEnding, kAfterFirstTupleElement, kAfterSecondTupleElement, kAfterThirdTupleElement, kAfterSubsequentTupleElement, + kConstData, kBeginGenericArgList, kContinueGenericArgList, kPathBackrefEnding, kTypeBackrefEnding, + kConstantBackrefEnding, }; // Element counts for the stack arrays. Larger stack sizes accommodate more diff --git a/absl/debugging/internal/demangle_rust_test.cc b/absl/debugging/internal/demangle_rust_test.cc index 1525b522..5e53eae3 100644 --- a/absl/debugging/internal/demangle_rust_test.cc +++ b/absl/debugging/internal/demangle_rust_test.cc @@ -340,6 +340,11 @@ TEST(DemangleRust, TypeBackrefsDoNotRecurseDuringSilence) { "<(i32, u32, i128, ...) as c::t>::f"); } +TEST(DemangleRust, ConstBackrefsDoNotRecurseDuringSilence) { + // B_ points at the whole I...E mangling, which does not parse as a const. + EXPECT_DEMANGLING("_RINvC1c1fAlB_E", "c::f::<>"); +} + TEST(DemangleRust, ReturnFromBackrefToInputPosition256) { // Show that we can resume at input positions that don't fit into a byte. EXPECT_DEMANGLING("_RNvYNtC1c238very_long_type_" @@ -399,6 +404,55 @@ TEST(DemangleRust, MonomorphicEntityNestedInsideGeneric) { "c::f::<>::g"); } +TEST(DemangleRust, ArrayTypeWithSimpleElementType) { + EXPECT_DEMANGLING("_RNvYAlj1f_NtC1c1t1f", "<[i32; 0x1f] as c::t>::f"); +} + +TEST(DemangleRust, ArrayTypeWithComplexElementType) { + EXPECT_DEMANGLING("_RNvYAINtC1c1slEj1f_NtB6_1t1f", + "<[c::s::<>; 0x1f] as c::t>::f"); +} + +TEST(DemangleRust, NestedArrayType) { + EXPECT_DEMANGLING("_RNvYAAlj1f_j2e_NtC1c1t1f", + "<[[i32; 0x1f]; 0x2e] as c::t>::f"); +} + +TEST(DemangleRust, BackrefArraySize) { + EXPECT_DEMANGLING("_RNvYAAlj1f_B5_NtC1c1t1f", + "<[[i32; 0x1f]; 0x1f] as c::t>::f"); +} + +TEST(DemangleRust, ZeroArraySize) { + EXPECT_DEMANGLING("_RNvYAlj0_NtC1c1t1f", "<[i32; 0x0] as c::t>::f"); +} + +TEST(DemangleRust, SurprisingMinusesInArraySize) { + // Compilers shouldn't do this stuff, but existing demanglers accept it. + EXPECT_DEMANGLING("_RNvYAljn0_NtC1c1t1f", "<[i32; -0x0] as c::t>::f"); + EXPECT_DEMANGLING("_RNvYAljn42_NtC1c1t1f", "<[i32; -0x42] as c::t>::f"); +} + +TEST(DemangleRust, NumberAsGenericArg) { + EXPECT_DEMANGLING("_RINvC1c1fKl8_E", // c::f::<0x8> + "c::f::<>"); +} + +TEST(DemangleRust, NumberAsFirstOfTwoGenericArgs) { + EXPECT_DEMANGLING("_RINvC1c1fKl8_mE", // c::f::<0x8, u32> + "c::f::<>"); +} + +TEST(DemangleRust, NumberAsSecondOfTwoGenericArgs) { + EXPECT_DEMANGLING("_RINvC1c1fmKl8_E", // c::f::<u32, 0x8> + "c::f::<>"); +} + +TEST(DemangleRust, NumberPlaceholder) { + EXPECT_DEMANGLING("_RNvINvC1c1fKpE1g", // c::f::<_>::g + "c::f::<>::g"); +} + } // namespace } // namespace debugging_internal ABSL_NAMESPACE_END |