public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden
@ 2024-08-26 22:17 mail at johslarsen dot net
  2024-08-26 22:30 ` [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass pinskia at gcc dot gnu.org
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: mail at johslarsen dot net @ 2024-08-26 22:17 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

            Bug ID: 116492
           Summary: inherited constructors in subclass of std::expected
                    can not be overridden
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mail at johslarsen dot net
  Target Milestone: ---

Created attachment 59007
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=59007&action=edit
preprocessed file

First of all, sorry I subclassed the standard library, and yes, I am perfectly
aware that this is a very bad practice. As such the important part might not be
a fix for this in particular, but that it could shed light on similar problems
elsewhere

The following code snippet compiled with gcc 12.1 (first with std::expected on
godbolt) through 14.2 (and trunk) constructs obj by calling std::expected's
constructor directly instead of the constructor defined in my_expected:

    #include <expected>

    class my_expected : public std::expected<int, const char*> {
    public:
        my_expected() : std::expected<int, const char*>::expected(42) {}
        using std::expected<int, const char*>::expected;
    };

    int main() {
        my_expected obj;
        return *obj != 42;
    }

Resulting in *obj being zero (instead of 42), and a non-zero exit value.

This only happens with the using statement, but as far as I understand the C++
documentation the derived constructor should have been used instead:

> [...] if an inherited constructor matches the signature of one of the constructors
> of Derived, it is hidden from lookup by the version found in Derived.
> https://en.cppreference.com/w/cpp/language/using_declaration

The same does not happen in clang, and in gcc with similar examples from other
classes I have tried. g++ returns no errors or warnings with -Wall -Wextra and
all the other flags you suggested. The attached preprocessed file was generated
with g++ 14.2.1 20240805

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
@ 2024-08-26 22:30 ` pinskia at gcc dot gnu.org
  2024-08-26 22:33 ` pinskia at gcc dot gnu.org
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-08-26 22:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2024-08-26
            Summary|inherited constructors in   |inherited constructors with
                   |subclass of std::expected   |concept in subclass
                   |can not be overridden       |overrides constructor in
                   |                            |subclass
             Blocks|                            |67491
             Status|UNCONFIRMED                 |NEW
           Keywords|                            |wrong-code
     Ever confirmed|0                           |1

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Slightly reduced:
```
template <class T>
concept true_c = true;

 template <class T>
    struct expected
    {
      T a;
      bool hasvalue;
      constexpr expected(T a1) : a(a1), hasvalue(true){}
      constexpr expected()
      requires true_c<T>
      : a(), hasvalue(true){}
      expected(expected&&) = default;
      T &operator*()
      {
        if (!hasvalue) throw 1;
        return a;
      }
    };

    class my_expected : public expected<int> {
    public:
        using expected<int>::expected;
        my_expected() : expected<int>::expected(42) {}
    };

    int main() {
        my_expected obj;
        return *obj != 42;
    }
