Bug 48453 - [C++0x] [DR 1287] Invalid reference initialization via explicit conversion
Summary: [C++0x] [DR 1287] Invalid reference initialization via explicit conversion
Status: RESOLVED WORKSFORME
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-05 07:41 UTC by Daniel Krügler
Modified: 2015-03-20 17:07 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2011-04-06 04:08:17


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Krügler 2011-04-05 07:41:08 UTC
GCC 4.7.0 accepts the following code in C++0x mode:

template<class T>
T&& create();

template<class T, class Arg>
void test() {
 T t(create<Arg>());
 (void) t;
}

template<class T>
struct To {
 explicit operator T();
};

int main()
{
 test<int&, To<int&>>(); // a Well-formed
 test<int&&, To<int&&>>(); // b Well-formed
}

This code should be ill-formed because of the *explicit* conversion to a reference type. 

The semantics of this program is described in 8.5.3 [dcl.init.ref] p. 5 (referring to WD N3242). In case of (a) we first inter into bullet 1 ("If the reference is an lvalue reference"). Sub-bullet 1 does not apply, then we have to inspect sub-bullet 2:

"has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with “cv3 T3”106 (this conversion is selected by enumerating the applicable conversion functions (13.3.1.6) and choosing the best one through overload resolution (13.3)),"

This *seems* to fit, except that there is no *implicit* conversion possible here, so we cannot enter this rule. For (a) bullet 2 does not apply and we must fail immediately.

For (b) we ignore bullet 1, but step into bullet 2 because of the rvalue-reference. Again, sub-bullet 1 does not apply, only sub-bullet 2 comes near:

"has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an xvalue, class prvalue, or function lvalue of type “cv3 T3”, where “cv1 T1” is reference-compatible with “cv3 T3”,"

Again, we have *no* implicit conversion, but now we need to try the last sub-bullet 3:

"Otherwise, a temporary of type “cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy-initialization (8.5). [..]"

The semantics of a non-reference copy-initialization forbids the consideration of the explicit conversion function, thus, we should fail again.
Comment 1 Jason Merrill 2011-04-06 04:08:17 UTC
This seems to me like a wording issue, not a compiler bug.  The use of "implicitly" in 8.5.3 should have been adjusted when explicit conversion operators went in; this should be reported as a core DR.
Comment 2 Daniel Krügler 2011-04-06 06:34:20 UTC
(In reply to comment #1)

I agree, I just recognize that 13.3.1.6 [over.match.ref] p. 1 b. 1 is written to support this:

"The conversion functions of S and its base classes are considered, 
except that for copy-initialization, only the non-explicit conversion 
functions are considered. Those that are not hidden within S and yield
type “lvalue reference to cv2 T2” (when 8.5.3 requires an lvalue result) 
or “cv2 T2” or “rvalue reference to cv2 T2” (when 8.5.3 requires an rvalue 
result), where “cv1 T” is reference-compatible (8.5.3) with “cv2 T2”, are 
candidate functions."

IMO the core language should strike the reference to "implicit conversions" in 8.5.3.
Comment 3 Jens Maurer 2011-04-06 21:56:51 UTC
Agreed.  The wording in the standard should be fixed.
Comment 4 Paolo Carlini 2013-06-14 11:05:20 UTC
It would be nice to have a DR # for this. In any case, if in practice the compiler is already Ok, we can probably close it, right?
Comment 5 Jason Merrill 2013-06-14 12:56:42 UTC
Added DR 1287 reference.  I'm inclined to leave the bug suspended until that issue is resolved.
Comment 6 Paolo Carlini 2013-06-14 13:32:02 UTC
Ok, thanks.
Comment 7 Paolo Carlini 2013-06-14 13:34:03 UTC
Oh, by the way, the status is <ready>.
Comment 8 Paolo Carlini 2015-03-20 16:43:13 UTC
This is now in C++14. Time to add the testcase and close the bug.
Comment 9 Daniel Krügler 2015-03-20 16:54:58 UTC
(In reply to Paolo Carlini from comment #8)
> This is now in C++14. Time to add the testcase and close the bug.
I agree.
Comment 10 paolo@gcc.gnu.org 2015-03-20 17:06:50 UTC
Author: paolo
Date: Fri Mar 20 17:06:18 2015
New Revision: 221537

URL: https://gcc.gnu.org/viewcvs?rev=221537&root=gcc&view=rev
Log:
2015-03-20  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/48453
	* g++.dg/cpp0x/pr48453.C: New.

Added:
    trunk/gcc/testsuite/g++.dg/cpp0x/pr48453.C
Modified:
    trunk/gcc/testsuite/ChangeLog
Comment 11 Paolo Carlini 2015-03-20 17:07:32 UTC
Done.