Skip to content

Regression in clang 16 -frelaxed-template-template-args support to alias templates. #63281

Open
@mawww

Description

@mawww
template<typename T, int I = 0>
struct A {};

template<typename T, int I = 0>
using B = A<T, I>; 

template<template <typename> typename T>
void g() {}

void f() {
    g<A>();
    g<B>();
}

fails to compile on Clang 16 (using -frelaxed-template-template-args) with the following error:

<source>:12:5: error: no matching function for call to 'g'
    g<B>();
    ^~~~
<source>:8:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'T'
void g() {}
     ^

The same code compiles on Clang 15. Removing -frelaxed-template-template-args makes that code fail in both Clang 15 and 16 and also complains about g<A>() with the same error.

Activity

added
clang:frontendLanguage frontend issues, e.g. anything involving "Sema"
and removed on Jun 13, 2023
llvmbot

llvmbot commented on Jun 13, 2023

@llvmbot
Member

@llvm/issue-subscribers-clang-frontend

krobelus

krobelus commented on Jun 13, 2023

@krobelus
Member

bisects to ef8feb6..f4ea3bd (using manyclangs)
probably introduced by f4ea3bd, cc @mizvekov

aThorp96

aThorp96 commented on Oct 24, 2023

@aThorp96

This appears to affect Apple's clang 15 as well. Is this the right place for that report?

 ~/code/cpp_test [04:36:12]
athorp$ cat test.cpp
template<typename T, int I = 0>
struct A {};

template<typename T, int I = 0>
using B = A<T, I>;

template<template <typename> typename T>
void g() {}

void f() {
    g<A>();
    g<B>();
}%
 ~/code/cpp_test [04:36:14]
athorp$ c++ --version
Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: arm64-apple-darwin22.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
 ~/code/cpp_test [04:36:21]
athorp$ c++ -Wc++11-extensions test.cpp
test.cpp:5:11: warning: alias declarations are a C++11 extension [-Wc++11-extensions]
using B = A<T, I>;
          ^
test.cpp:7:30: warning: template template parameter using 'typename' is a C++17 extension [-Wc++17-extensions]
template<template <typename> typename T>
                             ^~~~~~~~
                             class
test.cpp:11:5: error: no matching function for call to 'g'
    g<A>();
    ^~~~
test.cpp:8:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'T'
void g() {}
     ^
test.cpp:12:5: error: no matching function for call to 'g'
    g<B>();
    ^~~~
test.cpp:8:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'T'
void g() {}
     ^
2 warnings and 2 errors generated.
 ~/code/cpp_test [04:36:31]
athorp$ c++ -frelaxed-template-template-args -Wc++11-extensions test.cpp
test.cpp:5:11: warning: alias declarations are a C++11 extension [-Wc++11-extensions]
using B = A<T, I>;
          ^
test.cpp:7:30: warning: template template parameter using 'typename' is a C++17 extension [-Wc++17-extensions]
template<template <typename> typename T>
                             ^~~~~~~~
                             class
test.cpp:12:5: error: no matching function for call to 'g'
    g<B>();
    ^~~~
test.cpp:8:6: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'T'
void g() {}
     ^
2 warnings and 1 error generated.
self-assigned this
on Oct 25, 2023
mizvekov

mizvekov commented on Apr 27, 2024

@mizvekov
Contributor

Note that this didn't work in clang-15 properly either: https://godbolt.org/z/GbcEvW1cM

Notice the previously incorrect deduction, which would produce a different instantiation, and so failing to diagnose the duplicate explicit instantiation.

mizvekov

mizvekov commented on Apr 28, 2024

@mizvekov
Contributor

The latter issue, which I mentioned, of producing different instantiations is tracked by CWG1286, which is still unresolved, but we should probably implement provisional wording.

There is already an LLVM issue for it: #65843


The original issue, failure to deduce an alias template, I believe clang is correct to reject it.

See https://eel.is/c++draft/temp.deduct#type-8 and more specifically https://eel.is/c++draft/temp.deduct#type-8.2

A template type argument T, a template template argument TT, or a template non-type argument i can be deduced if P and A have one of the following forms:

...
TTopt
...

where

(8.2) TTopt represents either a class template or a template template parameter,

An alias template is neither a class template nor a template template parameter.

And see also this note: https://eel.is/c++draft/temp.alias#note-1

Note 1: An alias template name is never deduced. — end note
cor3ntin

cor3ntin commented on Apr 30, 2024

@cor3ntin
Contributor

@mizvekov I agree with this reading. You might want to improve diagnostics in a separate PR

Edit: Actually, I'm not sure. What we are trying to deduce here is not the alias but its template arguments.
And there is wild divergence. It might be a bug in https://eel.is/c++draft/temp.deduct#type-8 @zygoloid @erichkeane

Edit2: not that much divergence https://godbolt.org/z/jc77frbMz
But this looks like CWG2037/CWG1286/etc

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @mawww@mizvekov@cor3ntin@krobelus@EugeneZelenko

      Issue actions

        Regression in clang 16 `-frelaxed-template-template-args` support to alias templates. · Issue #63281 · llvm/llvm-project