Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't obtain full type of the non-template type parameter in clang frontend #57562

Closed
DoDoENT opened this issue Sep 5, 2022 · 4 comments
Closed
Labels
clang:tooling LibTooling

Comments

@DoDoENT
Copy link
Contributor

DoDoENT commented Sep 5, 2022

Consider this example:

template< typename T, auto ... dims >
struct NDArray;

struct Dimension
{
    using value_type = unsigned short;

    value_type size{ value_type( 0 ) };
};

template < typename ConcreteDim >
struct DimensionImpl : Dimension {}; 

struct Width : DimensionImpl< Width  > {};
struct Height: DimensionImpl< Height > {};

inline constexpr Width  W;
inline constexpr Height H;

NDArray< float, W > bla;

Clang reports the error as

error: implicit instantiation of undefined template 'NDArray<float, {{{0}}}>

while GCC provides full type information:

error: aggregate 'NDArray<float, Width{DimensionImpl<Width>{Dimension{0}}}> bla' has incomplete type and cannot be defined

In my code, I'm using libTooling to obtain full type names of some C++ code, and I've noticed that in cases such as the above, Clang simply writes {{{0}}} instead of Width{DimensionImpl<Width>{Dimension{0}}}. This is problematic for me as my tool should behave differently if this {{{0}}} is actually Width than if it's actually Height.

I'm obtaining type information in libTooling using this snippet:

bool VisitVarDecl( clang::VarDecl * varDecl )
{
     auto canonicalType{ varDecl->getType().getCanonicalType().getAsString() };
     // make some decisions based on canonicalType
     return true;
}

However, clang appears to correctly resolve overloads taking NDArray< float, W > vs NDArray< float, H >, so this means that clang actually does have a distinction between those two types.

However, how to obtain the full name of the type?

Also, would you consider putting the full name of the type in the clang's error as well (the way GCC does)?

@EugeneZelenko EugeneZelenko added clang:tooling LibTooling and removed new issue labels Sep 5, 2022
@DoDoENT
Copy link
Contributor Author

DoDoENT commented Sep 7, 2022

The issue also persists in clang 15.0.0.

@DoDoENT
Copy link
Contributor Author

DoDoENT commented Sep 7, 2022

I've noticed that stack traces displayed by LLDB and sanitizers show the full correct name of the type, however, it appears that they parse that from debug info stored in the binary, which means that someone somewhere had to write that inside, meaning that clang has that information somewhere.

Can someone point me to how to get the same strings LLDB and sanitizer get for type names from AST nodes?

@dwblaikie
Copy link
Collaborator

LLDB and sanitizers probably get it from mangled names - though you could check in the DWARF to see if the human-readable names are better than the ones you're getting in diagnostics.
If you compile a small program with -g and then use llvm-dwarfdump on that object/executable, you should get the debug info that's used by LLDB, etc. The functions should have a DW_AT_name that's the human-readable version, and a DW_AT_linkage_name that's the mangled one. The mangled one would certainly demangle (using llvm-cxxfilt I think) to include the extra info, I would imagine. But I don't know if the human-readable one would be unambiguous or not - if it is, then you could go look in clang's CGDebugInfo.cpp to see how that name is generated.

@DoDoENT
Copy link
Contributor Author

DoDoENT commented Sep 22, 2022

@dwblaikie, thank you for the pointers. I've investigated how the name is getting printed in AST and created this patch which actually gets me the behavior I want (the same as GCC).

I've made a patch for LLVM.

DoDoENT added a commit to microblink/llvm-project that referenced this issue Sep 22, 2022
…ting policy

If enabled, it will ensure that full type name is always printed.
This should fix issue reported here: llvm#57562

Currently, I've disabled the policy by default, as enabling it makes some tests fail, notably:
- CodeGenCXX/debug-info-template.cpp
- SemaCXX/constexpr-printing.cpp
- SemaCXX/cxx2a-nttp-printing.cpp
- SemaTemplate/temp_arg_string_printing.cpp

However, my opinion is that those tests should be updated and new policy always enabled, to mimic GCC's behavior.

I've added 2 new tests in AST/TypePrinterTest.cpp, one of which actually demonstrates the issue I've had in the first place (which was also reported on GitHub).

Differential Revision: https://reviews.llvm.org/D134453
DoDoENT added a commit to microblink/llvm-project that referenced this issue Oct 27, 2022
When printing NTTP template types, ensure that type name of the NTTP is
printed.

This should fix issue reported here: llvm#57562

Differential Revision: https://reviews.llvm.org/D134453
virnarula pushed a commit to virnarula/llvm-project that referenced this issue Nov 2, 2022
When printing NTTP template types, ensure that type name of the NTTP is
printed.

Fixes llvm#57562

Differential Revision: https://reviews.llvm.org/D134453
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:tooling LibTooling
Projects
None yet
Development

No branches or pull requests

3 participants