llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.32k stars 12.11k forks source link

Better warnings for structural non-type template substitution failure #60397

Open duk-37 opened 1 year ago

duk-37 commented 1 year ago

Simple repro involving user-defined string literals -- notice the difference in clarity between clang and gcc warnings

shafik commented 1 year ago

The sample program is:

#include <array>
#include <algorithm>
#include <string_view>

template <size_t N>
class stack_buffer {
    __attribute__((always_inline)) consteval stack_buffer(const char(&arr)[N]) {
        std::copy_n(arr, N, _buf);
    }

    char _buf[N];
};

template<stack_buffer F>
auto operator ""_test() {
    return 1234;
}

static auto z = "hello"_test;

The clang diagnostic is:

<source>:19:24: error: no matching literal operator for call to 'operator""_test' with arguments of types 'const char *' and 'unsigned long', and no matching literal operator template
static auto z = "hello"_test;
                       ^
1 error generated.

Vs gcc diagnostic:

<source>:19:17: error: no matching function for call to 'operator""_test<"hello">()'
   19 | static auto z = "hello"_test;
      |                 ^~~~~~~~~~~~
<source>:15:6: note: candidate: 'template<stack_buffer<...auto...> F> auto operator""_test()'
   15 | auto operator ""_test() {
      |      ^~~~~~~~
<source>:15:6: note:   template argument deduction/substitution failed:
<source>:19:17: error: 'stack_buffer<6>' is not a valid type for a template non-type parameter because it is not structural
   19 | static auto z = "hello"_test;
      |                 ^~~~~~~~~~~~
<source>:11:10: note: 'stack_buffer<6>::_buf' is not public
   11 |     char _buf[N];
      |          ^~~~
Compiler returned: 1

CC @cjdb @AaronBallman