[Clang] Clarify diagnostic notes for implicitly generated deduction guides (#96084)

Given the following invalid code,
```cpp
template <class T>
struct S {
  T *a;
};
S s = {1};
```
we produce such diagnostics currently:
```
<source>:2:8: note: candidate template ignored: could not match 'S<T>' against 'int'
    2 | struct S {
      |        ^
<source>:2:8: note: candidate template ignored: could not match 'T *' against 'int'
```
Which I think is confusing because there's no `S<T>` nor `T *` at the
location it points to. This is because we're deducing the initializer
against implicitly generated deduction guides, and their source
locations just point to the corresponding `RecordDecl`. Hence the
misleading notes.

This patch alleviates the issue by adding extra notes demonstrating
which implicit deduction guide we're deducing against. In other words,
in addition to the note of `could not match 'T *' against 'int'`, we
would also say the implicit deduction guide we're trying to use:
`template <class T> S(T *) -> S<T>`, which looks clearer IMO.

---------

Co-authored-by: Sirraide <aeternalmail@gmail.com>
This commit is contained in:
Younan Zhang 2024-07-02 19:34:48 +08:00 committed by GitHub
parent 7d0656d734
commit 3b639d7d1d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 156 additions and 44 deletions

View File

@ -651,6 +651,8 @@ Improvements to Clang's diagnostics
that will be destroyed at the end of the full expression.
Fixes #GH54492.
- Clang now shows implicit deduction guides when diagnosing overload resolution failure. #GH92393.
Improvements to Clang's time-trace
----------------------------------

View File

@ -2419,6 +2419,7 @@ def err_selected_explicit_constructor : Error<
"chosen constructor is explicit in copy-initialization">;
def note_explicit_ctor_deduction_guide_here : Note<
"explicit %select{constructor|deduction guide}0 declared here">;
def note_implicit_deduction_guide : Note<"implicit deduction guide declared as '%0'">;
// C++11 auto
def warn_cxx98_compat_auto_type_specifier : Warning<

View File

@ -40,6 +40,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLForwardCompat.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@ -11884,6 +11885,46 @@ static void DiagnoseFailedExplicitSpec(Sema &S, OverloadCandidate *Cand) {
<< (ES.getExpr() ? ES.getExpr()->getSourceRange() : SourceRange());
}
static void NoteImplicitDeductionGuide(Sema &S, FunctionDecl *Fn) {
auto *DG = dyn_cast<CXXDeductionGuideDecl>(Fn);
if (!DG)
return;
TemplateDecl *OriginTemplate =
DG->getDeclName().getCXXDeductionGuideTemplate();
// We want to always print synthesized deduction guides for type aliases.
// They would retain the explicit bit of the corresponding constructor.
if (!(DG->isImplicit() || (OriginTemplate && OriginTemplate->isTypeAlias())))
return;
std::string FunctionProto;
llvm::raw_string_ostream OS(FunctionProto);
FunctionTemplateDecl *Template = DG->getDescribedFunctionTemplate();
if (!Template) {
// This also could be an instantiation. Find out the primary template.
FunctionDecl *Pattern =
DG->getTemplateInstantiationPattern(/*ForDefinition=*/false);
if (!Pattern) {
// The implicit deduction guide is built on an explicit non-template
// deduction guide. Currently, this might be the case only for type
// aliases.
// FIXME: Add a test once https://github.com/llvm/llvm-project/pull/96686
// gets merged.
assert(OriginTemplate->isTypeAlias() &&
"Non-template implicit deduction guides are only possible for "
"type aliases");
DG->print(OS);
S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
<< FunctionProto;
return;
}
Template = Pattern->getDescribedFunctionTemplate();
assert(Template && "Cannot find the associated function template of "
"CXXDeductionGuideDecl?");
}
Template->print(OS);
S.Diag(DG->getLocation(), diag::note_implicit_deduction_guide)
<< FunctionProto;
}
/// Generates a 'note' diagnostic for an overload candidate. We've
/// already generated a primary error at the call site.
///
@ -11941,6 +11982,17 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return;
}
// If this is a synthesized deduction guide we're deducing against, add a note
// for it. These deduction guides are not explicitly spelled in the source
// code, so simply printing a deduction failure note mentioning synthesized
// template parameters or pointing to the header of the surrounding RecordDecl
// would be confusing.
//
// We prefer adding such notes at the end of the deduction failure because
// duplicate code snippets appearing in the diagnostic would likely become
// noisy.
auto _ = llvm::make_scope_exit([&] { NoteImplicitDeductionGuide(S, Fn); });
switch (Cand->FailureKind) {
case ovl_fail_too_many_arguments:
case ovl_fail_too_few_arguments:

View File

@ -193,8 +193,11 @@ static_assert(__is_same(decltype(i), I<char, 4>));
J j = { "ghi" };
// since-cxx20-error@-1 {{no viable constructor or deduction guide}}
// since-cxx20-note@#cwg2681-J {{candidate template ignored: could not match 'J<N>' against 'const char *'}}
// since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J(J<N>) -> J<N>'}}
// since-cxx20-note@#cwg2681-J {{candidate template ignored: could not match 'const unsigned char' against 'const char'}}
// since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J(const unsigned char (&)[N]) -> J<N>'}}
// since-cxx20-note@#cwg2681-J {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
// since-cxx20-note@#cwg2681-J {{implicit deduction guide declared as 'template <size_t N> J() -> J<N>'}}
#endif
}

