Skip to content

Commit b9f1cc4

Browse files
author
Patrick Palka
committed
c++: constrained memfn vs corresponding using [PR121351]
The b.f(42) calls in the below testcases started to get rejected as ambiguous after r15-3740 which corrected our inheritedness tiebreaker to only apply to constructors (and not all member functions) as per CWG2273. But arguably these calls should still be valid regardless of the tiebreaker because B::f corresponds to and therefore hides A::f, so there should only be a single candidate in the first place. This doesn't happen because when determining correspondence we compare the members' uninstantiated constraints instead of their partially substituted constraints as in other declaration matching situations. It doesn't really make sense to compare uninstantiated constraints from two different template contexts. This patch fixes this by substituting in outer template arguments before comparing constraints of two potentially corresponding member functions. PR c++/121351 PR c++/119859 gcc/cp/ChangeLog: * class.cc (add_method): Substitute outer template arguments into constraints before comparing them if the declarations are from different classes. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-using5.C: New test. * g++.dg/cpp2a/concepts-using5a.C: New test. Reviewed-by: Jason Merrill <[email protected]>
1 parent b51ca7d commit b9f1cc4

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

gcc/cp/class.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,30 @@ add_method (tree type, tree method, bool via_using)
13561356
if (!compparms (parms1, parms2))
13571357
continue;
13581358

1359-
if (!equivalently_constrained (fn, method))
1359+
tree fn_constraints = get_constraints (fn);
1360+
tree method_constraints = get_constraints (method);
1361+
1362+
if (fn_constraints && method_constraints
1363+
&& DECL_CONTEXT (fn) != type
1364+
&& !processing_template_decl)
1365+
{
1366+
if (TREE_CODE (fn) == TEMPLATE_DECL)
1367+
++processing_template_decl;
1368+
if (tree ti = CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (fn)))
1369+
fn_constraints = tsubst_constraint_info (fn_constraints,
1370+
TI_ARGS (ti),
1371+
tf_warning_or_error,
1372+
fn);
1373+
if (tree ti = CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (method)))
1374+
method_constraints = tsubst_constraint_info (method_constraints,
1375+
TI_ARGS (ti),
1376+
tf_warning_or_error,
1377+
method);
1378+
if (TREE_CODE (fn) == TEMPLATE_DECL)
1379+
--processing_template_decl;
1380+
}
1381+
1382+
if (!equivalent_constraints (fn_constraints, method_constraints))
13601383
{
13611384
if (processing_template_decl)
13621385
/* We can't check satisfaction in dependent context, wait until
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// PR c++/121351
2+
// { dg-do compile { target c++20 } }
3+
4+
template<class T> concept C = true;
5+
6+
template<class T>
7+
struct A {
8+
template<class U> void f(U) requires C<T> = delete; // #1
9+
};
10+
11+
struct B : A<int> {
12+
using A::f;
13+
template<class U> void f(U) requires C<int>; // #2
14+
};
15+
16+
int main() {
17+
B b;
18+
b.f(42); // OK, #2 corresponds to and therefore hides #1
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// PR c++/121351
2+
// { dg-do compile { target c++20 } }
3+
// A version of concepts-using5a.C where B instead of A is a template.
4+
5+
template<class T> concept C = true;
6+
7+
struct A {
8+
template<class U> void f(U) requires C<int> = delete; // #1
9+
};
10+
11+
template<class T>
12+
struct B : A {
13+
using A::f;
14+
template<class U> void f(U) requires C<T>; // #2
15+
};
16+
17+
int main() {
18+
B<int> b;
19+
b.f(42); // OK, #2 corresponds to and therefore hides #1
20+
}

0 commit comments

Comments
 (0)