PR c++/50248
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Sep 2011 04:33:08 +0000 (04:33 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 5 Sep 2011 04:33:08 +0000 (04:33 +0000)
Core 1358
* init.c (perform_member_init): Don't diagnose missing inits here.
(emit_mem_initializers): Or here.
* method.c (process_subob_fn): Don't instantiate constexpr ctors.
* semantics.c (cx_check_missing_mem_inits): New.
(explain_invalid_constexpr_fn): Call it.
(register_constexpr_fundef): Likewise.  Leave
DECL_DECLARED_CONSTEXPR_P set when the body is unsuitable.
(cxx_eval_call_expression): Adjust diagnostics.
(cxx_eval_constant_expression): Catch use of 'this' in a constructor.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178518 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-48089.C
gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C [new file with mode: 0644]

index 96ac237..a83d19b 100644 (file)
@@ -1,3 +1,17 @@
+2011-09-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50248
+       Core 1358
+       * init.c (perform_member_init): Don't diagnose missing inits here.
+       (emit_mem_initializers): Or here.
+       * method.c (process_subob_fn): Don't instantiate constexpr ctors.
+       * semantics.c (cx_check_missing_mem_inits): New.
+       (explain_invalid_constexpr_fn): Call it.
+       (register_constexpr_fundef): Likewise.  Leave
+       DECL_DECLARED_CONSTEXPR_P set when the body is unsuitable.
+       (cxx_eval_call_expression): Adjust diagnostics.
+       (cxx_eval_constant_expression): Catch use of 'this' in a constructor.
+
 2011-08-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/50084
index 847f519..ff1884b 100644 (file)
@@ -606,15 +606,6 @@ perform_member_init (tree member, tree init)
 
          core_type = strip_array_types (type);
 
-         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
-             && !type_has_constexpr_default_constructor (core_type))
-           {
-             if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-               error ("uninitialized member %qD in %<constexpr%> constructor",
-                      member);
-             DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
-           }
-
          if (CLASS_TYPE_P (core_type)
              && (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type)
                  || CLASSTYPE_REF_FIELDS_NEED_INIT (core_type)))
@@ -962,16 +953,6 @@ emit_mem_initializers (tree mem_inits)
                        OPT_Wextra, "base class %q#T should be explicitly "
                        "initialized in the copy constructor",
                        BINFO_TYPE (subobject));
-
-         if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
-             && !(type_has_constexpr_default_constructor
-                  (BINFO_TYPE (subobject))))
-           {
-             if (!DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-               error ("uninitialized base %qT in %<constexpr%> constructor",
-                      BINFO_TYPE (subobject));
-             DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
-           }
        }
 
       /* Initialize the base.  */
index 3d272a3..74a3bdb 100644 (file)
@@ -952,23 +952,14 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
       goto bad;
     }
 
-  if (constexpr_p)
+  if (constexpr_p && !DECL_DECLARED_CONSTEXPR_P (fn))
     {
-      /* If this is a specialization of a constexpr template, we need to
-        force the instantiation now so that we know whether or not it's
-        really constexpr.  */
-      if (DECL_DECLARED_CONSTEXPR_P (fn) && DECL_TEMPLATE_INSTANTIATION (fn)
-         && !DECL_TEMPLATE_INSTANTIATED (fn))
-       instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false);
-      if (!DECL_DECLARED_CONSTEXPR_P (fn))
+      *constexpr_p = false;
+      if (msg)
        {
-         *constexpr_p = false;
-         if (msg)
-           {
-             inform (0, "defaulted constructor calls non-constexpr "
-                     "%q+D", fn);
-             explain_invalid_constexpr_fn (fn);
-           }
+         inform (0, "defaulted constructor calls non-constexpr "
+                 "%q+D", fn);
+         explain_invalid_constexpr_fn (fn);
        }
     }
 
index ce84062..fd96d70 100644 (file)
@@ -5775,6 +5775,53 @@ massage_constexpr_body (tree fun, tree body)
   return body;
 }
 
