mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-18 18:56:43 +00:00
[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:
parent
7d0656d734
commit
3b639d7d1d
@ -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
|
||||
----------------------------------
|
||||
|
||||
|
@ -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<
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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'}}
|
||||
|
@ -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};
|
||||
|
@ -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}}
|
||||
|
||||
|
@ -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>'}}
|
||||
}
|
||||
|
@ -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}}
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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 {};
|
||||
|
@ -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;
|
||||
|
@ -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}}
|
||||
|
@ -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'}}
|
||||
|
@ -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() {
|
||||
|
@ -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 {};
|
||||
|
@ -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}} \
|
||||
|
@ -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}}
|
||||
|
@ -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'}}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user