From a28ee5b51c9ea41707d9a5d2d358ad77850264c4 Mon Sep 17 00:00:00 2001 From: Chris Mihelich Date: Mon, 6 May 2024 05:56:26 -0700 Subject: Recognize some simple Rust mangled names in Demangle. PiperOrigin-RevId: 631018414 Change-Id: Ice8efa0af4cb1f72b5d62fbbea4cb12cbead8634 --- absl/debugging/internal/demangle_rust.h | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 absl/debugging/internal/demangle_rust.h (limited to 'absl/debugging/internal/demangle_rust.h') diff --git a/absl/debugging/internal/demangle_rust.h b/absl/debugging/internal/demangle_rust.h new file mode 100644 index 00000000..8e9060b4 --- /dev/null +++ b/absl/debugging/internal/demangle_rust.h @@ -0,0 +1,47 @@ +// Copyright 2024 The Abseil Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_ +#define ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_ + +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace debugging_internal { + +// Demangle the Rust encoding `mangled`. On success, return true and write the +// demangled symbol name to `out`. Otherwise, return false, leaving unspecified +// contents in `out`. For example, calling DemangleRustSymbolEncoding with +// `mangled = "_RNvC8my_crate7my_func"` will yield `my_crate::my_func` in `out`, +// provided `out_size` is large enough for that value and its trailing NUL. +// +// DemangleRustSymbolEncoding is async-signal-safe and runs in bounded C++ +// call-stack space. It is suitable for symbolizing stack traces in a signal +// handler. +// +// The demangling logic is under development. In this version of Abseil, +// DemangleRustSymbolEncoding parses a few simple kinds of symbol names, but +// nothing having backreferences in the input or angle brackets in the +// demangling, and it emits raw Punycode instead of the UTF-8 represented by it. +bool DemangleRustSymbolEncoding(const char* mangled, char* out, + std::size_t out_size); + +} // namespace debugging_internal +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_DEBUGGING_INTERNAL_DEMANGLE_RUST_H_ -- cgit v1.2.3 From 692d9e568301b2c01a35b8da3c9915cef4055a4f Mon Sep 17 00:00:00 2001 From: Chris Mihelich Date: Mon, 13 May 2024 09:05:25 -0700 Subject: Demangle Rust's Y production for passably simple s. PiperOrigin-RevId: 633229582 Change-Id: Ibda908d261b52b1af766304992edd77a5bdd56b5 --- absl/debugging/internal/demangle_rust.cc | 145 +++++++++++++++++++++++++- absl/debugging/internal/demangle_rust.h | 6 +- absl/debugging/internal/demangle_rust_test.cc | 84 +++++++++++++++ 3 files changed, 229 insertions(+), 6 deletions(-) (limited to 'absl/debugging/internal/demangle_rust.h') diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc index 7086cab2..f2a411d3 100644 --- a/absl/debugging/internal/demangle_rust.cc +++ b/absl/debugging/internal/demangle_rust.cc @@ -37,6 +37,33 @@ 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 == '_'; } +const char* BasicTypeName(char c) { + switch (c) { + case 'a': return "i8"; + case 'b': return "bool"; + case 'c': return "char"; + case 'd': return "f64"; + case 'e': return "str"; + case 'f': return "f32"; + case 'h': return "u8"; + case 'i': return "isize"; + case 'j': return "usize"; + case 'l': return "i32"; + case 'm': return "u32"; + case 'n': return "i128"; + case 'o': return "u128"; + case 'p': return "_"; + case 's': return "i16"; + case 't': return "u16"; + case 'u': return "()"; + case 'v': return "..."; + case 'x': return "i64"; + case 'y': return "u64"; + case 'z': return "!"; + } + return nullptr; +} + // Parser for Rust symbol mangling v0, whose grammar is defined here: // // https://doc.rust-lang.org/rustc/symbol-mangling/v0.html#symbol-grammar-summary @@ -115,12 +142,16 @@ class RustSymbolParser { // path -> crate-root | inherent-impl | trait-impl | trait-definition | // nested-path | generic-args | backref + // + // Note that ABSL_DEMANGLER_RECURSE does not work inside a nested switch + // (which would hide the generated case label). Thus we jump out of the + // inner switch with gotos before performing any fake recursion. path: switch (Take()) { case 'C': goto crate_root; case 'M': return false; // inherent-impl not yet implemented case 'X': return false; // trait-impl not yet implemented - case 'Y': return false; // trait-definition not yet implemented + case 'Y': goto trait_definition; case 'N': goto nested_path; case 'I': return false; // generic-args not yet implemented case 'B': return false; // backref not yet implemented @@ -132,7 +163,16 @@ class RustSymbolParser { if (!ParseIdentifier()) return false; continue; - // nested-path -> N namespace path identifier (N consumed above) + // trait-definition -> Y type path (Y already consumed) + trait_definition: + if (!Emit("<")) return false; + ABSL_DEMANGLER_RECURSE(type, kTraitDefinitionInfix); + if (!Emit(" as ")) return false; + ABSL_DEMANGLER_RECURSE(path, kTraitDefinitionEnding); + if (!Emit(">")) return false; + continue; + + // nested-path -> N namespace path identifier (N already consumed) // namespace -> lower | upper nested_path: // Uppercase namespaces must be saved on the stack so we can print @@ -156,6 +196,98 @@ class RustSymbolParser { // Neither upper or lower return false; + + // type -> basic-type | array-type | slice-type | tuple-type | + // ref-type | mut-ref-type | const-ptr-type | mut-ptr-type | + // fn-type | dyn-trait-type | path | backref + // + // We use ifs instead of switch (Take()) because the default case jumps + // to path, which will need to see the first character not yet Taken + // from the input. Because we do not use a nested switch here, + // ABSL_DEMANGLER_RECURSE works fine in the 'S' case. + type: + if (IsLower(Peek())) { + const char* type_name = BasicTypeName(Take()); + if (type_name == nullptr || !Emit(type_name)) return false; + continue; + } + if (Eat('A')) return false; // array-type not yet implemented + if (Eat('S')) { + if (!Emit("[")) return false; + ABSL_DEMANGLER_RECURSE(type, kSliceEnding); + if (!Emit("]")) return false; + continue; + } + if (Eat('T')) goto tuple_type; + if (Eat('R')) { + if (!Emit("&")) return false; + if (Eat('L')) return false; // lifetime not yet implemented + goto type; + } + if (Eat('Q')) { + if (!Emit("&mut ")) return false; + if (Eat('L')) return false; // lifetime not yet implemented + goto type; + } + if (Eat('P')) { + if (!Emit("*const ")) return false; + goto type; + } + if (Eat('O')) { + if (!Emit("*mut ")) return false; + goto type; + } + if (Eat('F')) return false; // fn-type not yet implemented + if (Eat('D')) return false; // dyn-trait-type not yet implemented + if (Eat('B')) return false; // backref not yet implemented + goto path; + + // tuple-type -> T type* E (T already consumed) + tuple_type: + if (!Emit("(")) return false; + + // The toolchain should call the unit type u instead of TE, but the + // grammar and other demanglers also recognize TE, so we do too. + if (Eat('E')) { + if (!Emit(")")) return false; + continue; + } + + // A tuple with one element is rendered (type,) instead of (type). + ABSL_DEMANGLER_RECURSE(type, kAfterFirstTupleElement); + if (Eat('E')) { + if (!Emit(",)")) return false; + continue; + } + + // A tuple with two elements is of course (x, y). + if (!Emit(", ")) return false; + ABSL_DEMANGLER_RECURSE(type, kAfterSecondTupleElement); + if (Eat('E')) { + if (!Emit(")")) return false; + continue; + } + + // And (x, y, z) for three elements. + if (!Emit(", ")) return false; + ABSL_DEMANGLER_RECURSE(type, kAfterThirdTupleElement); + if (Eat('E')) { + if (!Emit(")")) return false; + continue; + } + + // For longer tuples we write (x, y, z, ...), printing none of the + // content of the fourth and later types. Thus we avoid exhausting + // output buffers and human readers' patience when some library has a + // long tuple as an implementation detail, without having to + // completely obfuscate all tuples. + if (!Emit(", ...)")) return false; + ++silence_depth_; + while (!Eat('E')) { + ABSL_DEMANGLER_RECURSE(type, kAfterSubsequentTupleElement); + } + --silence_depth_; + continue; } } @@ -169,6 +301,13 @@ class RustSymbolParser { kVendorSpecificSuffix, kIdentifierInUppercaseNamespace, kIdentifierInLowercaseNamespace, + kTraitDefinitionInfix, + kTraitDefinitionEnding, + kSliceEnding, + kAfterFirstTupleElement, + kAfterSecondTupleElement, + kAfterThirdTupleElement, + kAfterSubsequentTupleElement, }; // Element count for the stack_ array. A larger kStackSize accommodates more @@ -320,6 +459,8 @@ class RustSymbolParser { // Emit the beginnings of braced forms like {shim:vtable#0}. if (uppercase_namespace == '\0') { + // Decoding of Punycode is not yet implemented. For now we emit + // "{Punycode ...}" with the raw encoding inside. if (is_punycoded && !Emit("{Punycode ")) return false; } else { switch (uppercase_namespace) { diff --git a/absl/debugging/internal/demangle_rust.h b/absl/debugging/internal/demangle_rust.h index 8e9060b4..1c19815f 100644 --- a/absl/debugging/internal/demangle_rust.h +++ b/absl/debugging/internal/demangle_rust.h @@ -33,10 +33,8 @@ namespace debugging_internal { // call-stack space. It is suitable for symbolizing stack traces in a signal // handler. // -// The demangling logic is under development. In this version of Abseil, -// DemangleRustSymbolEncoding parses a few simple kinds of symbol names, but -// nothing having backreferences in the input or angle brackets in the -// demangling, and it emits raw Punycode instead of the UTF-8 represented by it. +// The demangling logic is under development; search for "not yet implemented" +// in the .cc file to see where the gaps are. bool DemangleRustSymbolEncoding(const char* mangled, char* out, std::size_t out_size); diff --git a/absl/debugging/internal/demangle_rust_test.cc b/absl/debugging/internal/demangle_rust_test.cc index 2841576e..d42700fb 100644 --- a/absl/debugging/internal/demangle_rust_test.cc +++ b/absl/debugging/internal/demangle_rust_test.cc @@ -209,6 +209,90 @@ TEST(DemangleRust, NestedUppercaseNamespaces) { "crate_name::{Y:y#2}::{X:x#3}::{closure#4}"); } +TEST(DemangleRust, TraitDefinition) { + EXPECT_DEMANGLING( + "_RNvYNvC7crate_a9my_structNvC7crate_b8my_trait1f", + "::f"); +} + +TEST(DemangleRust, BasicTypeNames) { + EXPECT_DEMANGLING("_RNvYaNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYbNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYcNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYdNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYeNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYfNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYhNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYiNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYjNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYlNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYmNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYnNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYoNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYpNvC1c1t1f", "<_ as c::t>::f"); + EXPECT_DEMANGLING("_RNvYsNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYtNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYuNvC1c1t1f", "<() as c::t>::f"); + EXPECT_DEMANGLING("_RNvYvNvC1c1t1f", "<... as c::t>::f"); + EXPECT_DEMANGLING("_RNvYxNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYyNvC1c1t1f", "::f"); + EXPECT_DEMANGLING("_RNvYzNvC1c1t1f", "::f"); + + EXPECT_DEMANGLING_FAILS("_RNvYkNvC1c1t1f"); +} + +TEST(DemangleRust, SliceTypes) { + EXPECT_DEMANGLING("_RNvYSlNvC1c1t1f", "<[i32] as c::t>::f"); + EXPECT_DEMANGLING("_RNvYSNvC1d1sNvC1c1t1f", "<[d::s] as c::t>::f"); +} + +TEST(DemangleRust, ImmutableReferenceTypes) { + EXPECT_DEMANGLING("_RNvYRlNvC1c1t1f", "<&i32 as c::t>::f"); + EXPECT_DEMANGLING("_RNvYRNvC1d1sNvC1c1t1f", "<&d::s as c::t>::f"); +} + +TEST(DemangleRust, MutableReferenceTypes) { + EXPECT_DEMANGLING("_RNvYQlNvC1c1t1f", "<&mut i32 as c::t>::f"); + EXPECT_DEMANGLING("_RNvYQNvC1d1sNvC1c1t1f", "<&mut d::s as c::t>::f"); +} + +TEST(DemangleRust, ConstantRawPointerTypes) { + EXPECT_DEMANGLING("_RNvYPlNvC1c1t1f", "<*const i32 as c::t>::f"); + EXPECT_DEMANGLING("_RNvYPNvC1d1sNvC1c1t1f", "<*const d::s as c::t>::f"); +} + +TEST(DemangleRust, MutableRawPointerTypes) { + EXPECT_DEMANGLING("_RNvYOlNvC1c1t1f", "<*mut i32 as c::t>::f"); + EXPECT_DEMANGLING("_RNvYONvC1d1sNvC1c1t1f", "<*mut d::s as c::t>::f"); +} + +TEST(DemangleRust, TupleLength0) { + EXPECT_DEMANGLING("_RNvYTENvC1c1t1f", "<() as c::t>::f"); +} + +TEST(DemangleRust, TupleLength1) { + EXPECT_DEMANGLING("_RNvYTlENvC1c1t1f", "<(i32,) as c::t>::f"); + EXPECT_DEMANGLING("_RNvYTNvC1d1sENvC1c1t1f", "<(d::s,) as c::t>::f"); +} + +TEST(DemangleRust, TupleLength2) { + EXPECT_DEMANGLING("_RNvYTlmENvC1c1t1f", "<(i32, u32) as c::t>::f"); + EXPECT_DEMANGLING("_RNvYTNvC1d1xNvC1e1yENvC1c1t1f", + "<(d::x, e::y) as c::t>::f"); +} + +TEST(DemangleRust, TupleLength3) { + EXPECT_DEMANGLING("_RNvYTlmnENvC1c1t1f", "<(i32, u32, i128) as c::t>::f"); + EXPECT_DEMANGLING("_RNvYTNvC1d1xNvC1e1yNvC1f1zENvC1c1t1f", + "<(d::x, e::y, f::z) as c::t>::f"); +} + +TEST(DemangleRust, LongerTuplesAbbreviated) { + EXPECT_DEMANGLING("_RNvYTlmnoENvC1c1t1f", + "<(i32, u32, i128, ...) as c::t>::f"); + EXPECT_DEMANGLING("_RNvYTlmnNvC1d1xNvC1e1yENvC1c1t1f", + "<(i32, u32, i128, ...) as c::t>::f"); +} } // namespace } // namespace debugging_internal -- cgit v1.2.3 From f04e489056d9be93072bb633d9818b1e2add6316 Mon Sep 17 00:00:00 2001 From: Chris Mihelich Date: Fri, 14 Jun 2024 12:11:34 -0700 Subject: Drop std:: qualification from integer types like uint64_t. PiperOrigin-RevId: 643418422 Change-Id: Ib16cfef8ddedc8366df49ca75ab02eb60af08f26 --- absl/debugging/internal/demangle_rust.cc | 12 +++---- absl/debugging/internal/demangle_rust.h | 2 +- absl/debugging/internal/demangle_rust_test.cc | 10 +++--- absl/debugging/internal/demangle_test.cc | 2 +- .../debugging/internal/utf8_for_code_point_test.cc | 42 +++++++++++----------- 5 files changed, 34 insertions(+), 34 deletions(-) (limited to 'absl/debugging/internal/demangle_rust.h') diff --git a/absl/debugging/internal/demangle_rust.cc b/absl/debugging/internal/demangle_rust.cc index 06ee7a4b..6b686ab3 100644 --- a/absl/debugging/internal/demangle_rust.cc +++ b/absl/debugging/internal/demangle_rust.cc @@ -503,7 +503,7 @@ class RustSymbolParser { private: // Enumerates resumption points for ABSL_DEMANGLER_RECURSE calls. - enum ReturnAddress : std::uint8_t { + enum ReturnAddress : uint8_t { kInstantiatingCrate, kVendorSpecificSuffix, kIdentifierInUppercaseNamespace, @@ -585,9 +585,9 @@ class RustSymbolParser { // false if not everything fit into the output buffer. ABSL_MUST_USE_RESULT bool Emit(const char* token) { if (silence_depth_ > 0) return true; - const std::size_t token_length = std::strlen(token); - const std::size_t bytes_to_copy = token_length + 1; // token and final NUL - if (static_cast(out_end_ - out_) < bytes_to_copy) return false; + const size_t token_length = std::strlen(token); + const size_t bytes_to_copy = token_length + 1; // token and final NUL + if (static_cast(out_end_ - out_) < bytes_to_copy) return false; std::memcpy(out_, token, bytes_to_copy); out_ += token_length; return true; @@ -604,7 +604,7 @@ class RustSymbolParser { // because 999 > 256. The bound will remain correct even if future // maintenance changes the type of the disambiguator variable. char digits[3 * sizeof(disambiguator)] = {}; - std::size_t leading_digit_index = sizeof(digits) - 1; + size_t leading_digit_index = sizeof(digits) - 1; for (; disambiguator > 0; disambiguator /= 10) { digits[--leading_digit_index] = static_cast('0' + disambiguator % 10); @@ -909,7 +909,7 @@ class RustSymbolParser { } // namespace bool DemangleRustSymbolEncoding(const char* mangled, char* out, - std::size_t out_size) { + size_t out_size) { return RustSymbolParser(mangled, out, out + out_size).Parse(); } diff --git a/absl/debugging/internal/demangle_rust.h b/absl/debugging/internal/demangle_rust.h index 1c19815f..29e08ecd 100644 --- a/absl/debugging/internal/demangle_rust.h +++ b/absl/debugging/internal/demangle_rust.h @@ -36,7 +36,7 @@ namespace debugging_internal { // The demangling logic is under development; search for "not yet implemented" // in the .cc file to see where the gaps are. bool DemangleRustSymbolEncoding(const char* mangled, char* out, - std::size_t out_size); + size_t out_size); } // namespace debugging_internal ABSL_NAMESPACE_END diff --git a/absl/debugging/internal/demangle_rust_test.cc b/absl/debugging/internal/demangle_rust_test.cc index 00bba780..e6b68ae3 100644 --- a/absl/debugging/internal/demangle_rust_test.cc +++ b/absl/debugging/internal/demangle_rust_test.cc @@ -29,7 +29,7 @@ namespace { // chars>, buffer_size) returns true and seems not to have overrun its output // buffer, returns the string written by DemangleRustSymbolEncoding; otherwise // returns an error message. -std::string ResultOfDemangling(const char* mangled, std::size_t buffer_size) { +std::string ResultOfDemangling(const char* mangled, size_t buffer_size) { // Fill the buffer with something other than NUL so we test whether Demangle // appends trailing NUL as expected. std::string buffer(buffer_size + 1, '~'); @@ -58,9 +58,9 @@ std::string ResultOfDemangling(const char* mangled, std::size_t buffer_size) { #define EXPECT_DEMANGLING(mangled, plaintext) \ do { \ [] { \ - constexpr std::size_t plenty_of_space = sizeof(plaintext) + 128; \ - constexpr std::size_t just_enough_space = sizeof(plaintext); \ - constexpr std::size_t one_byte_too_few = sizeof(plaintext) - 1; \ + constexpr size_t plenty_of_space = sizeof(plaintext) + 128; \ + constexpr size_t just_enough_space = sizeof(plaintext); \ + constexpr size_t one_byte_too_few = sizeof(plaintext) - 1; \ const char* expected_plaintext = plaintext; \ const char* expected_error = "Failed parse"; \ ASSERT_EQ(ResultOfDemangling(mangled, plenty_of_space), \ @@ -76,7 +76,7 @@ std::string ResultOfDemangling(const char* mangled, std::size_t buffer_size) { // truncation of a real Rust symbol name). #define EXPECT_DEMANGLING_FAILS(mangled) \ do { \ - constexpr std::size_t plenty_of_space = 1024; \ + constexpr size_t plenty_of_space = 1024; \ const char* expected_error = "Failed parse"; \ EXPECT_EQ(ResultOfDemangling(mangled, plenty_of_space), expected_error); \ } while (0) diff --git a/absl/debugging/internal/demangle_test.cc b/absl/debugging/internal/demangle_test.cc index 55686814..5579221a 100644 --- a/absl/debugging/internal/demangle_test.cc +++ b/absl/debugging/internal/demangle_test.cc @@ -1209,7 +1209,7 @@ TEST(Demangle, BinaryFoldExpressions) { TEST(Demangle, SizeofPacks) { char tmp[80]; - // template struct S {}; + // template struct S {}; // // template auto f(T... p) -> S { return {}; } // template auto f(int, long) -> S<2>; diff --git a/absl/debugging/internal/utf8_for_code_point_test.cc b/absl/debugging/internal/utf8_for_code_point_test.cc index d6817c77..dd0591ae 100644 --- a/absl/debugging/internal/utf8_for_code_point_test.cc +++ b/absl/debugging/internal/utf8_for_code_point_test.cc @@ -25,32 +25,32 @@ namespace debugging_internal { namespace { TEST(Utf8ForCodePointTest, RecognizesTheSmallestCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0}); + Utf8ForCodePoint utf8(uint64_t{0}); ASSERT_EQ(utf8.length, 1); EXPECT_EQ(utf8.bytes[0], '\0'); } TEST(Utf8ForCodePointTest, RecognizesAsciiSmallA) { - Utf8ForCodePoint utf8(std::uint64_t{'a'}); + Utf8ForCodePoint utf8(uint64_t{'a'}); ASSERT_EQ(utf8.length, 1); EXPECT_EQ(utf8.bytes[0], 'a'); } TEST(Utf8ForCodePointTest, RecognizesTheLargestOneByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x7f}); + Utf8ForCodePoint utf8(uint64_t{0x7f}); ASSERT_EQ(utf8.length, 1); EXPECT_EQ(utf8.bytes[0], '\x7f'); } TEST(Utf8ForCodePointTest, RecognizesTheSmallestTwoByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x80}); + Utf8ForCodePoint utf8(uint64_t{0x80}); ASSERT_EQ(utf8.length, 2); EXPECT_EQ(utf8.bytes[0], static_cast(0xc2)); EXPECT_EQ(utf8.bytes[1], static_cast(0x80)); } TEST(Utf8ForCodePointTest, RecognizesSmallNWithTilde) { - Utf8ForCodePoint utf8(std::uint64_t{0xf1}); + Utf8ForCodePoint utf8(uint64_t{0xf1}); ASSERT_EQ(utf8.length, 2); const char* want = "ñ"; EXPECT_EQ(utf8.bytes[0], want[0]); @@ -58,7 +58,7 @@ TEST(Utf8ForCodePointTest, RecognizesSmallNWithTilde) { } TEST(Utf8ForCodePointTest, RecognizesCapitalPi) { - Utf8ForCodePoint utf8(std::uint64_t{0x3a0}); + Utf8ForCodePoint utf8(uint64_t{0x3a0}); ASSERT_EQ(utf8.length, 2); const char* want = "Π"; EXPECT_EQ(utf8.bytes[0], want[0]); @@ -66,14 +66,14 @@ TEST(Utf8ForCodePointTest, RecognizesCapitalPi) { } TEST(Utf8ForCodePointTest, RecognizesTheLargestTwoByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x7ff}); + Utf8ForCodePoint utf8(uint64_t{0x7ff}); ASSERT_EQ(utf8.length, 2); EXPECT_EQ(utf8.bytes[0], static_cast(0xdf)); EXPECT_EQ(utf8.bytes[1], static_cast(0xbf)); } TEST(Utf8ForCodePointTest, RecognizesTheSmallestThreeByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x800}); + Utf8ForCodePoint utf8(uint64_t{0x800}); ASSERT_EQ(utf8.length, 3); EXPECT_EQ(utf8.bytes[0], static_cast(0xe0)); EXPECT_EQ(utf8.bytes[1], static_cast(0xa0)); @@ -81,7 +81,7 @@ TEST(Utf8ForCodePointTest, RecognizesTheSmallestThreeByteCodePoint) { } TEST(Utf8ForCodePointTest, RecognizesTheChineseCharacterZhong1AsInZhong1Wen2) { - Utf8ForCodePoint utf8(std::uint64_t{0x4e2d}); + Utf8ForCodePoint utf8(uint64_t{0x4e2d}); ASSERT_EQ(utf8.length, 3); const char* want = "中"; EXPECT_EQ(utf8.bytes[0], want[0]); @@ -90,7 +90,7 @@ TEST(Utf8ForCodePointTest, RecognizesTheChineseCharacterZhong1AsInZhong1Wen2) { } TEST(Utf8ForCodePointTest, RecognizesOneBeforeTheSmallestSurrogate) { - Utf8ForCodePoint utf8(std::uint64_t{0xd7ff}); + Utf8ForCodePoint utf8(uint64_t{0xd7ff}); ASSERT_EQ(utf8.length, 3); EXPECT_EQ(utf8.bytes[0], static_cast(0xed)); EXPECT_EQ(utf8.bytes[1], static_cast(0x9f)); @@ -98,17 +98,17 @@ TEST(Utf8ForCodePointTest, RecognizesOneBeforeTheSmallestSurrogate) { } TEST(Utf8ForCodePointTest, RejectsTheSmallestSurrogate) { - Utf8ForCodePoint utf8(std::uint64_t{0xd800}); + Utf8ForCodePoint utf8(uint64_t{0xd800}); EXPECT_EQ(utf8.length, 0); } TEST(Utf8ForCodePointTest, RejectsTheLargestSurrogate) { - Utf8ForCodePoint utf8(std::uint64_t{0xdfff}); + Utf8ForCodePoint utf8(uint64_t{0xdfff}); EXPECT_EQ(utf8.length, 0); } TEST(Utf8ForCodePointTest, RecognizesOnePastTheLargestSurrogate) { - Utf8ForCodePoint utf8(std::uint64_t{0xe000}); + Utf8ForCodePoint utf8(uint64_t{0xe000}); ASSERT_EQ(utf8.length, 3); EXPECT_EQ(utf8.bytes[0], static_cast(0xee)); EXPECT_EQ(utf8.bytes[1], static_cast(0x80)); @@ -116,7 +116,7 @@ TEST(Utf8ForCodePointTest, RecognizesOnePastTheLargestSurrogate) { } TEST(Utf8ForCodePointTest, RecognizesTheLargestThreeByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0xffff}); + Utf8ForCodePoint utf8(uint64_t{0xffff}); ASSERT_EQ(utf8.length, 3); EXPECT_EQ(utf8.bytes[0], static_cast(0xef)); EXPECT_EQ(utf8.bytes[1], static_cast(0xbf)); @@ -124,7 +124,7 @@ TEST(Utf8ForCodePointTest, RecognizesTheLargestThreeByteCodePoint) { } TEST(Utf8ForCodePointTest, RecognizesTheSmallestFourByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x10000}); + Utf8ForCodePoint utf8(uint64_t{0x10000}); ASSERT_EQ(utf8.length, 4); EXPECT_EQ(utf8.bytes[0], static_cast(0xf0)); EXPECT_EQ(utf8.bytes[1], static_cast(0x90)); @@ -133,7 +133,7 @@ TEST(Utf8ForCodePointTest, RecognizesTheSmallestFourByteCodePoint) { } TEST(Utf8ForCodePointTest, RecognizesTheJackOfHearts) { - Utf8ForCodePoint utf8(std::uint64_t{0x1f0bb}); + Utf8ForCodePoint utf8(uint64_t{0x1f0bb}); ASSERT_EQ(utf8.length, 4); const char* want = "🂻"; EXPECT_EQ(utf8.bytes[0], want[0]); @@ -143,7 +143,7 @@ TEST(Utf8ForCodePointTest, RecognizesTheJackOfHearts) { } TEST(Utf8ForCodePointTest, RecognizesTheLargestFourByteCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x10ffff}); + Utf8ForCodePoint utf8(uint64_t{0x10ffff}); ASSERT_EQ(utf8.length, 4); EXPECT_EQ(utf8.bytes[0], static_cast(0xf4)); EXPECT_EQ(utf8.bytes[1], static_cast(0x8f)); @@ -152,21 +152,21 @@ TEST(Utf8ForCodePointTest, RecognizesTheLargestFourByteCodePoint) { } TEST(Utf8ForCodePointTest, RejectsTheSmallestOverlargeCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0x110000}); + Utf8ForCodePoint utf8(uint64_t{0x110000}); EXPECT_EQ(utf8.length, 0); } TEST(Utf8ForCodePointTest, RejectsAThroughlyOverlargeCodePoint) { - Utf8ForCodePoint utf8(std::uint64_t{0xffffffff00000000}); + Utf8ForCodePoint utf8(uint64_t{0xffffffff00000000}); EXPECT_EQ(utf8.length, 0); } TEST(Utf8ForCodePointTest, OkReturnsTrueForAValidCodePoint) { - EXPECT_TRUE(Utf8ForCodePoint(std::uint64_t{0}).ok()); + EXPECT_TRUE(Utf8ForCodePoint(uint64_t{0}).ok()); } TEST(Utf8ForCodePointTest, OkReturnsFalseForAnInvalidCodePoint) { - EXPECT_FALSE(Utf8ForCodePoint(std::uint64_t{0xffffffff00000000}).ok()); + EXPECT_FALSE(Utf8ForCodePoint(uint64_t{0xffffffff00000000}).ok()); } } // namespace -- cgit v1.2.3 From d4cf6b71af0960eeacf45f9b3c7d5d713d52e3b1 Mon Sep 17 00:00:00 2001 From: Chris Mihelich Date: Thu, 27 Jun 2024 12:58:13 -0700 Subject: Declare Rust demangling feature-complete. PiperOrigin-RevId: 647417773 Change-Id: I7d945ae27199262b3baf83b232d17c2f641a27ac --- absl/debugging/internal/demangle.h | 3 ++- absl/debugging/internal/demangle_rust.h | 3 --- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'absl/debugging/internal/demangle_rust.h') diff --git a/absl/debugging/internal/demangle.h b/absl/debugging/internal/demangle.h index e75d1473..cb0aba13 100644 --- a/absl/debugging/internal/demangle.h +++ b/absl/debugging/internal/demangle.h @@ -56,7 +56,8 @@ namespace debugging_internal { // // See the unit test for more examples. // -// Support for Rust mangled names is in development; see demangle_rust.h. +// Demangle also recognizes Rust mangled names by delegating the parsing of +// anything that starts with _R to DemangleRustSymbolEncoding (demangle_rust.h). // // Note: we might want to write demanglers for ABIs other than Itanium // C++ ABI in the future. diff --git a/absl/debugging/internal/demangle_rust.h b/absl/debugging/internal/demangle_rust.h index 29e08ecd..94a9aecb 100644 --- a/absl/debugging/internal/demangle_rust.h +++ b/absl/debugging/internal/demangle_rust.h @@ -32,9 +32,6 @@ namespace debugging_internal { // DemangleRustSymbolEncoding is async-signal-safe and runs in bounded C++ // call-stack space. It is suitable for symbolizing stack traces in a signal // handler. -// -// The demangling logic is under development; search for "not yet implemented" -// in the .cc file to see where the gaps are. bool DemangleRustSymbolEncoding(const char* mangled, char* out, size_t out_size); -- cgit v1.2.3