View File

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -std=c++1z -verify %s
template<typename T> struct A { // expected-note 2{{candidate}}
template<typename T> struct A { // expected-note 2{{candidate}} expected-note 2{{implicit deduction guide}}
T t, u;
};
template<typename T> A(T, T) -> A<T>; // expected-note {{deduced conflicting types for parameter 'T'}}

View File

@ -35,8 +35,9 @@ namespace std {
}
namespace p0702r1 {
template<typename T> struct X { // expected-note {{candidate}}
X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'Z'}}
template<typename T> struct X { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
X(std::initializer_list<T>); // expected-note {{candidate template ignored: could not match 'std::initializer_list<T>' against 'Z'}} \
// expected-note {{implicit deduction guide declared as 'template <typename T> X(std::initializer_list<T>) -> X<T>'}}
};
X xi = {0};

View File

@ -6,8 +6,8 @@
#if __cplusplus > 201402L
namespace ClassTemplateParamNotForwardingRef {
// This is not a forwarding reference.
template<typename T> struct A { // expected-note {{candidate}}
A(T&&); // expected-note {{expects an rvalue}}
template<typename T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
A(T&&); // expected-note {{expects an rvalue}} expected-note {{implicit deduction guide}}
};
int n;
A a = n; // expected-error {{no viable constructor or deduction guide}}
@ -75,10 +75,12 @@ namespace std_example {
int n3 = g(i); // expected-error{{no matching function for call to 'g'}}
#if __cplusplus > 201402L
template<class T> struct A { // expected-note {{candidate}}
template<class T> struct A { // expected-note {{candidate}} expected-note {{implicit deduction guide}}
template<class U>
A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}}
A(T &&, int *); // expected-note {{requires 2}}
A(T &&, U &&, int *); // expected-note {{[with T = int, U = int] not viable: expects an rvalue}} \
// expected-note {{implicit deduction guide declared as 'template <class T, class U> A(T &&, type-parameter-0-1 &&, int *) -> A<T>'}}
A(T &&, int *); // expected-note {{requires 2}} \
// expected-note {{implicit deduction guide declared as 'template <class T> A(T &&, int *) -> A<T>'}}
};
template<class T> A(T &&, int *) -> A<T>; // expected-note {{requires 2}}

View File

@ -7,5 +7,7 @@ import foo;
void use() {
X x; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'X'}}
// expected-note@Inputs/template_name_lookup/foo.cppm:3 {{candidate template ignored: couldn't infer template argument 'T'}}
// expected-note@Inputs/template_name_lookup/foo.cppm:3 {{implicit deduction guide declared as 'template <typename T> X(X<T>) -> X<T>'}}
// expected-note@Inputs/template_name_lookup/foo.cppm:3 {{candidate function template not viable: requires 1 argument, but 0 were provided}}
// expected-note@Inputs/template_name_lookup/foo.cppm:3 {{implicit deduction guide declared as 'template <typename T> X() -> X<T>'}}
}