```


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67491
[Bug 67491] [meta-bug] concepts issues

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
  2024-08-26 22:30 ` [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass pinskia at gcc dot gnu.org
@ 2024-08-26 22:33 ` pinskia at gcc dot gnu.org
  2024-08-26 22:35 ` pinskia at gcc dot gnu.org
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-08-26 22:33 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
>The same does not happen in clang, and in gcc with similar examples from other classes I have tried.

So it comes down to the concept on the constructor which is why you didn't run
into similar examples from other classes.  std::expected has requires
statements on the constructors in some cases.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
  2024-08-26 22:30 ` [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass pinskia at gcc dot gnu.org
  2024-08-26 22:33 ` pinskia at gcc dot gnu.org
@ 2024-08-26 22:35 ` pinskia at gcc dot gnu.org
  2024-09-04 18:45 ` ppalka at gcc dot gnu.org
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-08-26 22:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

--- Comment #3 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #1)
> Slightly reduced:

In this example if you comment out:
```
requires true_c<T>
```

GCC does the correct thing.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
                   ` (2 preceding siblings ...)
  2024-08-26 22:35 ` pinskia at gcc dot gnu.org
@ 2024-09-04 18:45 ` ppalka at gcc dot gnu.org
  2024-09-17 15:17 ` ppalka at gcc dot gnu.org
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-09-04 18:45 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jason at gcc dot gnu.org,
                   |                            |ppalka at gcc dot gnu.org
              Alias|                            |cwg2789

--- Comment #4 from Patrick Palka <ppalka at gcc dot gnu.org> ---
More reduced:

template<class T>
struct A {
  A() requires true = delete; // #1
};

struct B : A<int> {
  using A<int>::A;
  B(); // #2
};

B b; // GCC and Clang-17 select #1, MSVC/Clang-18 select #2

This seems to be a recent behavior change in the standard,
https://wg21.link/cwg2789, which GCC doesn't fully implement, in particular the

  ...
  if they are member functions, both are direct members of the same class, and
  ...

part.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
                   ` (3 preceding siblings ...)
  2024-09-04 18:45 ` ppalka at gcc dot gnu.org
@ 2024-09-17 15:17 ` ppalka at gcc dot gnu.org
  2024-09-20 16:34 ` cvs-commit at gcc dot gnu.org
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-09-17 15:17 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=113191

--- Comment #5 from Patrick Palka <ppalka at gcc dot gnu.org> ---
I tried implementing the missing inherited vs non-inherited check from CWG2789
in cand_parms_match which fixes this testcase but it causes concepts-memfun4.C
(added by r14-7157) to regress with excess errors.  The new errors/behavior
seem correct to me, so I must be missing something...

Before/after diff of concepts-memfun4.C:

@@ -1,3 +1,34 @@
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:26:25: error: static assertion
failed
+   26 | static_assert(S<>{}.f() == 5);
+      |               ~~~~~~~~~~^~~~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:26:25: note: the comparison
reduces to ‘(10 == 5)’
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:27:22: error: call of overloaded
‘g()’ is ambiguous
+   27 | static_assert(S<>{}.g() == 5);
+      |               ~~~~~~~^~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:10:17: note: candidate:
‘constexpr int B<T>::g(this S<T>&&) requires  true [with T = void]’
+   10 |   constexpr int g(this S<T>&&) requires true { return 5; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:21:17: note: candidate:
‘constexpr int S< <template-parameter-1-1> >::g() [with
<template-parameter-1-1> = void]’
+   21 |   constexpr int g() { return 10; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:28:22: error: call of overloaded
‘h()’ is ambiguous
+   28 | static_assert(S<>{}.h() == 5);
+      |               ~~~~~~~^~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:11:17: note: candidate:
‘constexpr int B<T>::h() requires  true [with T = void]’
+   11 |   constexpr int h() requires true { return 5; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:22:17: note: candidate:
‘constexpr int S< <template-parameter-1-1> >::h(this S<
<template-parameter-1-1> >&&) [with <template-parameter-1-1> = void]’
+   22 |   constexpr int h(this S&&) { return 10; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:41:15: error: conversion from
‘S2<>’ to ‘int’ is ambiguous
+   41 | static_assert(S2<>{} == 5);
+      |               ^~~~~~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:33:13: note: candidate:
‘constexpr C< <template-parameter-1-1> >::operator int() const [with
<template-parameter-1-1> = void]’
+   33 |   constexpr operator int () const { return 15; }
+      |             ^~~~~~~~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:9:13: note: candidate:
‘constexpr B<T>::operator int() const requires  true [with T = void]’
+    9 |   constexpr operator int () const requires true { return 5; }
+      |             ^~~~~~~~
 gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:46:22: error: request for member
‘f’ is ambiguous
    46 | static_assert(S2<>{}.f() == 5); // { dg-error "ambiguous" }
       |                      ^
@@ -16,6 +47,19 @@ gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:8:17: note:
candidate: ‘constexp
 gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:51:17: note: candidate:
‘constexpr int S3< <template-parameter-1-1> >::f() volatile [with
<template-parameter-1-1> = void]’
    51 |   constexpr int f() volatile { return 10; }
       |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:64:23: warning: ISO C++ says
that these are ambiguous, even though the worst conversion for the first is
better than the worst conversion for the second:
+   64 | static_assert(S4<>{}.f() == 5);
+      |               ~~~~~~~~^~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:60:17: note: candidate 1:
‘constexpr int S4< <template-parameter-1-1> >::f() const & [with
<template-parameter-1-1> = void]’
+   60 |   constexpr int f() const & { return 10; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:8:17: note: candidate 2:
‘constexpr int B<T>::f() const requires  true [with T = void]’
+    8 |   constexpr int f() const requires true { return 5; }
+      |                 ^
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:64:26: error: static assertion
failed
+   64 | static_assert(S4<>{}.f() == 5);
+      |               ~~~~~~~~~~~^~~~
+gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:64:26: note: the comparison
reduces to ‘(10 == 5)’
 gcc/testsuite/g++.dg/cpp2a/concepts-memfun4.C:75:15: error: conversion from
‘S5<>’ to ‘int’ is ambiguous
    75 | static_assert(S5<>{} == 5);     // { dg-error "ambiguous" }
       |               ^~~~~~

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
                   ` (4 preceding siblings ...)
  2024-09-17 15:17 ` ppalka at gcc dot gnu.org
@ 2024-09-20 16:34 ` cvs-commit at gcc dot gnu.org
  2024-09-20 21:37 ` cvs-commit at gcc dot gnu.org
  2024-09-20 21:38 ` ppalka at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2024-09-20 16:34 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:ee3efe06c9c49c04eaa4e195a7ae8774a1b3faa2

commit r15-3741-gee3efe06c9c49c04eaa4e195a7ae8774a1b3faa2
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Sep 20 12:33:13 2024 -0400

    c++: CWG 2789 and usings [PR116492]

    After CWG 2789, the "more constrained" tiebreaker for non-template
    functions should exclude member functions that are defined in
    different classes.  This patch implements this missing refinement.

    In turn we can get rid of four-parameter version of object_parms_correspond
    and call the main overload directly since now correspondence is only
    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: Also compile in C++20 mode.
            Expect ambiguity when candidates come from different classes.
            * g++.dg/cpp2a/concepts-inherit-ctor12.C: New test.

    Reviewed-by: Jason Merrill <jason@redhat.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
                   ` (5 preceding siblings ...)
  2024-09-20 16:34 ` cvs-commit at gcc dot gnu.org
@ 2024-09-20 21:37 ` cvs-commit at gcc dot gnu.org
  2024-09-20 21:38 ` ppalka at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2024-09-20 21:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-14 branch has been updated by Patrick Palka
<ppalka@gcc.gnu.org>:

https://gcc.gnu.org/g:659f32ea9de57661f8a37dcfb0b9a01bfe29acce

commit r14-10696-g659f32ea9de57661f8a37dcfb0b9a01bfe29acce
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Sep 20 17:37:03 2024 -0400

    c++: CWG 2789 and usings [PR116492]

    For GCC 14, narrowly fix this PR by implementing the missing

      - 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.

    Reviewed-by: Jason Merrill <jason@redhat.com>

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass
  2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
                   ` (6 preceding siblings ...)
  2024-09-20 21:37 ` cvs-commit at gcc dot gnu.org
@ 2024-09-20 21:38 ` ppalka at gcc dot gnu.org
  7 siblings, 0 replies; 9+ messages in thread
From: ppalka at gcc dot gnu.org @ 2024-09-20 21:38 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116492

Patrick Palka <ppalka at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Target Milestone|---                         |14.3
         Resolution|---                         |FIXED
             Status|NEW                         |RESOLVED
           Assignee|unassigned at gcc dot gnu.org      |ppalka at gcc dot gnu.org

--- Comment #8 from Patrick Palka <ppalka at gcc dot gnu.org> ---
Narrowly fixed for GCC 14.3, fully fixed GCC 15, thanks for the bug report.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-09-20 21:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-26 22:17 [Bug c++/116492] New: inherited constructors in subclass of std::expected can not be overridden mail at johslarsen dot net
2024-08-26 22:30 ` [Bug c++/116492] inherited constructors with concept in subclass overrides constructor in subclass pinskia at gcc dot gnu.org
2024-08-26 22:33 ` pinskia at gcc dot gnu.org
2024-08-26 22:35 ` pinskia at gcc dot gnu.org
2024-09-04 18:45 ` ppalka at gcc dot gnu.org
2024-09-17 15:17 ` ppalka at gcc dot gnu.org
2024-09-20 16:34 ` cvs-commit at gcc dot gnu.org
2024-09-20 21:37 ` cvs-commit at gcc dot gnu.org
2024-09-20 21:38 ` ppalka at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).