[2/2] c++: CWG 2789 and usings [PR116492]
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
Commit Message
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
look OK for trunk? I'm not sure this is worth backporting
without the previous CWG 2273 tweak since it'll mean inconsistent
behavior between implict vs explicit object members in GCC 14: the call
to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
2273 tiebreaker incorrectly triggering), while the g() and h() calls
would be ambiguous (since that tiebreaker doesn't consider object
correspondence).
Also I'm not 100% sure if I'm interpreting "both are direct members of
the same class" correctly here to mean ruling out using'd vs non-using'd
members, since https://eel.is/c++draft/namespace.udecl#note-5 says
using'd members are "treated as though they were direct members of the
derived class"...?
-- >8 --
After CWG 2789, the "more constrained" tiebreaker for non-template
functions should exclude members that come from different classes
via using. This patch implements this missing refinement. In turn
we can get rid of four-parameter overload of object_parms_correspond
and call the main overload directly since we know correspondence is now
only checked for members from the same class.
PR c++/116492
DR 2789
gcc/cp/ChangeLog:
* call.cc (object_parms_correspond): Remove.
(cand_parms_match): Return false for member functions
that come from different classes. Adjust call to
object_parms_correspond.
(joust): Update comment for the non-template "more
constrained" case.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-memfun4.C: Expect ambiguity when
candidates come from different classes.
* g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
---
gcc/cp/call.cc | 54 +++++++------------
.../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 ++++++
gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C | 24 +++++----
3 files changed, 49 insertions(+), 45 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
Comments
On 9/18/24 10:59 PM, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
> look OK for trunk? I'm not sure this is worth backporting
> without the previous CWG 2273 tweak since it'll mean inconsistent
> behavior between implict vs explicit object members in GCC 14: the call
> to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
> 2273 tiebreaker incorrectly triggering), while the g() and h() calls
> would be ambiguous (since that tiebreaker doesn't consider object
> correspondence).
Agreed, I wouldn't backport.
> Also I'm not 100% sure if I'm interpreting "both are direct members of
> the same class" correctly here to mean ruling out using'd vs non-using'd
> members, since https://eel.is/c++draft/namespace.udecl#note-5 says
> using'd members are "treated as though they were direct members of the
> derived class"...?
Looking back at the CWG wiki notes, I see that ruling out using vs
non-using was intended.
> +++ b/gcc/cp/call.cc
> @@ -12893,16 +12872,19 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, pmatch match_kind)
> tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
> tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
>
> + if (DECL_FUNCTION_MEMBER_P (fn1)
> + && DECL_FUNCTION_MEMBER_P (fn2))
> {
> + tree base1 = DECL_CONTEXT (strip_inheriting_ctors (fn1));
> + tree base2 = DECL_CONTEXT (strip_inheriting_ctors (fn2));
> + if (base1 != base2)
> + return false;
> +
> + /* CWG2789 is not adequate, it should specify corresponding object
> + parameters, not same typed object parameters. */
With this change, the difference is no longer significant; the comment
should change to something like
/* Use object_parms_correspond to simplify comparing iobj/xobj/static
member functions. */
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C
> @@ -20,12 +23,14 @@ struct S : B<> {
> constexpr operator int () const { return 10; }
> constexpr int g() { return 10; }
> constexpr int h(this S&&) { return 10; }
> + // { dg-warning "explicit object" "" { target c++20_only } .-1 }
> };
>
> -// implicit object parms match, B::f is more constrained
> -static_assert(S<>{}.f() == 5);
> -static_assert(S<>{}.g() == 5);
> -static_assert(S<>{}.h() == 5);
> +// ambiguous, constraints aren't considered since the candidates
> +// are defined from different classes
"defined in" or "come from"
OK with these two tweaks.
Jason
On Fri, 20 Sep 2024, Jason Merrill wrote:
> On 9/18/24 10:59 PM, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
> > look OK for trunk? I'm not sure this is worth backporting
> > without the previous CWG 2273 tweak since it'll mean inconsistent
> > behavior between implict vs explicit object members in GCC 14: the call
> > to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
> > 2273 tiebreaker incorrectly triggering), while the g() and h() calls
> > would be ambiguous (since that tiebreaker doesn't consider object
> > correspondence).
>
> Agreed, I wouldn't backport.
What do you think about enforcing this part of CWG 2789 only for
constructors in GCC 14? That would sidestep the inconsistency that
arises if we don't also backport the CWG 2273, and still fix the
testcase in the PR.
Like so?
-- >8 --
Subject: [PATCH GCC 14] c++: CWG 2789 and usings [PR116492]
For GCC 14, narrowly fix this PR by enforcing the unimplemented
- if they are member functions, both are direct members of the same
class, and
part of CWG 2789 for constructors only.
PR c++/116492
DR 2789
gcc/cp/ChangeLog:
* call.cc (cand_parms_match): Return false for constructors that
come from different classes.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
---
gcc/cp/call.cc | 4 ++++
.../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 ++++++++++++++++
2 files changed, 20 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 0f4eeeb5395..5c7aaa6dcf1 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12826,6 +12826,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, pmatch match_kind)
&& DECL_FUNCTION_MEMBER_P (fn2)))
/* Early escape. */;
+ else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
+ && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
+ != DECL_CONTEXT (strip_inheriting_ctors (fn2))))
+ return false;
/* CWG2789 is not adequate, it should specify corresponding object
parameters, not same typed object parameters. */
else if (!object_parms_correspond (c1, fn1, c2, fn2))
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
new file mode 100644
index 00000000000..3e5dbfc37ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
@@ -0,0 +1,16 @@
+// PR c++/116492
+// CWG 2789
+// { dg-do compile { target c++20 } }
+
+template<class T>
+struct A {
+ A() requires true = delete;
+};
+
+struct B : A<int> {
+ B();
+ using A<int>::A;
+};
+
+B b; // OK, selects the non-inherited constructor over the more constrained
+ // inherited constructor.
On 9/20/24 6:51 PM, Patrick Palka wrote:
> On Fri, 20 Sep 2024, Jason Merrill wrote:
>
>> On 9/18/24 10:59 PM, Patrick Palka wrote:
>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
>>> look OK for trunk? I'm not sure this is worth backporting
>>> without the previous CWG 2273 tweak since it'll mean inconsistent
>>> behavior between implict vs explicit object members in GCC 14: the call
>>> to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
>>> 2273 tiebreaker incorrectly triggering), while the g() and h() calls
>>> would be ambiguous (since that tiebreaker doesn't consider object
>>> correspondence).
>>
>> Agreed, I wouldn't backport.
>
> What do you think about enforcing this part of CWG 2789 only for
> constructors in GCC 14? That would sidestep the inconsistency that
> arises if we don't also backport the CWG 2273, and still fix the
> testcase in the PR.
>
> Like so?
That seems reasonable with a comment.
> -- >8 --
>
> Subject: [PATCH GCC 14] c++: CWG 2789 and usings [PR116492]
>
> For GCC 14, narrowly fix this PR by enforcing the unimplemented
>
> - if they are member functions, both are direct members of the same
> class, and
>
> part of CWG 2789 for constructors only.
>
> PR c++/116492
> DR 2789
>
> gcc/cp/ChangeLog:
>
> * call.cc (cand_parms_match): Return false for constructors that
> come from different classes.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
> ---
> gcc/cp/call.cc | 4 ++++
> .../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 ++++++++++++++++
> 2 files changed, 20 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
>
> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> index 0f4eeeb5395..5c7aaa6dcf1 100644
> --- a/gcc/cp/call.cc
> +++ b/gcc/cp/call.cc
> @@ -12826,6 +12826,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, pmatch match_kind)
> && DECL_FUNCTION_MEMBER_P (fn2)))
> /* Early escape. */;
>
> + else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
> + && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
> + != DECL_CONTEXT (strip_inheriting_ctors (fn2))))
> + return false;
> /* CWG2789 is not adequate, it should specify corresponding object
> parameters, not same typed object parameters. */
> else if (!object_parms_correspond (c1, fn1, c2, fn2))
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> new file mode 100644
> index 00000000000..3e5dbfc37ad
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> @@ -0,0 +1,16 @@
> +// PR c++/116492
> +// CWG 2789
> +// { dg-do compile { target c++20 } }
> +
> +template<class T>
> +struct A {
> + A() requires true = delete;
> +};
> +
> +struct B : A<int> {
> + B();
> + using A<int>::A;
> +};
> +
> +B b; // OK, selects the non-inherited constructor over the more constrained
> + // inherited constructor.
On Fri, 20 Sep 2024, Jason Merrill wrote:
> On 9/20/24 6:51 PM, Patrick Palka wrote:
> > On Fri, 20 Sep 2024, Jason Merrill wrote:
> >
> > > On 9/18/24 10:59 PM, Patrick Palka wrote:
> > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
> > > > look OK for trunk? I'm not sure this is worth backporting
> > > > without the previous CWG 2273 tweak since it'll mean inconsistent
> > > > behavior between implict vs explicit object members in GCC 14: the call
> > > > to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
> > > > 2273 tiebreaker incorrectly triggering), while the g() and h() calls
> > > > would be ambiguous (since that tiebreaker doesn't consider object
> > > > correspondence).
> > >
> > > Agreed, I wouldn't backport.
> >
> > What do you think about enforcing this part of CWG 2789 only for
> > constructors in GCC 14? That would sidestep the inconsistency that
> > arises if we don't also backport the CWG 2273, and still fix the
> > testcase in the PR.
> >
> > Like so?
>
> That seems reasonable with a comment.
Ack, does
/* This really really be checked for all member functions as per
CWG2789, but for GCC 14 we check this only for constructors since
without r15-3740 doing so would result in inconsistent handling
of object parameters (such as in concepts-memfun4.C). */
work?
>
> > -- >8 --
> >
> > Subject: [PATCH GCC 14] c++: CWG 2789 and usings [PR116492]
> >
> > For GCC 14, narrowly fix this PR by enforcing the unimplemented
> >
> > - if they are member functions, both are direct members of the same
> > class, and
> >
> > part of CWG 2789 for constructors only.
> >
> > PR c++/116492
> > DR 2789
> >
> > gcc/cp/ChangeLog:
> >
> > * call.cc (cand_parms_match): Return false for constructors that
> > come from different classes.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
> > ---
> > gcc/cp/call.cc | 4 ++++
> > .../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 ++++++++++++++++
> > 2 files changed, 20 insertions(+)
> > create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> >
> > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > index 0f4eeeb5395..5c7aaa6dcf1 100644
> > --- a/gcc/cp/call.cc
> > +++ b/gcc/cp/call.cc
> > @@ -12826,6 +12826,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2,
> > pmatch match_kind)
> > && DECL_FUNCTION_MEMBER_P (fn2)))
> > /* Early escape. */;
> > + else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
> > + && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
> > + != DECL_CONTEXT (strip_inheriting_ctors (fn2))))
> > + return false;
> > /* CWG2789 is not adequate, it should specify corresponding object
> > parameters, not same typed object parameters. */
> > else if (!object_parms_correspond (c1, fn1, c2, fn2))
> > diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> > b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> > new file mode 100644
> > index 00000000000..3e5dbfc37ad
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
> > @@ -0,0 +1,16 @@
> > +// PR c++/116492
> > +// CWG 2789
> > +// { dg-do compile { target c++20 } }
> > +
> > +template<class T>
> > +struct A {
> > + A() requires true = delete;
> > +};
> > +
> > +struct B : A<int> {
> > + B();
> > + using A<int>::A;
> > +};
> > +
> > +B b; // OK, selects the non-inherited constructor over the more constrained
> > + // inherited constructor.
>
>
On 9/20/24 7:34 PM, Patrick Palka wrote:
> On Fri, 20 Sep 2024, Jason Merrill wrote:
>
>> On 9/20/24 6:51 PM, Patrick Palka wrote:
>>> On Fri, 20 Sep 2024, Jason Merrill wrote:
>>>
>>>> On 9/18/24 10:59 PM, Patrick Palka wrote:
>>>>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
>>>>> look OK for trunk? I'm not sure this is worth backporting
>>>>> without the previous CWG 2273 tweak since it'll mean inconsistent
>>>>> behavior between implict vs explicit object members in GCC 14: the call
>>>>> to S<>{}.f() in concepts-memfun4.C would now return 10 (due to the CWG
>>>>> 2273 tiebreaker incorrectly triggering), while the g() and h() calls
>>>>> would be ambiguous (since that tiebreaker doesn't consider object
>>>>> correspondence).
>>>>
>>>> Agreed, I wouldn't backport.
>>>
>>> What do you think about enforcing this part of CWG 2789 only for
>>> constructors in GCC 14? That would sidestep the inconsistency that
>>> arises if we don't also backport the CWG 2273, and still fix the
>>> testcase in the PR.
>>>
>>> Like so?
>>
>> That seems reasonable with a comment.
>
> Ack, does
>
> /* This really really be checked for all member functions as per
> CWG2789, but for GCC 14 we check this only for constructors since
> without r15-3740 doing so would result in inconsistent handling
> of object parameters (such as in concepts-memfun4.C). */
>
> work?
With "really really" fixed, yes.
>>> -- >8 --
>>>
>>> Subject: [PATCH GCC 14] c++: CWG 2789 and usings [PR116492]
>>>
>>> For GCC 14, narrowly fix this PR by enforcing the unimplemented
>>>
>>> - if they are member functions, both are direct members of the same
>>> class, and
>>>
>>> part of CWG 2789 for constructors only.
>>>
>>> PR c++/116492
>>> DR 2789
>>>
>>> gcc/cp/ChangeLog:
>>>
>>> * call.cc (cand_parms_match): Return false for constructors that
>>> come from different classes.
>>>
>>> gcc/testsuite/ChangeLog:
>>>
>>> * g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.
>>> ---
>>> gcc/cp/call.cc | 4 ++++
>>> .../g++.dg/cpp2a/concepts-inherit-ctor12.C | 16 ++++++++++++++++
>>> 2 files changed, 20 insertions(+)
>>> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
>>>
>>> diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
>>> index 0f4eeeb5395..5c7aaa6dcf1 100644
>>> --- a/gcc/cp/call.cc
>>> +++ b/gcc/cp/call.cc
>>> @@ -12826,6 +12826,10 @@ cand_parms_match (z_candidate *c1, z_candidate *c2,
>>> pmatch match_kind)
>>> && DECL_FUNCTION_MEMBER_P (fn2)))
>>> /* Early escape. */;
>>> + else if ((DECL_INHERITED_CTOR (fn1) || DECL_INHERITED_CTOR (fn2))
>>> + && (DECL_CONTEXT (strip_inheriting_ctors (fn1))
>>> + != DECL_CONTEXT (strip_inheriting_ctors (fn2))))
>>> + return false;
>>> /* CWG2789 is not adequate, it should specify corresponding object
>>> parameters, not same typed object parameters. */
>>> else if (!object_parms_correspond (c1, fn1, c2, fn2))
>>> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
>>> b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
>>> new file mode 100644
>>> index 00000000000..3e5dbfc37ad
>>> --- /dev/null
>>> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-inherit-ctor12.C
>>> @@ -0,0 +1,16 @@
>>> +// PR c++/116492
>>> +// CWG 2789
>>> +// { dg-do compile { target c++20 } }
>>> +
>>> +template<class T>
>>> +struct A {
>>> + A() requires true = delete;
>>> +};
>>> +
>>> +struct B : A<int> {
>>> + B();
>>> + using A<int>::A;
>>> +};
>>> +
>>> +B b; // OK, selects the non-inherited constructor over the more constrained
>>> + // inherited constructor.
>>
>>
>
@@ -12808,27 +12808,6 @@ class_of_implicit_object (z_candidate *cand)
return BINFO_TYPE (cand->conversion_path);
}
-/* True if candidates C1 and C2 have corresponding object parameters per
- [basic.scope.scope]. */
-
-static bool
-object_parms_correspond (z_candidate *c1, tree fn1, z_candidate *c2, tree fn2)
-{
- tree context = class_of_implicit_object (c1);
- tree ctx2 = class_of_implicit_object (c2);
- if (!ctx2)
- /* Leave context as is. */;
- else if (!context)
- context = ctx2;
- else if (context != ctx2)
- /* This can't happen for normal function calls, since it means finding
- functions in multiple bases which would fail with an ambiguous lookup,
- but it can occur with reversed operators. */
- return false;
-
- return object_parms_correspond (fn1, fn2, context);
-}
-
/* Return whether the first parameter of C1 matches the second parameter
of C2. */
@@ -12893,16 +12872,19 @@ cand_parms_match (z_candidate *c1, z_candidate *c2, pmatch match_kind)
tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn1));
tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (fn2));
- if (!(DECL_FUNCTION_MEMBER_P (fn1)
- && DECL_FUNCTION_MEMBER_P (fn2)))
- /* Early escape. */;
-
- /* CWG2789 is not adequate, it should specify corresponding object
- parameters, not same typed object parameters. */
- else if (!object_parms_correspond (c1, fn1, c2, fn2))
- return false;
- else
+ if (DECL_FUNCTION_MEMBER_P (fn1)
+ && DECL_FUNCTION_MEMBER_P (fn2))
{
+ tree base1 = DECL_CONTEXT (strip_inheriting_ctors (fn1));
+ tree base2 = DECL_CONTEXT (strip_inheriting_ctors (fn2));
+ if (base1 != base2)
+ return false;
+
+ /* CWG2789 is not adequate, it should specify corresponding object
+ parameters, not same typed object parameters. */
+ if (!object_parms_correspond (fn1, fn2, base1))
+ return false;
+
/* We just compared the object parameters, if they don't correspond
we already returned false. */
auto skip_parms = [] (tree fn, tree parms)
@@ -13269,10 +13251,14 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
return winner;
}
- /* Concepts: F1 and F2 are non-template functions with the same
- parameter-type-lists, and F1 is more constrained than F2 according to the
- partial ordering of constraints described in 13.5.4. */
-
+ /* F1 and F2 are non-template functions and
+ - they have the same non-object-parameter-type-lists ([dcl.fct]), and
+ - if they are member functions, both are direct members of the same
+ class, and
+ - if both are non-static member functions, they have the same types for
+ their object parameters, and
+ - F1 is more constrained than F2 according to the partial ordering of
+ constraints described in [temp.constr.order]. */
if (flag_concepts && DECL_P (cand1->fn) && DECL_P (cand2->fn)
&& !cand1->template_decl && !cand2->template_decl
&& cand_parms_match (cand1, cand2, pmatch::current))
new file mode 100644
@@ -0,0 +1,16 @@
+// PR c++/116492
+// CWG 2789
+// { dg-do compile { target c++20 } }
+
+template<class T>
+struct A {
+ A() requires true = delete;
+};
+
+struct B : A<int> {
+ B();
+ using A<int>::A;
+};
+
+B b; // OK, selects the non-inherited constructor over the more constrained
+ // inherited constructor.
@@ -1,5 +1,7 @@
// PR c++/113191
-// { dg-do compile { target c++23 } }
+// CWG 2789
+// { dg-do compile { target c++20 } }
+// { dg-additional-options "-Wno-error=c++23-extensions" { target c++20_only } }
template<typename> struct S;
@@ -8,6 +10,7 @@ struct B {
constexpr int f() const requires true { return 5; }
constexpr operator int () const requires true { return 5; }
constexpr int g(this S<T>&&) requires true { return 5; }
+ // { dg-warning "explicit object" "" { target c++20_only } .-1 }
constexpr int h() requires true { return 5; }
};
@@ -20,12 +23,14 @@ struct S : B<> {
constexpr operator int () const { return 10; }
constexpr int g() { return 10; }
constexpr int h(this S&&) { return 10; }
+ // { dg-warning "explicit object" "" { target c++20_only } .-1 }
};
-// implicit object parms match, B::f is more constrained
-static_assert(S<>{}.f() == 5);
-static_assert(S<>{}.g() == 5);
-static_assert(S<>{}.h() == 5);
+// ambiguous, constraints aren't considered since the candidates
+// are defined from different classes
+static_assert(S<>{}.f() == 5); // { dg-error "ambiguous" }
+static_assert(S<>{}.g() == 5); // { dg-error "ambiguous" }
+static_assert(S<>{}.h() == 5); // { dg-error "ambiguous" }
template <typename = void>
struct C {
@@ -36,9 +41,8 @@ struct C {
template <typename = void>
struct S2: B<>, C<> { };
-// implicit object parms for conversion functions are all considered to be from
-// the class of the object argument
-static_assert(S2<>{} == 5);
+// ambiguous as above
+static_assert(S2<>{} == 5); // { dg-error "ambiguous" }
// ambiguous lookup, so we never actually compare the candidates
// if we did, implicit object parms don't match due to different classes
@@ -51,7 +55,6 @@ struct S3 : B<> {
constexpr int f() volatile { return 10; }
};
-// implicit object parms don't match due to different cv-quals
static_assert(S3<>{}.f() == 5); // { dg-error "ambiguous" }
template <typename = void>
@@ -60,8 +63,7 @@ struct S4 : B<> {
constexpr int f() const & { return 10; }
};
-// no ref-qual matches any ref-qual
-static_assert(S4<>{}.f() == 5);
+static_assert(S4<>{}.f() == 5); // { dg-error "ambiguous" }
template <typename = void>
struct C2 {