Bug 25950 - [DR 391] Reference binding and explicit copy constructors
Summary: [DR 391] Reference binding and explicit copy constructors
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.1
: P2 enhancement
Target Milestone: 4.3.0
Assignee: Jason Merrill
URL:
Keywords:
: 12226 27295 28365 28846 30959 31156 36490 (view as bug list)
Depends on: 12226
Blocks:
  Show dependency treegraph
 
Reported: 2006-01-24 22:23 UTC by Howard Hinnant
Modified: 2018-03-12 22:25 UTC (History)
12 users (show)

See Also:
Host:
Target:
Build:
Known to work: 3.3.3 3.2.3 2.95.3 3.0.4 4.3.0
Known to fail: 3.4.0 4.0.0 4.1.0
Last reconfirmed: 2007-10-22 19:14:21


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Howard Hinnant 2006-01-24 22:23:59 UTC
Consider:

   struct X {
      X();
      explicit X(const X&);
   };

void f(X);
void g(const X&);

int main()
{
    X x;
    f(x);
    f(X());
    g(x);
    g(X());
}

We currently give errors for f(x), f(X()) and g(X()), but not g(x).  This is not quite the behavior of EDG which allows g(X()).

There are (at least) two pertinent cwg defect reports:  152 and 391.  152 has TC1 status (it is normative) and clarifies the behavior for f(), and is consistent with the bevavior of both gcc and EDG.  Issue 391 addresses g() and (I believe) explains the discrepancy between gcc and EDG by specifying that X() will bind directly to the reference parameter of g() with no copy.

This issue has been voted on in full committee and approved as a dr.  However the next available time to make anything normative is C++0X.  So 391 has been applied to the working draft, and EDG has apparently implemented it.

I respectfully request that gcc implement it as well.  The issue is non-controversial on the committee and is causing problems with client code today.
Comment 1 Andrew Pinski 2006-01-24 22:38:48 UTC
I am going to mark this depending on PR 12226 for a second since that is the PR 12226 which made promoted this change.
Comment 2 Andrew Pinski 2006-01-24 22:48:50 UTC
I am going to mark this a regression but not confirm it because I don't understand this issue fully and this seems like someone else who knows better about this should do that.

CCing Mark as he did the change for PR 12226.

Adding the URL for the DR report for lazy people (me):
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#391
Comment 3 Howard Hinnant 2006-01-24 22:51:13 UTC
More information:

I now believe I unknowingly misled when I surmized that EDG had implemented cwg 391.  If you declare the copy ctor private in the example, EDG rejects g(X()) based on accessibility.  Rather I am now surmizing that there is wiggle room in 8.5.3 to allow EDG's behavior.  More specifically, EDG is choosing this bullet:

*  The reference is bound to the object represented by the rvalue (see basic.lval) or to a sub-object within that object.