View File

@ -79,8 +79,8 @@ struct A {
B<true> b_true;
B<false> b_false;
#else
//expected-note@-8 {{candidate template ignored}}
//expected-note@-8 {{explicit constructor declared here}}
//expected-note@-8 {{candidate template ignored}} expected-note@-8 {{implicit deduction guide declared as 'template <bool b> A(A<b>) -> A<b>'}}
//expected-note@-8 {{explicit constructor declared here}} expected-note@-8 {{implicit deduction guide declared as 'template <bool b> explicit(b) A(B<b>) -> A<b>'}}
//expected-note@-15+ {{candidate constructor}}
//expected-note@-8+ {{explicit conversion function is not a candidate (explicit specifier}}
//expected-note@-11 {{explicit constructor is not a candidate (explicit specifier}}

View File

@ -22,7 +22,9 @@ struct struct_with_aligned_field {
template <typename>
struct templated_struct {};
// expected-note@-1{{candidate template ignored: couldn't infer template argument ''}}
// expected-note@-2{{candidate function template not viable: requires 1 argument, but 0 were provided}}
// expected-note@-2{{implicit deduction guide declared as 'template <typename> templated_struct() -> templated_struct<type-parameter-0-0>'}}
// expected-note@-3{{candidate function template not viable: requires 1 argument, but 0 were provided}}
// expected-note@-4{{implicit deduction guide declared as 'template <typename> templated_struct(templated_struct<type-parameter-0-0>) -> templated_struct<type-parameter-0-0>'}}
// A typedef of the aligned struct.
typedef aligned_struct another_aligned_struct;

View File

@ -139,11 +139,13 @@ namespace look_into_current_instantiation {
// templates, and members of the current instantiation
A<float> &r = a;
template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}}
template<typename T> struct B { // expected-note {{could not match 'B<T>' against 'int'}} \
// expected-note {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}}
struct X {
typedef T type;
};
B(typename X::type); // expected-note {{couldn't infer template argument 'T'}}
B(typename X::type); // expected-note {{couldn't infer template argument 'T'}} \
// expected-note {{implicit deduction guide declared as 'template <typename T> B(typename X::type) -> B<T>'}}
};
B b = 0; // expected-error {{no viable}}
@ -564,8 +566,10 @@ namespace PR47175 {
// Ensure we don't crash when CTAD fails.
template <typename T1, typename T2>
struct Foo { // expected-note{{candidate function template not viable}}
Foo(T1, T2); // expected-note{{candidate function template not viable}}
struct Foo { // expected-note {{candidate function template not viable}} \
// expected-note {{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(Foo<T1, T2>) -> Foo<T1, T2>'}}
Foo(T1, T2); // expected-note {{candidate function template not viable}} \
// expected-note {{implicit deduction guide declared as 'template <typename T1, typename T2> Foo(T1, T2) -> Foo<T1, T2>'}}
};
template <typename... Args>

View File

@ -110,6 +110,8 @@ struct Foo {
template <typename X, int Y>
using Bar = Foo<X, sizeof(X)>; // expected-note {{candidate template ignored: couldn't infer template argument 'X'}} \
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) Bar(Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
// expected-note {{implicit deduction guide declared as 'template <typename X> requires __is_deducible(test9::Bar, Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>) Bar(const type-parameter-0-0 (&)[sizeof(type-parameter-0-0)]) -> Foo<type-parameter-0-0, sizeof(type-parameter-0-0)>'}} \
// expected-note {{candidate template ignored: constraints not satisfied [with X = int]}} \
// expected-note {{cannot deduce template arguments for 'Bar' from 'Foo<int, 4UL>'}}
@ -137,9 +139,12 @@ struct A {};
template<class T> struct Foo { T c; };
template<class X, class Y=A>
using AFoo = Foo<Y>; // expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0>' against 'int'}} \
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
// expected-note {{candidate template ignored: constraints not satisfied [with Y = int]}} \
// expected-note {{cannot deduce template arguments for 'AFoo' from 'Foo<int>'}} \
// expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}}
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo(type-parameter-0-0) -> Foo<type-parameter-0-0>'}} \
// expected-note {{candidate function template not viable: requires 0 arguments, but 1 was provided}} \
// expected-note {{implicit deduction guide declared as 'template <class Y = A> requires __is_deducible(test11::AFoo, Foo<type-parameter-0-0>) AFoo() -> Foo<type-parameter-0-0>'}}
AFoo s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}}
} // namespace test11
@ -192,6 +197,8 @@ struct Foo {
template <int K>
using Bar = Foo<double, K>; // expected-note {{constraints not satisfied for class template 'Foo'}}
// expected-note@-1 {{candidate template ignored: could not match}}
// expected-note@-2 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(Foo<double, K>) -> Foo<double, K>'}}
// expected-note@-3 {{implicit deduction guide declared as 'template <int K> requires __is_deducible(test14::Bar, Foo<double, K>) Bar(const double (&)[K]) -> Foo<double, K>'}}
double abc[3];
Bar s2 = {abc}; // expected-error {{no viable constructor or deduction guide for deduction }}
} // namespace test14
@ -204,7 +211,9 @@ template<typename> concept False = false;
template<False W>
using BFoo = AFoo<W>; // expected-note {{candidate template ignored: constraints not satisfied [with V = int]}} \
// expected-note {{cannot deduce template arguments for 'BFoo' from 'Foo<int *>'}} \
// expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0 *>' against 'int *'}}
// expected-note {{implicit deduction guide declared as 'template <class V> requires __is_deducible(AFoo, Foo<type-parameter-0-0 *>) && __is_deducible(test15::BFoo, Foo<type-parameter-0-0 *>) BFoo(type-parameter-0-0 *) -> Foo<type-parameter-0-0 *>}} \
// expected-note {{candidate template ignored: could not match 'Foo<type-parameter-0-0 *>' against 'int *'}} \
// expected-note {{template <class V> requires __is_deducible(AFoo, Foo<type-parameter-0-0 *>) && __is_deducible(test15::BFoo, Foo<type-parameter-0-0 *>) BFoo(Foo<type-parameter-0-0 *>) -> Foo<type-parameter-0-0 *>}}
int i = 0;
AFoo a1(&i); // OK, deduce Foo<int *>
@ -255,8 +264,11 @@ Foo(T) -> Foo<int>;
template <typename U>
using Bar = Foo<U>; // expected-note {{could not match 'Foo<type-parameter-0-0>' against 'int'}} \
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<type-parameter-0-0>) Bar(Foo<type-parameter-0-0>) -> Foo<type-parameter-0-0>'}} \
// expected-note {{candidate template ignored: constraints not satisfied}} \
// expected-note {{candidate function template not viable}}
// expected-note {{implicit deduction guide declared as 'template <typename T> requires False<T> && __is_deducible(test18::Bar, Foo<int>) Bar(type-parameter-0-0) -> Foo<int>'}} \
// expected-note {{candidate function template not viable}} \
// expected-note {{implicit deduction guide declared as 'template <typename U> requires __is_deducible(test18::Bar, Foo<type-parameter-0-0>) Bar() -> Foo<type-parameter-0-0>'}}
Bar s = {1}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments}}
} // namespace test18
@ -284,7 +296,8 @@ class Foo {};
// Verify that template template type parameter TTP is referenced/used in the
// template arguments of the RHS.
template <template<typename> typename TTP>
using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<template-parameter-0-0>>' against 'int'}}
using Bar = Foo<K<TTP>>; // expected-note {{candidate template ignored: could not match 'Foo<K<template-parameter-0-0>>' against 'int'}} \
// expected-note {{implicit deduction guide declared as 'template <template <typename> typename TTP> requires __is_deducible(test20::Bar, Foo<K<template-parameter-0-0>>) Bar(Foo<K<template-parameter-0-0>>) -> Foo<K<template-parameter-0-0>>'}}
template <class T>
class Container {};

