Message ID | 52F0D44C.1010106@oracle.com |
---|---|
State | New |
Headers | show |
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.
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
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<typename T> struct A : virtual B +{ + A(); + A(const A&); +}; + +template<typename T> A<T>::A(const A<T>&) = default; + +A<int> a = A<int>();