+/* FUN is a constexpr constructor with massaged body BODY.  Return true
+   if some bases/fields are uninitialized, and complain if COMPLAIN.  */
+
+static bool
+cx_check_missing_mem_inits (tree fun, tree body, bool complain)
+{
+  bool bad;
+  tree field;
+  unsigned i, nelts;
+
+  if (TREE_CODE (body) != CONSTRUCTOR)
+    return false;
+
+  bad = false;
+  nelts = CONSTRUCTOR_NELTS (body);
+  field = TYPE_FIELDS (DECL_CONTEXT (fun));
+  for (i = 0; i <= nelts; ++i)
+    {
+      tree index;
+      if (i == nelts)
+       index = NULL_TREE;
+      else
+       {
+         index = CONSTRUCTOR_ELT (body, i)->index;
+         /* Skip base vtable inits.  */
+         if (TREE_CODE (index) == COMPONENT_REF)
+           continue;
+       }
+      for (; field != index; field = DECL_CHAIN (field))
+       {
+         if (TREE_CODE (field) != FIELD_DECL
+             || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)))
+           continue;
+         if (!complain)
+           return true;
+         error ("uninitialized member %qD in %<constexpr%> constructor",
+                field);
+         bad = true;
+       }
+      if (field == NULL_TREE)
+       break;
+      field = DECL_CHAIN (field);
+    }
+
+  return bad;
+}
+
 /* We are processing the definition of the constexpr function FUN.
    Check that its BODY fulfills the propriate requirements and
    enter it in the constexpr function definition table.
@@ -5797,12 +5844,15 @@ register_constexpr_fundef (tree fun, tree body)
 
   if (!potential_rvalue_constant_expression (body))
     {
-      DECL_DECLARED_CONSTEXPR_P (fun) = false;
       if (!DECL_TEMPLATE_INFO (fun))
        require_potential_rvalue_constant_expression (body);
       return NULL;
     }
 
+  if (DECL_CONSTRUCTOR_P (fun)
+      && cx_check_missing_mem_inits (fun, body, !DECL_TEMPLATE_INFO (fun)))
+    return NULL;
+
   /* Create the constexpr function table if necessary.  */
   if (constexpr_fundef_table == NULL)
     constexpr_fundef_table = htab_create_ggc (101,
@@ -5842,8 +5892,7 @@ explain_invalid_constexpr_fn (tree fun)
 
   save_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (fun);
-  inform (0, "%q+D is not constexpr because it does not satisfy the "
-         "requirements:", fun);
+  inform (0, "%q+D is not usable as a constexpr function because:", fun);
   /* First check the declaration.  */
   if (is_valid_constexpr_fn (fun, true))
     {
@@ -5854,6 +5903,8 @@ explain_invalid_constexpr_fn (tree fun)
        {
          body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
          require_potential_rvalue_constant_expression (body);
+         if (DECL_CONSTRUCTOR_P (fun))
+           cx_check_missing_mem_inits (fun, body, true);
        }
     }
   input_location = save_loc;
@@ -6203,7 +6254,16 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
       if (new_call.fundef == NULL || new_call.fundef->body == NULL)
         {
          if (!allow_non_constant)
-           error_at (loc, "%qD used before its definition", fun);
+           {
+             if (DECL_SAVED_TREE (fun))
+               {
+                 /* The definition of fun was somehow unsuitable.  */
+                 error_at (loc, "%qD called in a constant expression", fun);
+                 explain_invalid_constexpr_fn (fun);
+               }
+             else
+               error_at (loc, "%qD used before its definition", fun);
+           }
          *non_constant_p = true;
           return t;
         }
@@ -7176,7 +7236,17 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
 
     case PARM_DECL:
       if (call && DECL_CONTEXT (t) == call->fundef->decl)
-       r = lookup_parameter_binding (call, t);
+       {
+         if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t)))
+           {
+             if (!allow_non_constant)
+               sorry ("use of the value of the object being constructed "
+                      "in a constant expression");
+             *non_constant_p = true;
+           }
+         else
+           r = lookup_parameter_binding (call, t);
+       }
       else if (addr)
        /* Defer in case this is only used for its type.  */;
       else
index 095ccc8..19441c4 100644 (file)
@@ -1,3 +1,12 @@
+2011-09-04  Jason Merrill  <jason@redhat.com>
+
+       PR c++/50248
+       Core 1358
+       * g++.dg/cpp0x/constexpr-template1.C: New.
+       * g++.dg/cpp0x/constexpr-template2.C: New.
+       * g++.dg/cpp0x/constexpr-48089.C: Adjust error markup.
+       * g++.dg/cpp0x/constexpr-ex1.C: Adjust error markup.
+
 2011-09-04  Eric Botcazou  <ebotcazou@adacore.com>
 
        * gnat.dg/specs/debug1.ads: Tweak pattern.
index 5124f7c..a6cf408 100644 (file)
@@ -14,7 +14,7 @@ struct s {
   int v;
 };
 
-constexpr s bang;              // { dg-error "" }
+constexpr s bang;              // { dg-message "" }
 
 struct R {
   int i,j;
@@ -33,7 +33,7 @@ struct T {
 
 constexpr T t1;
 // Ill-formed (diagnostic required)
-constexpr T t2(t1);            // { dg-error "" }
+constexpr T t2(t1);            // { dg-message "" }
 
 // Well-formed
 struct U {
index 584a5a0..3df7956 100644 (file)
@@ -89,6 +89,6 @@ struct resource {
 };
 constexpr resource f(resource d)
 { return d; }                  // { dg-error "non-constexpr" }
-constexpr resource d = f(9);   // { dg-error "resource" }
+constexpr resource d = f(9);   // { dg-message "constexpr" }
 
 // 4.4 floating-point constant expressions
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template1.C
new file mode 100644 (file)
index 0000000..8807723
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/50248, DR 1358
+// { dg-options -std=c++0x }
+
+template<class Elt, unsigned max>
+struct earray
+{
+    Elt elts[max];
+    earray() = default;
+    template<typename... Elt2>
+    constexpr earray(Elt2&& ... e): elts(0) { }
+};
+
+struct SessionData
+{
+    SessionData(SessionData&) = delete;
+    SessionData() = default;
+};
+
+struct MapSessionData : SessionData
+{
+    earray<short, 11> equip_index;
+};
+
+void test()
+{
+    MapSessionData *sd = new MapSessionData;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template2.C
new file mode 100644 (file)
index 0000000..6786d16
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-options -std=c++0x }
+
+template <class T> struct A
+{
+  T t;
+  constexpr A() { }            // { dg-error "uninitialized" }
+};
+
+int main()
+{
+  constexpr A<int> a;          // { dg-error "A()" }
+}