View File

@ -394,9 +394,11 @@ using type = T;
template<typename T1, typename T2, bool b>
struct A {
// expected-note@-1+ {{candidate function}}
// expected-note@-2+ {{implicit deduction guide}}
explicit(false)
A(typename nondeduced<T1>::type, typename nondeduced<T2>::type, typename nondeduced<B<b>>::type) {}
// expected-note@-1+ {{candidate template ignored}}
// expected-note@-2+ {{implicit deduction guide}}
};
template<typename T1, typename T2, bool b>
@ -678,10 +680,12 @@ namespace deduction_guide2 {
template<typename T1 = int, typename T2 = int>
struct A {
// expected-note@-1+ {{candidate template ignored}}
// expected-note@-2+ {{implicit deduction guide}}
explicit(!is_same<T1, T2>::value)
A(T1 = 0, T2 = 0) {}
// expected-note@-1 {{explicit constructor declared here}}
// expected-note@-2 2{{explicit constructor is not a candidate}}
// expected-note@-3 2{{implicit deduction guide declared}}
};
A a0 = 0;

View File

@ -3,9 +3,11 @@
class X {};
template<typename T>
class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}}
class B3 { // expected-note {{candidate template ignored: could not match 'B3<T>' against 'int'}} \
// expected-note {{implicit deduction guide declared as 'template <typename T> B3(B3<T>) -> B3<T>'}}
template<X x> B3(T); // expected-warning 2{{non-type template parameter of type 'X' is incompatible with C++ standards before C++20}} \
// expected-note {{candidate template ignored: couldn't infer template argument 'x'}}
// expected-note {{candidate template ignored: couldn't infer template argument 'x'}} \
// expected-note {{implicit deduction guide declared as 'template <typename T, X x> B3(T) -> B3<T>'}}
};
B3 b3 = 0; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'B3'}} \
// expected-note {{while building implicit deduction guide first needed here}}

