cpp_demangle
cpp_demangle copied to clipboard
Demangle failure with dragonbox symbol
Hello!
I noticed a case where the demangling fails, but where (llvm/apple) c++filt seems to work, with this beauty:
__ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSC_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEESA_SC_ENKUlDpT_E_clIJEEESA_SM_
A self contained test could be
fn main() -> Result<(),std::fmt::Error>{
let mangled = "__ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSC_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEESA_SC_ENKUlDpT_E_clIJEEESA_SM_";
let sym = cpp_demangle::Symbol::new(mangled).unwrap();
let demangled = sym.demangle(&Default::default())?;
println!("Demangled: {}", demangled);
Ok(())
}
And that just fails with Error: Error.
c++filt output for me is:
jkj::dragonbox::signed_significand_bits jkj::dragonbox::signed_significand_bits auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float> >, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::'lambda'(jkj::dragonbox::default_float_traits<float>)::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(jkj::dragonbox::default_float_traits<float>) const::'lambda'(auto...)::operator()<>('lambda'(auto...)) const
And finally attempt to minimise the source of the symbol for proof that I didn't just conjure it up myself. Steps:
git clone https://github.com/jk-jeon/dragonbox.git
vim dragonbox.cpp
clang -std=c++17 -c dragonbox.cpp
nm dragonbox.o | grep __ZZZ
where the dragonbox.cpp contents being:
#include "dragonbox/include/dragonbox/dragonbox.h"
void dragon_test() {
jkj::dragonbox::float_bits<float> br(0.0f);
auto const exponent_bits = br.extract_exponent_bits();
auto const s = br.remove_exponent_bits(exponent_bits);
auto result = jkj::dragonbox::to_decimal(
s, exponent_bits, jkj::dragonbox::policy::sign::ignore,
jkj::dragonbox::policy::trailing_zero::remove);
}
Fiddling with the DemangleOptions didn't seem to affect the outcome.
I wonder if it is possible to make the demangler "fool proof" on valid input, or should there perhaps be some "lossy mode", where it demangles as much as it can, but bails out gracefully giving partial result, for when I don't have too strict needs.
llvm-cxxfilt (built from rev 82fcd7397a5939a9f0148513cc7b6883a00a16b0) doesn't demangle this for me.
Hm, both the tools that come from xcode (xcode 13.4.1, c++filt claims to be 13.1.6), and homebrew installed (llvm/clang 13.0.1) seem to demangle it just fine. And these are the latest "stable" versions that I can easily install right now. I wonder if the mangling has then changed in later versions
I followed the instructions you provided using clang's tip and the symbol produced now appears to be
_ZZZN3jkj9dragonbox10to_decimalIfNS0_20default_float_traitsIfEEJNS0_6detail11policy_impl4sign6ignoreENS5_13trailing_zero6removeEEEEDaNS0_23signed_significand_bitsIT_T0_EEjDpT1_ENKUlSB_E_clINS5_26decimal_to_binary_rounding15nearest_to_evenEEEDaSB_ENKUlDpT_E_clIJEEEDaSL_
llvm-cxxfilt produces
auto auto auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float>>, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::'lambda'(float)::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(float) const::'lambda'(auto...)::operator()<>(auto...) const
cpp_demangle produces
auto auto auto jkj::dragonbox::to_decimal<float, jkj::dragonbox::default_float_traits<float>, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove>(jkj::dragonbox::signed_significand_bits<float, jkj::dragonbox::default_float_traits<float> >, unsigned int, jkj::dragonbox::detail::policy_impl::sign::ignore, jkj::dragonbox::detail::policy_impl::trailing_zero::remove)::{lambda(auto:1)#1}::operator()<jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even>(jkj::dragonbox::detail::policy_impl::decimal_to_binary_rounding::nearest_to_even) const::{lambda(auto:1)#1}::operator()<>() const
(libiberty does not parse this succesfully)
Fixing the incorrect lambda parameters here is pretty tricky, I think it's going to require some serious refactoring.