Skip to content

Demangle failure with dragonbox symbol #269

Open
@scoopr

Description

@scoopr

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions