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

[abi] mangled name for constrained template is not demangled by llvm-cxxfilt #89914

Open
hokein opened this issue Apr 24, 2024 · 9 comments · Fixed by #107385
Open

[abi] mangled name for constrained template is not demangled by llvm-cxxfilt #89914

hokein opened this issue Apr 24, 2024 · 9 comments · Fixed by #107385
Assignees
Labels
ABI Application Binary Interface libc++abi libc++abi C++ Runtime Library. Not libc++. tools:llvm-cxxfilt

Comments

@hokein
Copy link
Collaborator

hokein commented Apr 24, 2024

Example:

template <typename U, typename T>
concept True = true;

template <typename K>
struct Foo {
  template <True<K> U>
  void method(U t);
};

void s() {
   Foo<int> k;
   k.method(1);
}

Clang generates mangled name _ZN3FooIiE6methodITk4TrueIT_EiEEvS3_ for the template specialization Foo<int>::method. However this mangled name can not be demangled by the official tool llvm-cxxfilt.

It looks like something wrong with the constrain True part.

PS. gcc trunk generates a different name _ZN3FooIiE6methodIiEEvT_, which can be demangled, but it doesn't contain the constraint.

@hokein hokein added clang Clang issues not falling into any other category ABI Application Binary Interface clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Apr 24, 2024
@llvmbot
Copy link
Member

llvmbot commented Apr 24, 2024

@llvm/issue-subscribers-clang-frontend

Author: Haojian Wu (hokein)

Example:
template &lt;typename U, typename T&gt;
concept True = true;

template &lt;typename K&gt;
struct Foo {
  template &lt;True&lt;K&gt; U&gt;
  void method(U t);
};

void s() {
   Foo&lt;int&gt; k;
   k.method(1);
}

Clang generates mangled name _ZN3FooIiE6methodITk4TrueIT_EiEEvS3_ for the template specialization Foo&lt;int&gt;::method. However this mangled name can not be demangled by the official tool llvm-cxxfilt.

It looks like something wrong with the constrain True part.

PS. gcc trunk generates a different name _ZN3FooIiE6methodIiEEvT_, which can be demangled, but it doesn't contain the constraint.

@Michael137
Copy link
Member

Michael137 commented Apr 24, 2024

Looks like Clang mangles constraints with Tk:

// <template-param-decl>
//   ::= Ty                                  # template type parameter
//   ::= Tk <concept name> [<template-args>] # constrained type parameter
//   ::= Tn <type>                           # template non-type parameter
//   ::= Tt <template-param-decl>* E [Q <requires-clause expr>]
//                                           # template template parameter
//   ::= Tp <template-param-decl>            # template parameter pack
void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {
  // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/47.
  if (auto *Ty = dyn_cast<TemplateTypeParmDecl>(Decl)) {
    if (Ty->isParameterPack())
      Out << "Tp";
    const TypeConstraint *Constraint = Ty->getTypeConstraint();
    if (Constraint && !isCompatibleWith(LangOptions::ClangABI::Ver17)) {
      // Proposed on https://github.com/itanium-cxx-abi/cxx-abi/issues/24.
      Out << "Tk";
      mangleTypeConstraint(Constraint);

Which isn't standardised yet. We're just missing support for this new grammar in the libcxxabi demangler.

EDIT: Ah nvm, wasn't looking at the right place in the demangler. We are supposed to handle Tk already, but aren't

@hokein
Copy link
Collaborator Author

hokein commented Apr 24, 2024

We're just missing support for this new grammar in the libcxxabi demangler.

I think we have some supports for template constraints in the demangler, see https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5738.

Interestingly, the demangler works for the following code, where the mangled name is _ZN3FooIiE6methodITk4TrueIiEiEEvT_:

template <typename U, typename TTT>
concept True = true;

template <typename K>
struct Foo {
  // Replace the original K with `int`, _ZN3FooIiE6methodITk4TrueIiEiEEvT_
  template <True<int> U> 
  void method(U t);
};

void s() {
    Foo<int> k;
    k.method(1);
}

@EugeneZelenko EugeneZelenko removed the clang Clang issues not falling into any other category label Apr 24, 2024
@Michael137
Copy link
Member

Michael137 commented Apr 24, 2024

Issue seems to be that the reference T_ to the first template parameter fails to be parsed because when we parseTemplateArgs of the constraint, we clear out the OuterTemplateParams list, loosing the fact that we parsed int before. In your working example, note how the constraint parameter is i instead of T_. (similar to what I saw in #73521).

@hokein
Copy link
Collaborator Author

hokein commented Apr 25, 2024

Thanks!

Issue seems to be that the reference T_ to the first template parameter fails to be parsed because when we parseTemplateArgs of the constraint, we clear out the OuterTemplateParams list, loosing the fact that we parsed int before. In your working example, note how the constraint parameter is i instead of T_.

(assuming the mangled name is generated correctly) it sounds plausible. IIUC, it looks like an issue about template parameter backreferencing -- the T_ part of the constraint TrueIT_E should be substituted with the outer template argument which is int (the i in the FooIiE), but as you mentioned, we clear out this information when the demangler is parsing the template args of the constraint, thus it fails.

@ianlancetaylor
Copy link

But it seems that the current mangling expects that template references in constraints refer back to the template parameters of the template in which the constraint appears. Consider _ZN5test61gIiTk1DIT_EiEEvT0_ which is from libcxxabi/test/test_demangle.pass.cpp, line 30137. There it appears that the T_ refers to the i just before the Tk. What else could it possibly refer to?

@VitaNuo VitaNuo self-assigned this Sep 3, 2024
VitaNuo added a commit to VitaNuo/llvm-project that referenced this issue Sep 10, 2024
VitaNuo added a commit to VitaNuo/llvm-project that referenced this issue Sep 10, 2024
VitaNuo added a commit that referenced this issue Sep 12, 2024
…constraint expression (#107385)

This prevents demangler failures until the TODO in the
[demangler](https://github.com/llvm/llvm-project/blob/3e070906eff720dc44aee86e533e12aafc8bb14b/llvm/include/llvm/Demangle/ItaniumDemangle.h#L5678)
is implemented.

This is a temporary fix for
[#89914](#89914).
@EugeneZelenko EugeneZelenko added libc++abi libc++abi C++ Runtime Library. Not libc++. llvm Umbrella label for LLVM issues and removed clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 12, 2024
@VitaNuo VitaNuo reopened this Sep 16, 2024
@VitaNuo
Copy link
Contributor

VitaNuo commented Sep 16, 2024

Re-opened the issue, since I still intend to work on the proper demangling for contrained parameters.

Regarding resetting template parameter levels, here's the shortest example we have so far:

template <class ...Inner>
concept True = true;

template <class Outer>
struct Foo {
    template <class Middle>
    struct Bar {
            template <class Inner> requires True<Outer>
            static void baz();
    };
};

template <class Outer>
struct FooNext {
    template <class Middle>
    struct Bar {
            template <class Inner> requires True<Middle>
            static void foobar();
    };
};



template<void(*)()> struct FuncRef{};

void bar(FuncRef<&Foo<int>::Bar<bool>::baz<char>>,  FuncRef<&FooNext<int>::Bar<bool>::foobar<char>>) {}

It mangles to Z3bar7FuncRefIXadL_ZN3FooIiE3BarIbE3bazIcQ4TrueIT_EEEvvEEES_IXadL_ZN7FooNextIiE3BarIbE6foobarIcQ4TrueITL0__EEEvvEEE.

Note how T0_ and TL_ refer to the template parameter levels of two different templates in the same expression, which probably means some form of level clearing will still be necessary during demangling.

@EugeneZelenko EugeneZelenko added tools:llvm-cxxfilt and removed llvm Umbrella label for LLVM issues labels Sep 16, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2024

@llvm/issue-subscribers-tools-llvm-cxxfilt

Author: Haojian Wu (hokein)

Example:
template &lt;typename U, typename T&gt;
concept True = true;

template &lt;typename K&gt;
struct Foo {
  template &lt;True&lt;K&gt; U&gt;
  void method(U t);
};

void s() {
   Foo&lt;int&gt; k;
   k.method(1);
}

Clang generates mangled name _ZN3FooIiE6methodITk4TrueIT_EiEEvS3_ for the template specialization Foo&lt;int&gt;::method. However this mangled name can not be demangled by the official tool llvm-cxxfilt.

It looks like something wrong with the constrain True part.

PS. gcc trunk generates a different name _ZN3FooIiE6methodIiEEvT_, which can be demangled, but it doesn't contain the constraint.

@VitaNuo
Copy link
Contributor

VitaNuo commented Oct 22, 2024

We have discussed this in more detail with @zygoloid, who has provided compelling arguments for not demangling template parameter levels into specific types.

Consider the mangled names

_ZN1XIiiE1fEvQ1CIT_E
_ZN1XIiiE1fEvQ1CIT0_E

In the current version of the demangler, they would demangle to

X<$T = int, int>::f() requires C<$T>
X<int, $T = int>::f() requires C<$T>

If we implement the level demangling, both demanglings would become

X<int, int>::f() requires C<int>

which seems less useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ABI Application Binary Interface libc++abi libc++abi C++ Runtime Library. Not libc++. tools:llvm-cxxfilt
Projects
None yet
6 participants