Re: [C++ Patch/RFC] PR 60047

2014-02-12 Thread Jason Merrill

On 02/06/2014 02:59 AM, Paolo Carlini wrote:

-  if (vec_safe_is_empty (vbases))
+  if (vbases == NULL)


vec_safe_is_empty is still more correct here.

The rest of the patch is OK.

Jason



[Ping] Re: [C++ Patch/RFC] PR 60047

2014-02-11 Thread Paolo Carlini

Hi,

the last version of this work is unreviewed, should be rather 
straightforward...


Paolo.


Re: [C++ Patch/RFC] PR 60047

2014-02-06 Thread Paolo Carlini

Hi,

On 02/05/2014 10:28 PM, Jason Merrill wrote:

On 02/05/2014 11:19 AM, Paolo Carlini wrote:

   if (vec_safe_is_empty (vbases))
 /* No virtual bases to worry about.  */;
   else if (!assign_p)
 {
   if (constexpr_p)
 *constexpr_p = false;


*constexpr_p should be false for a constructor of a class with virtual 
bases, according to the standard (7.1.5p4):


The definition of a constexpr constructor shall satisfy the following 
constraints:

— the class shall not have any virtual base classes;
...

So the assert in implicit_declare_fn is wrong.  I guess I would fix it 
by checking CLASSTYPE_VBASECLASSES.
Ah! It didn't occur to me that the bug could be in the gcc_assert 
itself. Thus, thanks, I tested on x86_64-linux the below.


Paolo.

//
/cp
2014-02-06  Paolo Carlini  

PR c++/60047
* method.c (implicitly_declare_fn): A constructor of a class with
virtual base classes isn't constexpr (7.1.5p4).
(synthesized_method_walk): Revert PR58871 change.

/testsuite
2014-02-06  Paolo Carlini  

PR c++/60047
* g++.dg/cpp0x/pr60047.C: New.
Index: cp/method.c
===
--- cp/method.c (revision 207536)
+++ cp/method.c (working copy)
@@ -1366,7 +1366,7 @@ synthesized_method_walk (tree ctype, special_funct
 }
 
   vbases = CLASSTYPE_VBASECLASSES (ctype);
-  if (vec_safe_is_empty (vbases))
+  if (vbases == NULL)
 /* No virtual bases to worry about.  */;
   else if (!assign_p)
 {
@@ -1656,10 +1656,12 @@ implicitly_declare_fn (special_function_kind kind,
   /* Don't bother marking a deleted constructor as constexpr.  */
   if (deleted_p)
 constexpr_p = false;
-  /* A trivial copy/move constructor is also a constexpr constructor.  */
+  /* A trivial copy/move constructor is also a constexpr constructor,
+ unless the class has virtual bases (7.1.5p4).  */
   else if (trivial_p && cxx_dialect >= cxx11
   && (kind == sfk_copy_constructor
-  || kind == sfk_move_constructor))
+  || kind == sfk_move_constructor)
+  && !CLASSTYPE_VBASECLASSES (type))
 gcc_assert (constexpr_p);
 
   if (!trivial_p && type_has_trivial_fn (type, kind))
Index: testsuite/g++.dg/cpp0x/pr60047.C
===
--- testsuite/g++.dg/cpp0x/pr60047.C(revision 0)
+++ testsuite/g++.dg/cpp0x/pr60047.C(working copy)
@@ -0,0 +1,14 @@
+// PR c++/60047
+// { dg-do compile { target c++11 } }
+
+struct B { };
+
+template struct A : virtual B
+{
+  A();
+  A(const A&);
+};
+
+template A::A(const A&) = default;
+
+A a = A();


Re: [C++ Patch/RFC] PR 60047

2014-02-05 Thread Jason Merrill

On 02/05/2014 11:19 AM, Paolo Carlini wrote:

   if (vec_safe_is_empty (vbases))
 /* No virtual bases to worry about.  */;
   else if (!assign_p)
 {
   if (constexpr_p)
 *constexpr_p = false;


*constexpr_p should be false for a constructor of a class with virtual 
bases, according to the standard (7.1.5p4):


The definition of a constexpr constructor shall satisfy the following 
constraints:

— the class shall not have any virtual base classes;
...

So the assert in implicit_declare_fn is wrong.  I guess I would fix it 
by checking CLASSTYPE_VBASECLASSES.


Jason



Re: [C++ Patch/RFC] PR 60047

2014-02-05 Thread Paolo Carlini

Hi,

On 02/04/2014 12:51 PM, Paolo Carlini wrote:

Hi,

thus I tried to have a look to this issue, while experiencing some 
weird problems with the debugger, which slowed me down a lot. I have 
been able to figure out that we don't seem to actively set constexpr_p 
to true anywhere in implicitly_declare_fn (besides the unrelated case 
of inheriting constructors), thus I'm wondering if it would make sense 
to simply do the below?!? (and revert my recent tweak)
I spent a little more time on this. Outside the case of inheriting 
constructors and the special case of expected_trivial default 
constructors (which are handled in a special conditional), we are 
normally assigning true to constexpr_p only in one place, that is close 
to the beginning of synthesized_method_walk:


  /* If that user-written default constructor would satisfy the
 requirements of a constexpr constructor (7.1.5), the
 implicitly-defined default constructor is constexpr.  */
  if (constexpr_p)
*constexpr_p = ctor_p;

then, for the testcase at issue it becomes false in the place which we 
already discussed for the ICE:


  if (vec_safe_is_empty (vbases))
/* No virtual bases to worry about.  */;
  else if (!assign_p)
{
  if (constexpr_p)
*constexpr_p = false;

Then it doesn't gets a chance to return true. Thus, given the more 
accurate analysis, I think that we either do what I quickly proposed 
yesterday, or alternately, the only option I can see, we change 
process_subob_fn to set it to true in some cases (but I note that it 
does never set to true trivial_p).


Thanks,
Paolo.


[C++ Patch/RFC] PR 60047

2014-02-04 Thread Paolo Carlini

Hi,

thus I tried to have a look to this issue, while experiencing some weird 
problems with the debugger, which slowed me down a lot. I have been able 
to figure out that we don't seem to actively set constexpr_p to true 
anywhere in implicitly_declare_fn (besides the unrelated case of 
inheriting constructors), thus I'm wondering if it would make sense to 
simply do the below?!? (and revert my recent tweak)


Otherwise, Jason, if you suspect something deeper is going on, I would 
rather ask you to take over, today the debugger is still misbehaving on 
me :(


Thanks!
Paolo.

//
Index: cp/method.c
===
--- cp/method.c (revision 207457)
+++ cp/method.c (working copy)
@@ -1366,7 +1366,7 @@ synthesized_method_walk (tree ctype, special_funct
 }
 
   vbases = CLASSTYPE_VBASECLASSES (ctype);
-  if (vec_safe_is_empty (vbases))
+  if (vbases == NULL)
 /* No virtual bases to worry about.  */;
   else if (!assign_p)
 {
@@ -1660,7 +1660,7 @@ implicitly_declare_fn (special_function_kind kind,
   else if (trivial_p && cxx_dialect >= cxx11
   && (kind == sfk_copy_constructor
   || kind == sfk_move_constructor))
-gcc_assert (constexpr_p);
+constexpr_p = true;
 
   if (!trivial_p && type_has_trivial_fn (type, kind))
 type_set_nontrivial_flag (type, kind);
Index: testsuite/g++.dg/cpp0x/pr60047.C
===
--- testsuite/g++.dg/cpp0x/pr60047.C(revision 0)
+++ testsuite/g++.dg/cpp0x/pr60047.C(working copy)
@@ -0,0 +1,14 @@
+// PR c++/60047
+// { dg-do compile { target c++11 } }
+
+struct B { };
+
+template struct A : virtual B
+{
+  A();
+  A(const A&);
+};
+
+template A::A(const A&) = default;
+
+A a = A();