Skip to content

Commit 89e0168

Browse files
committed
[clang] check deduction consistency when partial ordering function templates
This makes partial ordering of function templates consistent with other entities. Fixes #18291
1 parent 70a9535 commit 89e0168

10 files changed

+695
-300
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ Bug Fixes to C++ Support
153153

154154
- Fixed a crash when an expression with a dependent ``__typeof__`` type is used as the operand of a unary operator. (#GH97646)
155155
- Fixed a failed assertion when checking invalid delete operator declaration. (#GH96191)
156+
- When performing partial ordering of function templates, clang now checks that
157+
the deduction was consistent. Fixes (#GH18291).
156158

157159
Bug Fixes to AST Handling
158160
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/ExprConstant.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5346,7 +5346,6 @@ static EvalStmtResult EvaluateStmt(StmtResult &Result, EvalInfo &Info,
53465346
const Expr *RetExpr = cast<ReturnStmt>(S)->getRetValue();
53475347
FullExpressionRAII Scope(Info);
53485348
if (RetExpr && RetExpr->isValueDependent()) {
5349-
EvaluateDependentExpr(RetExpr, Info);
53505349
// We know we returned, but we don't know what the value is.
53515350
return ESR_Failed;
53525351
}

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 577 additions & 249 deletions
Large diffs are not rendered by default.

clang/test/CodeCompletion/variadic-template.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ void f() {
88
// The important thing is that we provide OVERLOAD signature in all those cases.
99
//
1010
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-5):7 %s -o - | FileCheck --check-prefix=CHECK-1 %s
11-
// CHECK-1: OVERLOAD: [#void#]fun(<#T x#>, Args args...)
11+
// CHECK-1: OVERLOAD: [#void#]fun(<#T x#>)
1212
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-7):10 %s -o - | FileCheck --check-prefix=CHECK-2 %s
1313
// CHECK-2: OVERLOAD: [#void#]fun(int x)
1414
// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:%(line-9):13 %s -o - | FileCheck --check-prefix=CHECK-3 %s

clang/test/Index/complete-call.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,8 @@ struct Bar2Template : public BarTemplates {
409409
// CHECK-CC22-NEXT: Objective-C interface
410410

411411
// RUN: c-index-test -code-completion-at=%s:64:10 %s | FileCheck -check-prefix=CHECK-CC23 %s
412-
// CHECK-CC23: OverloadCandidate:{ResultType void}{Text foo_12}{LeftParen (}{CurrentParameter int}{Comma , }{Placeholder int}{RightParen )} (1)
412+
413+
// CHECK-CC23: OverloadCandidate:{ResultType void}{Text foo_12}{LeftParen (}{CurrentParameter T}{Comma , }{Placeholder T}{RightParen )} (1)
413414
// CHECK-CC23: Completion contexts:
414415
// CHECK-CC23-NEXT: Any type
415416
// CHECK-CC23-NEXT: Any value
@@ -702,7 +703,7 @@ struct Bar2Template : public BarTemplates {
702703
// CHECK-CC46-NEXT: Objective-C interface
703704

704705
// RUN: c-index-test -code-completion-at=%s:84:12 %s | FileCheck -check-prefix=CHECK-CC47 %s
705-
// CHECK-CC47: OverloadCandidate:{ResultType void}{Text foo_12}{LeftParen (}{CurrentParameter int}{Comma , }{Placeholder int}{RightParen )} (1)
706+
// CHECK-CC47: OverloadCandidate:{ResultType void}{Text foo_12}{LeftParen (}{CurrentParameter T}{Comma , }{Placeholder T}{RightParen )} (1)
706707
// CHECK-CC47: Completion contexts:
707708
// CHECK-CC47-NEXT: Any type
708709
// CHECK-CC47-NEXT: Any value

clang/test/SemaTemplate/GH18291.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang_cc1 -std=c++23 -verify %s
2+
3+
namespace t1 {
4+
template<bool> struct enable_if { typedef void type; };
5+
template <class T> class Foo {};
6+
template <class X> constexpr bool check() { return true; }
7+
template <class X, class Enable = void> struct Bar {};
8+
9+
template<class X> void func(Bar<X, typename enable_if<check<X>()>::type>) {}
10+
// expected-note@-1 {{candidate function}}
11+
12+
template<class T> void func(Bar<Foo<T>>) {}
13+
// expected-note@-1 {{candidate function}}
14+
15+
void g() {
16+
func(Bar<Foo<int>>()); // expected-error {{call to 'func' is ambiguous}}
17+
}
18+
} // namespace t1
19+
20+
namespace t2 {
21+
template <bool> struct enable_if;
22+
template <> struct enable_if<true> {
23+
typedef int type;
24+
};
25+
struct pair {
26+
template <int = 0> pair(int);
27+
template <class _U2, enable_if<__is_constructible(int &, _U2)>::type = 0>
28+
pair(_U2 &&);
29+
};
30+
int test_test_i;
31+
void test() { pair{test_test_i}; }
32+
} // namespace t2

clang/test/SemaTemplate/cwg2398.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ namespace class_template {
7474
// new-error@-1 {{ambiguous partial specialization}}
7575
} // namespace class_template
7676

77+
namespace class_template_func {
78+
template <class T1, class T2 = float> struct A {};
79+
80+
template <template <class T4> class TT1, class T5> void f(TT1<T5>);
81+
// new-note@-1 {{candidate function}}
82+
83+
template <class T6, class T7> void f(A<T6, T7>) {};
84+
// new-note@-1 {{candidate function}}
85+
86+
void g() {
87+
f(A<int>()); // new-error {{call to 'f' is ambiguous}}
88+
}
89+
} // namespace class_template_func
90+
7791
namespace type_pack1 {
7892
template<class T2> struct A;
7993
template<template<class ...T3s> class TT1, class T4> struct A<TT1<T4>> ;

clang/test/SemaTemplate/temp_arg_nontype.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -458,17 +458,13 @@ namespace dependent_nested_partial_specialization {
458458
namespace nondependent_default_arg_ordering {
459459
int n, m;
460460
template<typename A, A B = &n> struct X {};
461-
template<typename A> void f(X<A>); // expected-note {{candidate}}
462-
template<typename A> void f(X<A, &m>); // expected-note {{candidate}}
463-
template<typename A, A B> void f(X<A, B>); // expected-note 2{{candidate}}
461+
template<typename A> void f(X<A>);
462+
template<typename A> void f(X<A, &m>);
463+
template<typename A, A B> void f(X<A, B>);
464464
template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>);
465465
void g() {
466-
// FIXME: The first and second function templates above should be
467-
// considered more specialized than the third, but during partial
468-
// ordering we fail to check that we actually deduced template arguments
469-
// that make the deduced A identical to A.
470-
X<int *, &n> x; f(x); // expected-error {{ambiguous}}
471-
X<int *, &m> y; f(y); // expected-error {{ambiguous}}
466+
X<int *, &n> x; f(x);
467+
X<int *, &m> y; f(y);
472468
}
473469
}
474470

clang/test/SemaTemplate/temp_arg_type.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,10 @@ namespace deduce_noexcept {
6969
void noexcept_function() noexcept;
7070
void throwing_function();
7171

72-
template<typename T, bool B> float &deduce_function(T(*)() noexcept(B)); // expected-note {{candidate}}
73-
template<typename T> int &deduce_function(T(*)() noexcept); // expected-note {{candidate}}
72+
template<typename T, bool B> float &deduce_function(T(*)() noexcept(B));
73+
template<typename T> int &deduce_function(T(*)() noexcept);
7474
void test_function_deduction() {
75-
// FIXME: This should probably unambiguously select the second overload.
76-
int &r = deduce_function(noexcept_function); // expected-error {{ambiguous}}
75+
int &r = deduce_function(noexcept_function);
7776
float &s = deduce_function(throwing_function);
7877
}
7978

clang/test/Templight/templight-empty-entries-fix.cpp

Lines changed: 58 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,30 @@ template <bool d = true, class = typename b<d>::c> void a() { a(); }
170170

171171
template <bool = true> void d(int = 0) { d(); }
172172

173+
// CHECK-LABEL: {{^---$}}
174+
// CHECK: {{^name:[ ]+a$}}
175+
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
176+
// CHECK: {{^event:[ ]+Begin$}}
177+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
178+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
179+
// CHECK-LABEL: {{^---$}}
180+
// CHECK: {{^name:[ ]+a$}}
181+
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
182+
// CHECK: {{^event:[ ]+End$}}
183+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:60:57'$}}
184+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
185+
// CHECK-LABEL: {{^---$}}
186+
// CHECK: {{^name:[ ]+a$}}
187+
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
188+
// CHECK: {{^event:[ ]+Begin$}}
189+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
190+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
191+
// CHECK-LABEL: {{^---$}}
192+
// CHECK: {{^name:[ ]+a$}}
193+
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
194+
// CHECK: {{^event:[ ]+End$}}
195+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:20:25'$}}
196+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:60:63'$}}
173197
// CHECK-LABEL: {{^---$}}
174198
// CHECK: {{^name:[ ]+d$}}
175199
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
@@ -225,41 +249,41 @@ void e() {
225249
}
226250

227251
// CHECK-LABEL: {{^---$}}
228-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
252+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
229253
// CHECK: {{^kind:[ ]+Memoization$}}
230254
// CHECK: {{^event:[ ]+Begin$}}
231-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
232-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
255+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
256+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
233257
// CHECK-LABEL: {{^---$}}
234-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
258+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
235259
// CHECK: {{^kind:[ ]+Memoization$}}
236260
// CHECK: {{^event:[ ]+End$}}
237-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
238-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
261+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
262+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
239263
// CHECK-LABEL: {{^---$}}
240-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
264+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
241265
// CHECK: {{^kind:[ ]+Memoization$}}
242266
// CHECK: {{^event:[ ]+Begin$}}
243-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
244-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
267+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
268+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
245269
// CHECK-LABEL: {{^---$}}
246-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
270+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
247271
// CHECK: {{^kind:[ ]+Memoization$}}
248272
// CHECK: {{^event:[ ]+End$}}
249-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
250-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:224:5'$}}
273+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
274+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:248:5'$}}
251275
// CHECK-LABEL: {{^---$}}
252-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
276+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
253277
// CHECK: {{^kind:[ ]+Memoization$}}
254278
// CHECK: {{^event:[ ]+Begin$}}
255-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
256-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
279+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
280+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
257281
// CHECK-LABEL: {{^---$}}
258-
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:223:3\)'$}}
282+
// CHECK: {{^name:[ ]+'\(unnamed struct at .*templight-empty-entries-fix.cpp:247:3\)'$}}
259283
// CHECK: {{^kind:[ ]+Memoization$}}
260284
// CHECK: {{^event:[ ]+End$}}
261-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
262-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:223:3'$}}
285+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
286+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:247:3'$}}
263287

264288

265289
template <template<typename> class>
@@ -275,59 +299,59 @@ void foo() {
275299
// CHECK: {{^name:[ ]+d$}}
276300
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
277301
// CHECK: {{^event:[ ]+Begin$}}
278-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
279-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
302+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
303+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
280304
// CHECK-LABEL: {{^---$}}
281305
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
282306
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
283307
// CHECK: {{^event:[ ]+Begin$}}
284-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
308+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
285309
// CHECK: {{^poi:[ ]+''$}}
286310
// CHECK-LABEL: {{^---$}}
287311
// CHECK: {{^name:[ ]+unnamed template template parameter 0 of d$}}
288312
// CHECK: {{^kind:[ ]+PriorTemplateArgumentSubstitution$}}
289313
// CHECK: {{^event:[ ]+End$}}
290-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:265:35'$}}
314+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:289:35'$}}
291315
// CHECK: {{^poi:[ ]+''$}}
292316
// CHECK-LABEL: {{^---$}}
293317
// CHECK: {{^name:[ ]+d$}}
294318
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
295319
// CHECK: {{^event:[ ]+End$}}
296-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
297-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
320+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
321+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
298322
// CHECK-LABEL: {{^---$}}
299323
// CHECK: {{^name:[ ]+d$}}
300324
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
301325
// CHECK: {{^event:[ ]+Begin$}}
302-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
303-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
326+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
327+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
304328
// CHECK-LABEL: {{^---$}}
305329
// CHECK: {{^name:[ ]+d$}}
306330
// CHECK: {{^kind:[ ]+DeducedTemplateArgumentSubstitution$}}
307331
// CHECK: {{^event:[ ]+End$}}
308-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
309-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
332+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
333+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
310334
// CHECK-LABEL: {{^---$}}
311335
// CHECK: {{^name:[ ]+'d<C>'$}}
312336
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
313337
// CHECK: {{^event:[ ]+Begin$}}
314-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
315-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
338+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
339+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
316340
// CHECK-LABEL: {{^---$}}
317341
// CHECK: {{^name:[ ]+'d<C>'$}}
318342
// CHECK: {{^kind:[ ]+TemplateInstantiation$}}
319343
// CHECK: {{^event:[ ]+End$}}
320-
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:266:6'$}}
321-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
344+
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:290:6'$}}
345+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
322346
// CHECK-LABEL: {{^---$}}
323347
// CHECK: {{^name:[ ]+d$}}
324348
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
325349
// CHECK: {{^event:[ ]+Begin$}}
326350
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
327-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
351+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}
328352
// CHECK-LABEL: {{^---$}}
329353
// CHECK: {{^name:[ ]+d$}}
330354
// CHECK: {{^kind:[ ]+ExplicitTemplateArgumentSubstitution$}}
331355
// CHECK: {{^event:[ ]+End$}}
332356
// CHECK: {{^orig:[ ]+'.*templight-empty-entries-fix.cpp:171:29'$}}
333-
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:271:3'$}}
357+
// CHECK: {{^poi:[ ]+'.*templight-empty-entries-fix.cpp:295:3'$}}

0 commit comments

Comments
 (0)