aboutsummaryrefslogtreecommitdiff
path: root/absl/debugging
diff options
context:
space:
mode:
authorChris Mihelich <cmihelic@google.com>2024-05-21 15:00:10 -0700
committerCopybara-Service <copybara-worker@google.com>2024-05-21 15:01:12 -0700
commit7a730c1b22702b931431c84fe8e42b9c4b0051a0 (patch)
tree796a0f228fd26312724c8035df09f8617cd2bcda /absl/debugging
parent22108fae90c4edd0e50cb8546b0a883ca4558e0c (diff)
downloadabseil-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.cc67
-rw-r--r--absl/debugging/internal/demangle_rust_test.cc54
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