And (I'm still guessing) this choice requires access checking of the copy ctor, but does not require an implicit copy ctor.  Sorry my initial post wasn't more clear.  This is a confusing area to me.
Comment 4 gdr@cs.tamu.edu 2006-01-25 01:32:39 UTC
Subject: Re:  [3.4/4.0/4.1 Regression] [DR 391] Reference binding and explicit copy constructors

"pinskia at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| I am going to mark this a regression but not confirm it because I don't

before you declare something as a regression, please make sure you do
understand the real issues.  When you don't fully understand, please
leave it alone and help somewhere else.  Thanks.

-- Gaby
Comment 5 Andrew Pinski 2006-01-25 01:55:44 UTC
(In reply to comment #4)
> before you declare something as a regression, please make sure you do
> understand the real issues.  When you don't fully understand, please
> leave it alone and help somewhere else.  Thanks.

Well Marking things as regression is easy as it is just easy to test it on different versions of GCC which I did.  Now figuring out what we should do here is not up to me which is why I did not confirm it.  Now I read the DR and the standard (well I did read it for the bug linked here) but it seems like the DR only resolves one part of the question but it seems raise differnet questions for me which is why I left it unconfirmed.  Should have I written this first, maybe but then again you would have harped on me anyways.  If you noticed I gave some back ground info on when the change happened and CCed the person who changed it to get a clarification (in fact I said that in comment #2).  I linked to the DR report so that people could easier access to it instead of remembering the link each time when comming to this bug.  (and now this whole thing is offtopic from the bug report).

Comment 6 Howard Hinnant 2006-01-25 02:05:24 UTC
At the risk of continuing off-topic...

Thank you Andrew for your continuing prompt and high quality work.  It is a very valuable service and I've never had any complaints with the way you provide it.  Good Job and Thank You!
Comment 7 gdr@cs.tamu.edu 2006-01-25 02:38:28 UTC
Subject: Re:  [3.4/4.0/4.1 Regression] [DR 391] Reference binding and explicit copy constructors

"pinskia at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| (In reply to comment #4)
| > before you declare something as a regression, please make sure you do
| > understand the real issues.  When you don't fully understand, please
| > leave it alone and help somewhere else.  Thanks.
| 
| Well Marking things as regression is easy as it is just easy to test it on
| different versions of GCC which I did.

No, it is not that simple.
For example consider access checking (which this issue is about).  For
a long time, GCC has been known to be buggy on access checking,
therefore *wrongly* accepting codes it should reject (for example is
the PR you referenced.)  That was fixed by checking the accessibility
of the copy constructor even  when it is elided (as required by the
C++ standard). 

The C++ Working Paper has been slightly changed recently -- but not
the C++ standard -- to be somehow more permissisive in specific cases.
This PR is based on the hypothesis that the working paper stays as it
is on that point till we get the standard.
The proper categorization is that this is a request for enhancement. 

-- Gaby
Comment 8 Gabriel Dos Reis 2006-01-25 02:41:25 UTC
Changing to request for enhancement.  The requested behaviour is a change
in th working paper.  Existing behaviour is what is required by the standard
(even when it can be argued that checking for something that is elided is
suboptimal.)
Comment 9 Howard Hinnant 2006-01-25 02:54:22 UTC
(In reply to comment #8)
> Changing to request for enhancement.  The requested behaviour is a change
> in th working paper.  Existing behaviour is what is required by the standard
> (even when it can be argued that checking for something that is elided is
> suboptimal.)

Did you read comment 3? 

Comment 10 Andrew Pinski 2006-01-25 03:03:06 UTC
So this really just DR 152 and has nothing to do with DR 391 except misleading us.  DR 152 is TR1 so it is part of the standard, therefor this is still a regression and should be marked as normal severity.
Comment 11 gdr@cs.tamu.edu 2006-01-25 03:09:52 UTC
Subject: Re:  [3.4/4.0/4.1] [DR 391] Reference binding and explicit copy constructors

"hhinnant at apple dot com" <gcc-bugzilla@gcc.gnu.org> writes:

| ------- Comment #9 from hhinnant at apple dot com  2006-01-25 02:54 -------
| (In reply to comment #8)
| > Changing to request for enhancement.  The requested behaviour is a change
| > in th working paper.  Existing behaviour is what is required by the standard
| > (even when it can be argued that checking for something that is elided is
| > suboptimal.)
| 
| Did you read comment 3? 

Yes.  Is your claim that whether the copy constructor is converting or
not does not matter? 

-- Gaby
Comment 12 gdr@cs.tamu.edu 2006-01-25 03:20:11 UTC
Subject: Re:  [3.4/4.0/4.1 Regression] [DR 152] Reference binding and explicit copy constructors

"pinskia at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| So this really just DR 152

No!

DR 152 is about what happens when you pass an argument by value and
the copy-constructor happens to be explicit.  DR 152 says that well,
you loose -- the copy-constructor is a converting constructor and if
it is explicit, then the pass-by-value fails.  Read the last sentence
of bullet 1 and bullet 2 carefully.

| and has nothing to do with DR 391 except misleading us.

It is exactly the opposite.  DR 152 is a distraction.
The PR is about 

| DR 152 is TR1

if it were TR1, it would not have been the C++ standard.  It is TC1,
but again this issue is NOT about DR 152.  It is about DR 391 and
and related aspect.

-- Gaby
Comment 13 Howard Hinnant 2006-01-25 03:24:44 UTC
(In reply to comment #11)
> | Did you read comment 3? 
> 
> Yes.  Is your claim that whether the copy constructor is converting or
> not does not matter? 

No.  My suspicion is that there is a 99.99% chance that EDG is conforming to C++03 in this regard.  And furthermore, their behavior (which is different from ours) is preferable to our customers.
Comment 14 Gabriel Dos Reis 2006-01-25 03:28:11 UTC
DR 391, not 392.  My typo.
Comment 15 Andrew Pinski 2006-01-25 03:34:57 UTC
Actually DR 152 clarifies that this is invalid code. as Per 8.5/12 this is copy-initialization.
Comment 16 gdr@cs.tamu.edu 2006-01-25 03:40:56 UTC
Subject: Re:  [3.4/4.0/4.1] [DR 392] Reference binding and explicit copy constructors

"hhinnant at apple dot com" <gcc-bugzilla@gcc.gnu.org> writes:

| (In reply to comment #11)
| > | Did you read comment 3? 
| > 
| > Yes.  Is your claim that whether the copy constructor is converting or
| > not does not matter? 
| 
| No.  My suspicion is that there is a 99.99% chance that EDG is conforming to
| C++03 in this regard.

Further investigation reveals this:  If an implementation chooses the
second bullet (where it elects to copy the temporary to another
temporary) what is the semantics?  Is it copy-initialization as
everywhere else in argument pass-by-value?  Or is it 
direct-initialization?  That is what my question meant.  GCC always
uses copy-initialization in function argument passing, except when the
parameter directly binds, i.e. no temporary is needed.

| And furthermore, their behavior (which is different from
| ours) is preferable to our customers.

I think I know where this PR comes from (move semantics simulation
anyone? :-).  My main objection is classifying it as regression.  The
issue would deserve a DR if we did not already have 391.

-- Gaby
Comment 17 Mark Mitchell 2006-01-25 06:46:00 UTC
This is certainly not a P1 for 4.1.  If it's a bug (it probably is, but I still want to think about it more), it's a minor one, in the grand scheme of things.
Comment 18 gdr@cs.tamu.edu 2006-01-25 15:51:48 UTC
Subject: Re:  [3.4/4.0/4.1] [DR 391] Reference binding and explicit copy constructors

"mmitchel at gcc dot gnu dot org" <gcc-bugzilla@gcc.gnu.org> writes:

| This is certainly not a P1 for 4.1.  If it's a bug (it probably is, but I still
| want to think about it more), it's a minor one, in the grand scheme of things.

Howard raised the issue on the -core reflector.  See c++std-core-11265
when Mike expessed the same opinion as me in previous comments.  It is
ill-formed in C++03 (GCC behaviour is correct).  However, it is no
longer the same behaviour after the last changes voted in the working
paper.

-- Gaby
Comment 19 Mark Mitchell 2006-02-24 00:26:46 UTC
This issue will not be resolved in GCC 4.1.0; retargeted at GCC 4.1.1.
Comment 20 Andrew Pinski 2006-04-05 07:10:16 UTC
*** Bug 12226 has been marked as a duplicate of this bug. ***
Comment 21 Andrew Pinski 2006-04-24 23:37:17 UTC
*** Bug 27295 has been marked as a duplicate of this bug. ***
Comment 22 Mark Mitchell 2006-05-25 02:33:47 UTC
Will not be fixed in 4.1.1; adjust target milestone to 4.1.2.
Comment 23 Andrew Pinski 2006-07-12 23:11:32 UTC
*** Bug 28365 has been marked as a duplicate of this bug. ***
Comment 24 Andrew Pinski 2006-08-25 17:41:11 UTC
*** Bug 28846 has been marked as a duplicate of this bug. ***
Comment 25 Andrew Pinski 2007-02-25 16:49:44 UTC
*** Bug 30959 has been marked as a duplicate of this bug. ***
Comment 26 Andrew Pinski 2007-03-12 21:59:37 UTC
*** Bug 31156 has been marked as a duplicate of this bug. ***
Comment 27 Jason Merrill 2007-10-24 03:45:48 UTC
Subject: Bug 25950

Author: jason
Date: Wed Oct 24 03:45:37 2007
New Revision: 129596

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129596
Log:
        PR c++/25950 (DR 391)
        * call.c (struct conversion): Remove check_copy_constructor_p.
        (reference_binding): Always bind a reference directly to a
        compatible class rvalue.  Pass down LOOKUP_NO_TEMP_BIND during
        temporary creation.
        (check_constructor_callable): Remove.
        (convert_like_real): Don't call it.
        (initialize_reference): Don't call check_constructor_callable.
        (standard_conversion): Check LOOKUP_NO_CONVERSION instead of
        LOOKUP_CONSTRUCTOR_CALLABLE.  Don't require a temporary for base
        conversions if LOOKUP_NO_TEMP_BIND.
        (implicit_conversion): Pass through LOOKUP_NO_TEMP_BIND.
        (build_user_type_conversion_1): Pass through LOOKUP_NO_TEMP_BIND for
        second conversion.
        * cp-tree.h (LOOKUP_CONSTRUCTOR_CALLABLE): Remove.

Added:
    trunk/gcc/testsuite/g++.dg/overload/reftemp1.C
    trunk/gcc/testsuite/g++.dg/overload/reftemp2.C
Removed:
    trunk/gcc/testsuite/g++.dg/init/copy7.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h

Comment 28 Jason Merrill 2007-11-03 13:40:30 UTC
Fixed for 4.3.0.
Comment 29 Joseph S. Myers 2008-07-04 19:32:04 UTC
Fixed in 4.3, no longer marked a regression; closing.
Comment 30 Andrew Pinski 2008-07-31 07:03:02 UTC
*** Bug 36490 has been marked as a duplicate of this bug. ***
Comment 31 Jackie Rosen 2014-02-16 10:02:47 UTC Comment hidden (spam)