This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ Patch] PR 64418


Hello,

This patch fixes an issue with C++11 where user-defined conversion is not properly suppressed in certain cases of list-initialisation.

Consider the example:
--- 8< ------
struct C {
      C(const C &);
};

struct X {
      operator C() const;
};

C a{X()};

--- 8< ------

This program is successfully compiled. However, I believe this is an
erroneous behaviour.

The variable "a" is initialised by direct list-initialization
according to 8.5.4. [dcl.init.list] #3 and 13.3.1.7 [over.match.list].
As the class C does not have an initializer-list ctor, all the
constructors of C are tried with the elements of the initializer list
as arguments.

GCC tries and in fact finds a user-defined conversion sequence from X
to the first parameter of the C's copy-ctor.

However, according to 13.3.3.1 [over.best.ics] #4,

"[...] when considering the argument of a constructor [...] that is a
candidate by [...] by 13.3.1.7 [...] or when the initializer list has
exactly one element and a conversion to some class X or reference to
(possibly cv-qualified) X is considered for the first parameter of a
constructor of X [...] only standard conversion sequences and ellipsis
conversion sequences are considered.

Bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51553 is related to this one.

Bootstrapped and regtested on:

Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-list-conv/configure --prefix=/home/chill/opt/gcc-list-conv --enable-languages=c,c++ --disable-multilib
Thread model: posix
gcc version 5.0.0 20141225 (experimental) [chill/list-conv revision b97cebe:8ccc35f:77c6247fdf2b97e796de45e5a2279b3a44b2f998] (GCC)

without regressions, except the testcase initlist64.C, which, I believe is flawed and was fixed.




/cp
2014-12-27  Momchil Velikov  <momchil.velikov@gmail.com>

	PR c++/64418
	* call.c (add_function_candidate): Do not allow user-defined
	conversions during list-initialisation, when the constructor is
	called with a single argument that takes a reference to the
	constructor's class.

/testsuite
2014-12-27  Momchil Velikov  <momchil.velikov@gmail.com>

	PR c++/64418
	* g++.dg/cpp0x/initlist64.C: Fix testcase.
	* g++.dg/cpp0x/initlist91.C: New.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 86c78ab..1e36dd2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2078,11 +2078,10 @@ add_function_candidate (struct z_candidate **candidates,
 	    {
 	      if (!(flags & LOOKUP_ONLYCONVERTING))
 		lflags |= LOOKUP_COPY_PARM;
-	      /* We allow user-defined conversions within init-lists, but
-		 don't list-initialize the copy parm, as that would mean
-		 using two levels of braces for the same type.  */
-	      if ((flags & LOOKUP_LIST_INIT_CTOR)
-		  && BRACE_ENCLOSED_INITIALIZER_P (arg))
+
+	      /* According to [over.best.ics] #4, suppress user-defined
+		 conversion in the context of list-initialisation.  */
+	      if ((flags & LOOKUP_LIST_INIT_CTOR))
 		lflags |= LOOKUP_NO_CONVERSION;
 	    }
 	  else
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist64.C b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
index 78e5308..11e6bd9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist64.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist64.C
@@ -16,14 +16,14 @@ struct Z
   explicit operator X() const;
 };
 
-X a = { Y() };
+X a = { Y() };	// { dg-error "" }
 X aa = Y();
 
-X b{ Y() };
+X b{ Y() };	// { dg-error "" }
 X bb(Y());
 
 X c = { Z() };  // { dg-error "" }
 X cc = Z();	// { dg-error "" }
 
-X d{ Z() };
+X d{ Z() };	// { dg-error "" }
 X dd( Z() );
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist91.C b/gcc/testsuite/g++.dg/cpp0x/initlist91.C
new file mode 100644
index 0000000..9debb79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist91.C
@@ -0,0 +1,25 @@
+// PR c++/51553
+// { dg-do compile { target c++11 } }
+
+struct C {
+  C(const C &);
+  C(const C &, int);
+  C(int, const C &);
+};
+
+struct X {
+  operator C() const;
+};
+
+X x;
+
+C a{x};		// { dg-error "" }
+C b{x, 1};
+C c{1, x};
+C d(x);
+C e(x, 1);
+C f(1, x);
+C g = x;
+C h = {x};	// { dg-error "" }
+C i = {x, 1};
+C j = {1, x};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]