Summary: | c++filt crashes when demangling a symbol | ||
---|---|---|---|
Product: | gcc | Reporter: | blastrock |
Component: | demangler | Assignee: | Not yet assigned to anyone <unassigned> |
Status: | UNCONFIRMED --- | ||
Severity: | normal | CC: | mark |
Priority: | P3 | ||
Version: | 5.3.1 | ||
Target Milestone: | --- | ||
Host: | Target: | ||
Build: | Known to work: | ||
Known to fail: | Last reconfirmed: | ||
Bug Depends on: | 78252 | ||
Bug Blocks: | |||
Attachments: |
preprocessed file by clang 3.8
preprocessed file by gcc 5.3.1 Very small test case |
Description
blastrock
2016-04-02 15:44:19 UTC
Created attachment 38165 [details]
preprocessed file by clang 3.8
Created attachment 38166 [details]
preprocessed file by gcc 5.3.1
Created attachment 38418 [details]
Very small test case
I investigated this bug a little more and managed to produce a very small test case.
Compile this file with g++ 5.3.1 and clang 3.8 and you will get these two symbols:
_Z4moveIRZ5awaitIRiEDaOT_EUlRKS3_E_ES4_S4_ from clang
_Z4moveIRZ5awaitIRiEDaOT_EUlRKS2_E_ES3_S3_ from gcc
When trying c++filt on the one got from gcc, it will just fail demangling it and print it raw. But when we do it with the one produced by clang, we get a crash. The only difference I see there is the substitutions which are shifted by one on the clang version (I have no idea which compiler is right though).
I enabled the debug stuff from the demangle binary in libiberty and got this (I added the addresses of the nodes for debugging):
0x7fffffffd620: typed name
0x7fffffffd5d8: template
0x7fffffffd410: name 'move'
0x7fffffffd5c0: template argument list
0x7fffffffd5a8: reference
0x7fffffffd590: local name
0x7fffffffd518: typed name
0x7fffffffd488: template
0x7fffffffd428: name 'await'
0x7fffffffd470: template argument list
0x7fffffffd458: reference
0x7fffffffd440: builtin type int
0x7fffffffd500: function type
0x7fffffffd4a0: name 'auto'
0x7fffffffd4e8: argument list
0x7fffffffd4d0: rvalue reference
0x7fffffffd4b8: template parameter 0
0x7fffffffd578: lambda 0
0x7fffffffd560: argument list
0x7fffffffd548: reference
0x7fffffffd530: const
0x7fffffffd4d0: rvalue reference
0x7fffffffd4b8: template parameter 0
0x7fffffffd608: function type
0x7fffffffd530: const
0x7fffffffd4d0: rvalue reference
0x7fffffffd4b8: template parameter 0
0x7fffffffd5f0: argument list
0x7fffffffd530: const
0x7fffffffd4d0: rvalue reference
0x7fffffffd4b8: template parameter 0
What I understand is that when libiberty goes down the first branch, the "template parameter 0" references this same branch and so we get infinite recursion. I guess we can at least prevent the crash if we keep in the state a variable saying which template parameter we are referencing so that we don't go down the same path infinitely.
My (de)mangling skills are still very low and I don't think I can solve this one alone. Any help is appreciated.
This related to Bug 78252 - C++ demangler crashes with infinite recursion with lambda (auto) With the patch proposed for that bug there is no crash anymore and the symbols demangle. _ZSt4moveIRZN11tconcurrent6futureIvE4thenIZ5awaitIS2_EDaOT_EUlRKS6_E_EENS1_INSt5decayIDTclfp_defpTEEE4typeEEES7_EUlvE_EONSt16remove_referenceIS6_E4typeES7_ demangles to: std::remove_reference<tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}>(auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}&& const)::{lambda()#1}&>::type&& std::move<tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto await<tconcurrent::future<void> >(tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}>(auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}&& const)::{lambda()#1}&)::{lambda(auto&& const&)#1}>(tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}>(auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}&& const)::{lambda()#1}& const)::{lambda()#1}&>(tconcurrent::future<std::decay<decltype ({parm#1}(*this))>::type> tconcurrent::future<void>::then<auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}>(auto await<tconcurrent::future<void> >(tconcurrent::future<void>&&)::{lambda(auto&& const&)#1}&& const)::{lambda()#1}& const) _Z4moveIRZ5awaitIRiEDaOT_EUlRKS3_E_ES4_S4_ demangles to: auto await<int&>(int&)::{lambda(auto&& const&)#1}& const move<auto await<int&>(auto await<int&>(int&)::{lambda(auto&& const&)#1}&)::{lambda(auto&& const&)#1}&>(auto await<int&>(int&)::{lambda(auto&& const&)#1}& const) _Z4moveIRZ5awaitIRiEDaOT_EUlRKS2_E_ES3_S3_ demangles to: auto await<int&>(int&)::{lambda(auto const&)#1}& move<auto await<int&>(auto await<int&>(int&)::{lambda(auto const&)#1}&)::{lambda(auto const&)#1}&>(auto await<int&>(int&)::{lambda(auto const&)#1}&) Using binutils from a month ago or so, this does not crash but also does not demangle... (In reply to Christian Biesinger from comment #5) > Using binutils from a month ago or so, this does not crash but also does not > demangle... Could you be slightly more specific? Which symbol produced by which compiler doesn't (correctly) demangle? And, if known, is it a valid mangled symbol? |