Currently, there are a few cases, when clang generates type names differently for template instantiations in DWARF and during symbols mangling. Thus debugger (lldb, in particular) is unable to resolve to resolve the real type using RTTI. Consider an example:
enum class TagType : bool { Tag1 }; struct I { virtual ~I() = default; }; template <TagType Tag> struct Impl : public I { private: int v = 123; }; int main(int argc, const char * argv[]) { Impl<TagType::Tag1> impl; I& i = impl; return 0; // [*] }
For such code clang generates type name "Impl<TagType::Tag1>" in DWARF and "Impl<(TagType)0>" when mangling symbols.
This leads to the following issue in debugger (let's say the debugger is stopped at point [*]):
- The "i" variable is of reference type and "I" is of polymorphic type;
- The debugger tries to resolve RTTI record for "I" and get the real type name from it;
- The real type of the "i" variable is "Impl<(TagType)0>" (because it was generated with clang mangling mechanism);
- The debugger tries to find the "Impl<(TagType)0>" type in DWARF and fails, because in DWARF it is named "Impl<TagType::Tag1>";
Thus the "v" member of "i" is not shown and "i" has the "I&" type, but not "Impl<TagType::Tag1>&".
There is one more case even without enums:
struct I { virtual ~I(){} }; template <int Tag> struct Impl : public I { int v = 123; }; template <> struct Impl<1+1+1> : public I // Note the expression used for this specialization { int v = 124; }; template <class T> struct TT { I* i = new T(); }; int main(int argc, const char * argv[]) { TT<Impl<3>> tt; return 0; // [*] }
For such code clang generates type name "Impl<1+1+1>" into DWARF and "Impl<3>" when mangling symbols, so similarly at point [*] the "tt.i" won't be shown properly because of the same reasons. BTW, "Impl<1+1+1>" is generated in CGDebugInfo::getClassName(), where RD->getNameForDiagnostic() is called for template specializations.
This patch fixes the described issues, but has the following drawback: after the fix, the template instantiations with enums are generated in format "TemplateType<EnumType(value)>", that is less native than previously "TemplateType<EnumType::Item>". This could be visible for user when working with the debugger (the type in format "TemplateType<EnumType::Item>" won't be resolved to a known type). Is it OK or are there other ideas how to fix the issues, described above?
this change looks like it has the potential to break existing code.