Bug 98642 - [10 Regression] wrong "use of deleted function" error
Summary: [10 Regression] wrong "use of deleted function" error
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P1 normal
Target Milestone: 10.3
Assignee: Jason Merrill
URL:
Keywords: rejects-valid
Depends on:
Blocks: 90254 93711
  Show dependency treegraph
 
Reported: 2021-01-12 19:51 UTC by Marek Polacek
Modified: 2021-03-29 11:19 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 10.2.0, 11.0
Known to fail: 10.2.1
Last reconfirmed: 2021-01-12 00:00:00


Attachments
possible patch to elide more copies (2.66 KB, patch)
2021-01-15 19:12 UTC, Jason Merrill
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2021-01-12 19:51:17 UTC
class base {
public:
  base(void) {};
  base(base &&) = delete;
};

class foo : public base {
};

template<typename C>
inline C &bar(void)
{
  static C c{};
  return c;
}

const foo &baz(void)
{
  return bar<const foo>();
}

is rejected since r11-2704 in C++17.  clang++/EDG accept this.
Comment 1 Marek Polacek 2021-01-12 19:56:08 UTC
$ ./cc1plus -quiet 98642.C
98642.C: In instantiation of ‘C& bar() [with C = const foo]’:
98642.C:19:25:   required from here
98642.C:13:12: error: use of deleted function ‘base::base(base&&)’
   13 |   static C c{};
      |            ^
98642.C:4:3: note: declared here
    4 |   base(base &&) = delete;
      |   ^~~~
Comment 2 GCC Commits 2021-01-15 18:57:19 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

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

commit r11-6736-gd75199f782348bfc401f925b60f33ffc9822b7cc
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 13 13:27:06 2021 -0500

    c++: Avoid redundant copy in {} init [PR98642]
    
    Here, initializing from { } implies a call to the default constructor for
    base.  We were then seeing that we're initializing a base subobject, so we
    tried to copy the result of that call.  This is clearly wrong; we should
    initialize the base directly from its default constructor.
    
    This patch does a lot of refactoring of unsafe_copy_elision_p and adds
    make_safe_copy_elision that will also try to do the base constructor
    rewriting from the last patch.
    
    gcc/cp/ChangeLog:
    
            PR c++/98642
            * call.c (unsafe_return_slot_p): Return int.
            (init_by_return_slot_p): Split out from...
            (unsafe_copy_elision_p): ...here.
            (unsafe_copy_elision_p_opt): New name for old meaning.
            (build_over_call): Adjust.
            (make_safe_copy_elision): New.
            * typeck2.c (split_nonconstant_init_1): Elide copy from safe
            list-initialization.
            * cp-tree.h: Adjust.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/98642
            * g++.dg/cpp1z/elide5.C: New test.
Comment 3 Jason Merrill 2021-01-15 19:12:59 UTC
Created attachment 49977 [details]
possible patch to elide more copies

This implements a suggestion I made in https://github.com/itanium-cxx-abi/cxx-abi/issues/107
Comment 4 Richard Biener 2021-01-27 09:34:18 UTC
Confirmed it broke on the GCC 10 branch after the GCC 10.2 release which worked,
thus indeed P1 but only is rejected with -std=c++17 not with the default -std
level.

What broke it on the branch?  (maybe reversion is a better fix there?)
Comment 5 Richard Biener 2021-01-27 09:36:57 UTC
So obviously that was

2020-12-23  Jason Merrill  <jason@redhat.com>

        PR c++/90254
        PR c++/93711
        * cp-tree.h (unsafe_return_slot_p): Declare.
        * call.c (is_base_field_ref): Rename to unsafe_return_slot_p.
        (build_over_call): Check unsafe_return_slot_p.
        (build_special_member_call): Likewise.
        * init.c (expand_default_init): Likewise.
        * typeck2.c (split_nonconstant_init_1): Likewise.
Comment 6 GCC Commits 2021-01-29 16:00:40 UTC
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:506fcfdb12562e829448e2b2eff475c65986e26b

commit r10-9312-g506fcfdb12562e829448e2b2eff475c65986e26b
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 13 13:27:06 2021 -0500

    c++: Avoid redundant copy in {} init [PR98642]
    
    Here, initializing from { } implies a call to the default constructor for
    base.  We were then seeing that we're initializing a base subobject, so we
    tried to copy the result of that call.  This is clearly wrong; we should
    initialize the base directly from its default constructor.
    
    gcc/cp/ChangeLog:
    
            PR c++/98642
            * typeck2.c (split_nonconstant_init_1): Don't copy a list-init
            constructor call.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/98642
            * g++.dg/cpp1z/elide5.C: New test.
Comment 7 Jakub Jelinek 2021-03-19 13:21:26 UTC
So is this now fixed even for 10.3?
Comment 8 Richard Biener 2021-03-29 11:19:08 UTC
The reported testcase is now accepted.