View File

@ -1,6 +1,8 @@
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
template <class T> class Foo {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} \
// expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
// expected-note {{implicit deduction guide declared as 'template <class T> Foo(Foo<T>) -> Foo<T>'}} \
// expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
// expected-note {{implicit deduction guide declared as 'template <class T> Foo() -> Foo<T>'}}
Foo(); // expected-error {{deduction guide declaration without trailing return type}}
Foo vs; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'Foo'}}

View File

@ -3,8 +3,10 @@
// RUN: %clang_cc1 -std=c++20 %s -fsyntax-only -verify
extern "C++" {
template <class T>
class X {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}}
// expected-note@-1 {{candidate function template not viable: requires 1 argument, but 0 were provided}}
class X {}; // expected-note {{candidate template ignored: couldn't infer template argument 'T'}} \
// expected-note {{implicit deduction guide declared as 'template <class T> X(X<T>) -> X<T>'}} \
// expected-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
// expected-note {{implicit deduction guide declared as 'template <class T> X() -> X<T>'}}
}
void foo() {

View File

@ -2,7 +2,7 @@
// RUN: %clang_cc1 -std=c++20 -verify=expected,cxx20 -ast-dump -ast-dump-decl-types -ast-dump-filter "deduction guide" %s | FileCheck %s --strict-whitespace
namespace Basic {
template<class T> struct A { // cxx17-note 6 {{candidate}}
template<class T> struct A { // cxx17-note 6 {{candidate}} cxx17-note 6 {{implicit deduction guide}}
T x;
T y;
};
@ -36,12 +36,14 @@ namespace Basic {
T y;
};
template <typename T> struct C { // cxx20-note 10 {{candidate}} cxx17-note 12 {{candidate}}
template <typename T> struct C { // cxx20-note 10 {{candidate}} cxx17-note 12 {{candidate}} \
cxx20-note 10 {{implicit deduction guide}} cxx17-note 12 {{implicit deduction guide}}
S<T> s;
T t;
};
template <typename T> struct D { // cxx20-note 6 {{candidate}} cxx17-note 8 {{candidate}}
template <typename T> struct D { // cxx20-note 6 {{candidate}} cxx17-note 8 {{candidate}} \
cxx20-note 6 {{implicit deduction guide}} cxx17-note 8 {{implicit deduction guide}}
S<int> s;
T t;
};
@ -99,7 +101,7 @@ namespace Basic {
// CHECK: |-ClassTemplateSpecialization {{.*}} 'S'
// CHECK: `-BuiltinType {{.*}} 'int'
template <typename T> struct E { // cxx17-note 4 {{candidate}}
template <typename T> struct E { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
T t;
decltype(t) t2;
};
@ -133,7 +135,7 @@ namespace Basic {
};
template <typename T>
struct F { // cxx17-note 2 {{candidate}}
struct F { // cxx17-note 2 {{candidate}} cxx17-note 2 {{implicit deduction guide}}
typename I<T>::type i;
T t;
};
@ -161,7 +163,8 @@ namespace Basic {
namespace Array {
typedef unsigned long size_t;
template <typename T, size_t N> struct A { // cxx20-note 2 {{candidate}} cxx17-note 14 {{candidate}}
template <typename T, size_t N> struct A { // cxx20-note 2 {{candidate}} cxx17-note 14 {{candidate}} \
cxx20-note 2 {{implicit deduction guide}} cxx17-note 14 {{implicit deduction guide}}
T array[N];
};
@ -217,7 +220,7 @@ namespace Array {
}
namespace BraceElision {
template <typename T> struct A { // cxx17-note 4 {{candidate}}
template <typename T> struct A { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
T array[2];
};
@ -247,7 +250,7 @@ namespace BraceElision {
}
namespace TrailingPack {
template<typename... T> struct A : T... { // cxx17-note 4 {{candidate}}
template<typename... T> struct A : T... { // cxx17-note 4 {{candidate}} cxx17-note 4 {{implicit deduction guide}}
};
A a1 = { // cxx17-error {{no viable}}
@ -286,7 +289,7 @@ namespace TrailingPack {
}
namespace NonTrailingPack {
template<typename... T> struct A : T... { // expected-note 4 {{candidate}}
template<typename... T> struct A : T... { // expected-note 4 {{candidate}} expected-note 4 {{implicit deduction guide}}
int a;
};
@ -303,7 +306,8 @@ namespace NonTrailingPack {
namespace DeduceArity {
template <typename... T> struct Types {};
template <typename... T> struct F : Types<T...>, T... {}; // cxx20-note 12 {{candidate}} cxx17-note 16 {{candidate}}
template <typename... T> struct F : Types<T...>, T... {}; // cxx20-note 12 {{candidate}} cxx17-note 16 {{candidate}} \
cxx20-note 12 {{implicit deduction guide}} cxx17-note 16 {{implicit deduction guide}}
struct X {};
struct Y {};

View File

@ -45,6 +45,8 @@ typedef N::C<float> c2;
// PR5655
template<typename T> struct Foo { }; // precxx17-note {{template is declared here}} \
cxx17-note {{candidate template ignored: couldn't infer template argument 'T'}} \
cxx17-note {{implicit deduction guide declared as 'template <typename T> Foo() -> Foo<T>'}} \
cxx17-note {{implicit deduction guide declared as 'template <typename T> Foo(Foo<T>) -> Foo<T>'}} \
cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
void f(void) { Foo bar; } // precxx17-error {{use of class template 'Foo' requires template arguments}} \

View File

@ -20,8 +20,10 @@ namespace Access {
protected:
struct type {};
};
template<typename T> struct D : B { // expected-note {{not viable}}
D(T, typename T::type); // expected-note {{private member}}
template<typename T> struct D : B { // expected-note {{not viable}} \
expected-note {{implicit deduction guide declared as 'template <typename T> D(D<T>) -> D<T>'}}
D(T, typename T::type); // expected-note {{private member}} \
// expected-note {{implicit deduction guide declared as 'template <typename T> D(T, typename T::type) -> D<T>'}}
};
D b = {B(), {}};
@ -58,13 +60,15 @@ Y y(1);
namespace NoCrashOnGettingDefaultArgLoc {
template <typename>
class A {
A(int = 1); // expected-note {{candidate template ignored: couldn't infer template argumen}}
A(int = 1); // expected-note {{candidate template ignored: couldn't infer template argumen}} \
// expected-note {{implicit deduction guide declared as 'template <typename> D(int = <null expr>) -> D<type-parameter-0-0>'}}
};
class C : A<int> {
using A::A;
};
template <typename>
class D : C { // expected-note {{candidate function template not viable: requires 1 argument}}
class D : C { // expected-note {{candidate function template not viable: requires 1 argument}} \
expected-note {{implicit deduction guide declared as 'template <typename> D(D<type-parameter-0-0>) -> D<type-parameter-0-0>'}}
using C::C;
};
D abc; // expected-error {{no viable constructor or deduction guide}}

View File

@ -166,8 +166,9 @@ namespace PR51872_part1 {
template<int> class T1 { template <struct U1> T1(); };
// expected-error@-1 {{non-type template parameter has incomplete type 'struct U1'}}
// expected-note@-2 {{forward declaration of 'PR51872_part1::U1'}}
// expected-note@-3 {{implicit deduction guide declared as 'template <int> T1(T1<>) -> T1<>'}}
T1 t1 = 0;
// expected-error@-1 {{no viable constructor or deduction guide for deduction of template arguments of 'T1'}}
// expected-note@-6 {{candidate template ignored: could not match 'T1<>' against 'int'}}
// expected-note@-7 {{candidate template ignored: could not match 'T1<>' against 'int'}}
}

View File

@ -123,9 +123,11 @@ using CT = C<int>;
// CHECK: | `-TemplateArgument template
// CHECK: `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2
template<typename ...T> struct D { // expected-note {{candidate}}
template<typename ...T> struct D { // expected-note {{candidate}} \
// expected-note {{implicit deduction guide declared as 'template <typename ...T> D(D<T...>) -> D<T...>'}}
template<typename... U> using B = int(int (*...p)(T, U));
template<typename U1, typename U2> D(B<U1, U2>*); // expected-note {{candidate}}
template<typename U1, typename U2> D(B<U1, U2>*); // expected-note {{candidate}} \
// expected-note {{implicit deduction guide declared as 'template <typename ...T, typename U1, typename U2> D(B<type-parameter-0-1, type-parameter-0-2> *) -> D<T...>'}}
};
int f(int(int, int), int(int, int));
// FIXME: We can't deduce this because we can't deduce through a
@ -166,9 +168,11 @@ using DT = D<int, int>;
// CHECK-NOT: Subst
// CHECK: `-TemplateTypeParmType
template<int ...N> struct E { // expected-note {{candidate}}
template<int ...N> struct E { // expected-note {{candidate}} \
expected-note {{implicit deduction guide declared as 'template <int ...N> E(E<N...>) -> E<N...>'}}
template<int ...M> using B = Z<X<N, M>...>;
template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}}
template<int M1, int M2> E(B<M1, M2>); // expected-note {{candidate}} \
// expected-note {{implicit deduction guide declared as 'template <int ...N, int M1, int M2> E(B<M1, M2>) -> E<N...>'}}}}
};
// FIXME: We can't deduce this because we can't deduce through a
// SubstNonTypeTemplateParmPackExpr.

View File

@ -82,8 +82,11 @@ using NIL = nested_init_list<int>::B<int>;
// expected-error@+1 {{no viable constructor or deduction guide for deduction of template arguments of 'nested_init_list<int>::concept_fail'}}
nested_init_list<int>::concept_fail nil_invalid{1, ""};
// expected-note@#INIT_LIST_INNER_INVALID {{candidate template ignored: substitution failure [with F = const char *]: constraints not satisfied for class template 'concept_fail' [with F = const char *]}}
// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(int, F) -> concept_fail<F>'}}
// expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 1 argument, but 2 were provided}}
// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail(concept_fail<F>) -> concept_fail<F>'}}
// expected-note@#INIT_LIST_INNER_INVALID {{candidate function template not viable: requires 0 arguments, but 2 were provided}}
// expected-note@#INIT_LIST_INNER_INVALID {{implicit deduction guide declared as 'template <False F> concept_fail() -> concept_fail<F>'}}
namespace GH88142 {

View File

@ -6,7 +6,9 @@ template<typename T,
class A; // precxx17-note 3 {{template is declared here}} \
cxx17-note 2 {{template is declared here}} \
cxx17-note {{candidate template ignored: couldn't infer template argument 'T'}} \
cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}}
cxx17-note {{implicit deduction guide declared as 'template <typename T, int I, template <typename> class TT> A(A<T, I, TT>) -> A<T, I, TT>'}} \
cxx17-note {{candidate function template not viable: requires 1 argument, but 0 were provided}} \
cxx17-note {{implicit deduction guide declared as 'template <typename T, int I, template <typename> class TT> A() -> A<T, I, TT>'}} \
template<typename> class X;