re PR c++/45923 (constexpr diagnostics, more more)
authorJason Merrill <jason@redhat.com>
Wed, 29 Jun 2011 14:34:58 +0000 (10:34 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 29 Jun 2011 14:34:58 +0000 (10:34 -0400)
PR c++/45923
* class.c (explain_non_literal_class): New.
(finalize_literal_type_property): Call it.
* cp-tree.h: Declare it.
* semantics.c (ensure_literal_type_for_constexpr_object): Call it.
(is_valid_constexpr_fn): Likewise.
(massage_constexpr_body): Split out from...
(register_constexpr_fundef): ...here.
(is_instantiation_of_constexpr): New.
(expand_or_defer_fn_1): Leave DECL_SAVED_TREE alone in that case.
(explain_invalid_constexpr_fn): New.
(cxx_eval_call_expression): Call it.
(potential_constant_expression_1): Likewise.  Avoid redundant errors.
* method.c (process_subob_fn): Diagnose non-constexpr.
(walk_field_subobs): Likewise.
(synthesized_method_walk): Don't shortcut if we want diagnostics.
(explain_implicit_non_constexpr): New.
(defaulted_late_check): Use it.
* call.c (build_cxx_call): Remember location.

From-SVN: r175646

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/method.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-diag1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-ex1.C
gcc/testsuite/g++.dg/cpp0x/constexpr-friend.C
gcc/testsuite/g++.dg/cpp0x/constexpr-incomplete2.C

index 2cd5c0a4324167ea7858e816f384fa2f0e310e11..db0478a6285f5b9d511a6a267950dea4a2447bc5 100644 (file)
@@ -1,5 +1,25 @@
 2011-06-29  Jason Merrill  <jason@redhat.com>
 
+       PR c++/45923
+       * class.c (explain_non_literal_class): New.
+       (finalize_literal_type_property): Call it.
+       * cp-tree.h: Declare it.
+       * semantics.c (ensure_literal_type_for_constexpr_object): Call it.
+       (is_valid_constexpr_fn): Likewise.
+       (massage_constexpr_body): Split out from...
+       (register_constexpr_fundef): ...here.
+       (is_instantiation_of_constexpr): New.
+       (expand_or_defer_fn_1): Leave DECL_SAVED_TREE alone in that case.
+       (explain_invalid_constexpr_fn): New.
+       (cxx_eval_call_expression): Call it.
+       (potential_constant_expression_1): Likewise.  Avoid redundant errors.
+       * method.c (process_subob_fn): Diagnose non-constexpr.
+       (walk_field_subobs): Likewise.
+       (synthesized_method_walk): Don't shortcut if we want diagnostics.
+       (explain_implicit_non_constexpr): New.
+       (defaulted_late_check): Use it.
+       * call.c (build_cxx_call): Remember location.
+
        * method.c (maybe_explain_implicit_delete): Use pointer_set
        instead of htab.
 
index e2d455afcdeb0af68581cfb31c30ca233ddd4bf0..56f3408adc6b5c86e4005bd2f6bf6a2e3f4a8df1 100644 (file)
@@ -6721,7 +6721,10 @@ build_cxx_call (tree fn, int nargs, tree *argarray)
 {
   tree fndecl;
 
+  /* Remember roughly where this call is.  */
+  location_t loc = EXPR_LOC_OR_HERE (fn);
   fn = build_call_a (fn, nargs, argarray);
+  SET_EXPR_LOCATION (fn, loc);
 
   /* If this call might throw an exception, note that fact.  */
   fndecl = get_callee_fndecl (fn);
index 9054b5caa18975511d95f60a258206cfbe44d8aa..6aefd6840756c5a7faf28e46f2e063b0f3b73fd4 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "cgraph.h"
 #include "tree-dump.h"
 #include "splay-tree.h"
+#include "pointer-set.h"
 
 /* The number of nested classes being processed.  If we are not in the
    scope of any class, this is zero.  */
@@ -4582,10 +4583,73 @@ finalize_literal_type_property (tree t)
        {
          DECL_DECLARED_CONSTEXPR_P (fn) = false;
          if (!DECL_TEMPLATE_INFO (fn))
-           error ("enclosing class of %q+#D is not a literal type", fn);
+           {
+             error ("enclosing class of constexpr non-static member "
+                    "function %q+#D is not a literal type", fn);
+             explain_non_literal_class (t);
+           }
        }
 }
 
+/* T is a non-literal type used in a context which requires a constant
+   expression.  Explain why it isn't literal.  */
+
+void
+explain_non_literal_class (tree t)
+{
+  static struct pointer_set_t *diagnosed;
+
+  if (!CLASS_TYPE_P (t))
+    return;
+  t = TYPE_MAIN_VARIANT (t);
+
+  if (diagnosed == NULL)
+    diagnosed = pointer_set_create ();
+  if (pointer_set_insert (diagnosed, t) != 0)
+    /* Already explained.  */
+    return;
+
+  inform (0, "%q+T is not literal because:", t);
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+    inform (0, "  %q+T has a non-trivial destructor", t);
+  else if (CLASSTYPE_NON_AGGREGATE (t)
+          && !TYPE_HAS_TRIVIAL_DFLT (t)
+          && !TYPE_HAS_CONSTEXPR_CTOR (t))
+    inform (0, "  %q+T is not an aggregate, does not have a trivial "
+           "default constructor, and has no constexpr constructor that "
+           "is not a copy or move constructor", t);
+  else
+    {
+      tree binfo, base_binfo, field; int i;
+      for (binfo = TYPE_BINFO (t), i = 0;
+          BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+       {
+         tree basetype = TREE_TYPE (base_binfo);
+         if (!CLASSTYPE_LITERAL_P (basetype))
+           {
+             inform (0, "  base class %qT of %q+T is non-literal",
+                     basetype, t);
+             explain_non_literal_class (basetype);
+             return;
+           }
+       }
+      for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
+       {
+         tree ftype;
+         if (TREE_CODE (field) != FIELD_DECL)
+           continue;
+         ftype = TREE_TYPE (field);
+         if (!literal_type_p (ftype))
+           {
+             inform (0, "  non-static data member %q+D has "
+                     "non-literal type", field);
+             if (CLASS_TYPE_P (ftype))
+               explain_non_literal_class (ftype);
+           }
+       }
+    }
+}
+
 /* Check the validity of the bases and members declared in T.  Add any
    implicitly-generated functions (like copy-constructors and
    assignment operators).  Compute various flag bits (like
index 9afb33cc144a5f542823ed5b6d5cf20b0d9a69ae..7244cc88d4a1480a200dc231608472d0be8036e5 100644 (file)
@@ -4816,6 +4816,7 @@ extern bool type_has_virtual_destructor           (tree);
 extern bool type_has_move_constructor          (tree);
 extern bool type_has_move_assign               (tree);
 extern bool type_build_ctor_call               (tree);
+extern void explain_non_literal_class          (tree);
 extern void defaulted_late_check               (tree);
 extern bool defaultable_fn_check               (tree);
 extern void fixup_type_variants                        (tree);
@@ -5094,6 +5095,7 @@ extern void finish_thunk                  (tree);
 extern void use_thunk                          (tree, bool);
 extern bool trivial_fn_p                       (tree);
 extern bool maybe_explain_implicit_delete      (tree);
+extern void explain_implicit_non_constexpr     (tree);
 extern void synthesize_method                  (tree);
 extern tree lazily_declare_fn                  (special_function_kind,
                                                 tree);
@@ -5364,6 +5366,7 @@ extern tree maybe_constant_value (tree);
 extern tree maybe_constant_init (tree);
 extern bool is_sub_constant_expr (tree);
 extern bool reduced_constant_expression_p (tree);
+extern void explain_invalid_constexpr_fn (tree);
 extern VEC(tree,heap)* cx_error_context (void);
 
 enum {
index ec1c50252782a5a1be74aee538990548b362ae30..f10e846d0ea312df1b7a9d33e0df394487b9f53f 100644 (file)
@@ -958,7 +958,15 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
          && !DECL_TEMPLATE_INSTANTIATED (fn))
        instantiate_decl (fn, /*defer_ok*/false, /*expl_class*/false);
       if (!DECL_DECLARED_CONSTEXPR_P (fn))
-       *constexpr_p = false;
+       {
+         *constexpr_p = false;
+         if (msg)
+           {
+             inform (0, "defaulted constructor calls non-constexpr "
+                     "%q+D", fn);
+             explain_invalid_constexpr_fn (fn);
+           }
+       }
     }
 
   return;
@@ -1037,7 +1045,12 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
          /* FIXME will need adjustment for non-static data member
             initializers.  */
          if (constexpr_p && !CLASS_TYPE_P (mem_type))
-           *constexpr_p = false;
+           {
+             *constexpr_p = false;
+             if (msg)
+               inform (0, "defaulted default constructor does not "
+                       "initialize %q+#D", field);
+           }
        }
 
       if (!CLASS_TYPE_P (mem_type))
@@ -1071,8 +1084,9 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
 /* The caller wants to generate an implicit declaration of SFK for CTYPE
    which is const if relevant and CONST_P is set.  If spec_p, trivial_p and
    deleted_p are non-null, set their referent appropriately.  If diag is
-   true, we're being called from maybe_explain_implicit_delete to give
-   errors.  */
+   true, we're either being called from maybe_explain_implicit_delete to
+   give errors, or if constexpr_p is non-null, from
+   explain_invalid_constexpr_fn.  */
 
 static void
 synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
@@ -1175,6 +1189,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
      resolution, so a constructor can be trivial even if it would otherwise
      call a non-trivial constructor.  */
   if (expected_trivial
+      && !diag
       && (!copy_arg_p || cxx_dialect < cxx0x))
     {
       if (constexpr_p && sfk == sfk_constructor)
@@ -1366,6 +1381,20 @@ maybe_explain_implicit_delete (tree decl)
   return false;
 }
 
+/* DECL is a defaulted function which was declared constexpr.  Explain why
+   it can't be constexpr.  */
+
+void
+explain_implicit_non_constexpr (tree decl)
+{
+  tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl));
+  bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
+  bool dummy;
+  synthesized_method_walk (DECL_CLASS_CONTEXT (decl),
+                          special_function_p (decl), const_p,
+                          NULL, NULL, NULL, &dummy, true);
+}
+
 /* Implicitly declare the special function indicated by KIND, as a
    member of TYPE.  For copy constructors and assignment operators,
    CONST_P indicates whether these functions should take a const
@@ -1581,7 +1610,12 @@ defaulted_late_check (tree fn)
       && DECL_DECLARED_CONSTEXPR_P (fn))
     {
       if (!CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
-       error ("%qD cannot be declared as constexpr", fn);
+       {
+         error ("explicitly defaulted function %q+D cannot be declared "
+                "as constexpr because the implicit declaration is not "
+                "constexpr:", fn);
+         explain_implicit_non_constexpr (fn);
+       }
       DECL_DECLARED_CONSTEXPR_P (fn) = false;
     }
 
index 8121a0020b528389a8adb26fedecdb5033039f3a..458172980b421bd13a8ce65ea72ff488fba6ac59 100644 (file)
@@ -3538,6 +3538,17 @@ emit_associated_thunks (tree fn)
     }
 }
 
+/* Returns true iff FUN is an instantiation of a constexpr function
+   template.  */
+
+static inline bool
+is_instantiation_of_constexpr (tree fun)
+{
+  return (DECL_TEMPLATE_INFO (fun)
+         && DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
+                                       (DECL_TI_TEMPLATE (fun))));
+}
+
 /* Generate RTL for FN.  */
 
 bool
@@ -3567,7 +3578,10 @@ expand_or_defer_fn_1 (tree fn)
       /* We don't want to process FN again, so pretend we've written
         it out, even though we haven't.  */
       TREE_ASM_WRITTEN (fn) = 1;
-      DECL_SAVED_TREE (fn) = NULL_TREE;
+      /* If this is an instantiation of a constexpr function, keep
+        DECL_SAVED_TREE for explain_invalid_constexpr_fn.  */
+      if (!is_instantiation_of_constexpr (fn))
+       DECL_SAVED_TREE (fn) = NULL_TREE;
       return false;
     }
 
@@ -5299,6 +5313,7 @@ ensure_literal_type_for_constexpr_object (tree decl)
        {
          error ("the type %qT of constexpr variable %qD is not literal",
                 type, decl);
+         explain_non_literal_class (type);
          return NULL;
        }
     }
@@ -5365,8 +5380,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
       {
        ret = false;
        if (complain)
-         error ("invalid type for parameter %d of constexpr "
-                "function %q+#D", DECL_PARM_INDEX (parm), fun);
+         {
+           error ("invalid type for parameter %d of constexpr "
+                  "function %q+#D", DECL_PARM_INDEX (parm), fun);
+           explain_non_literal_class (TREE_TYPE (parm));
+         }
       }
 
   if (!DECL_CONSTRUCTOR_P (fun))
@@ -5376,8 +5394,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
        {
          ret = false;
          if (complain)
-           error ("invalid return type %qT of constexpr function %q+D",
-                  rettype, fun);
+           {
+             error ("invalid return type %qT of constexpr function %q+D",
+                    rettype, fun);
+             explain_non_literal_class (rettype);
+           }
        }
 
       /* Check this again here for cxx_eval_call_expression.  */
@@ -5386,7 +5407,11 @@ is_valid_constexpr_fn (tree fun, bool complain)
        {
          ret = false;
          if (complain)
-           error ("enclosing class of %q+#D is not a literal type", fun);
+           {
+             error ("enclosing class of constexpr non-static member "
+                    "function %q+#D is not a literal type", fun);
+             explain_non_literal_class (DECL_CONTEXT (fun));
+           }
        }
     }
 
@@ -5640,18 +5665,13 @@ constexpr_fn_retval (tree body)
     }
 }
 
-/* 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.
-   For constructor BODY is actually the TREE_LIST of the
-   member-initializer list.  */
+/* Subroutine of register_constexpr_fundef.  BODY is the DECL_SAVED_TREE of
+   FUN; do the necessary transformations to turn it into a single expression
+   that we can store in the hash table.  */
 
-tree
-register_constexpr_fundef (tree fun, tree body)
+static tree
+massage_constexpr_body (tree fun, tree body)
 {
-  constexpr_fundef entry;
-  constexpr_fundef **slot;
-
   if (DECL_CONSTRUCTOR_P (fun))
     body = build_constexpr_constructor_member_initializers
       (DECL_CONTEXT (fun), body);
@@ -5666,12 +5686,28 @@ register_constexpr_fundef (tree fun, tree body)
       if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
         body = TREE_OPERAND (body, 0);
       body = constexpr_fn_retval (body);
-      if (body == NULL_TREE || body == error_mark_node)
-        {
-          error ("body of constexpr function %qD not a return-statement", fun);
-          DECL_DECLARED_CONSTEXPR_P (fun) = false;
-          return NULL;
-        }
+    }
+  return body;
+}
+
+/* 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.
+   For constructor BODY is actually the TREE_LIST of the
+   member-initializer list.  */
+
+tree
+register_constexpr_fundef (tree fun, tree body)
+{
+  constexpr_fundef entry;
+  constexpr_fundef **slot;
+
+  body = massage_constexpr_body (fun, body);
+  if (body == NULL_TREE || body == error_mark_node)
+    {
+      error ("body of constexpr function %qD not a return-statement", fun);
+      DECL_DECLARED_CONSTEXPR_P (fun) = false;
+      return NULL;
     }
 
   if (!potential_rvalue_constant_expression (body))
@@ -5700,6 +5736,44 @@ register_constexpr_fundef (tree fun, tree body)
   return fun;
 }
 
+/* FUN is a non-constexpr function called in a context that requires a
+   constant expression.  If it comes from a constexpr template, explain why
+   the instantiation isn't constexpr.  */
+
+void
+explain_invalid_constexpr_fn (tree fun)
+{
+  static struct pointer_set_t *diagnosed;
+  tree body;
+  location_t save_loc;
+  /* Only diagnose instantiations of constexpr templates.  */
+  if (!is_instantiation_of_constexpr (fun))
+    return;
+  if (diagnosed == NULL)
+    diagnosed = pointer_set_create ();
+  if (pointer_set_insert (diagnosed, fun) != 0)
+    /* Already explained.  */
+    return;
+
+  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);
+  /* First check the declaration.  */
+  if (is_valid_constexpr_fn (fun, true))
+    {
+      /* Then if it's OK, the body.  */
+      if (DECL_DEFAULTED_FN (fun))
+       explain_implicit_non_constexpr (fun);
+      else
+       {
+         body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
+         require_potential_rvalue_constant_expression (body);
+       }
+    }
+  input_location = save_loc;
+}
+
 /* Objects of this type represent calls to constexpr functions
    along with the bindings of parameters to their arguments, for
    the purpose of compile time evaluation.  */
@@ -6005,7 +6079,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
     }
   if (TREE_CODE (fun) != FUNCTION_DECL)
     {
-      if (!allow_non_constant)
+      if (!allow_non_constant && !*non_constant_p)
        error_at (loc, "expression %qE does not designate a constexpr "
                  "function", fun);
       *non_constant_p = true;
@@ -6020,11 +6094,8 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
     {
       if (!allow_non_constant)
        {
-         error_at (loc, "%qD is not a constexpr function", fun);
-         if (DECL_TEMPLATE_INFO (fun)
-             && DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT
-                                           (DECL_TI_TEMPLATE (fun))))
-           is_valid_constexpr_fn (fun, true);
+         error_at (loc, "call to non-constexpr function %qD", fun);
+         explain_invalid_constexpr_fn (fun);
        }
       *non_constant_p = true;
       return t;
@@ -7023,8 +7094,11 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
       if (!literal_type_p (TREE_TYPE (t)))
        {
          if (!allow_non_constant)
-           error ("temporary of non-literal type %qT in a "
-                  "constant expression", TREE_TYPE (t));
+           {
+             error ("temporary of non-literal type %qT in a "
+                    "constant expression", TREE_TYPE (t));
+             explain_non_literal_class (TREE_TYPE (t));
+           }
          *non_constant_p = true;
          break;
        }
@@ -7574,7 +7648,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
                    && !morally_constexpr_builtin_function_p (fun))
                  {
                    if (flags & tf_error)
-                     error ("%qD is not %<constexpr%>", fun);
+                     {
+                       error_at (EXPR_LOC_OR_HERE (t),
+                                 "call to non-constexpr function %qD", fun);
+                       explain_invalid_constexpr_fn (fun);
+                     }
                    return false;
                  }
                /* A call to a non-static member function takes the address
@@ -7588,12 +7666,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
                    if (is_this_parameter (x))
                      /* OK.  */;
                    else if (!potential_constant_expression_1 (x, rval, flags))
-                     {
-                       if (flags & tf_error)
-                         error ("object argument is not a potential "
-                                "constant expression");
-                       return false;
-                     }
+                     return false;
                    i = 1;
                  }
              }
@@ -7609,22 +7682,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
            if (potential_constant_expression_1 (fun, rval, flags))
              /* Might end up being a constant function pointer.  */;
            else
-             {
-               if (flags & tf_error)
-                 error ("%qE is not a function name", fun);
-               return false;
-             }
+             return false;
           }
         for (; i < nargs; ++i)
           {
             tree x = get_nth_callarg (t, i);
            if (!potential_constant_expression_1 (x, rval, flags))
-             {
-               if (flags & tf_error)
-                 error ("argument in position %qP is not a "
-                        "potential constant expression", i);
-               return false;
-              }
+             return false;
           }
         return true;
       }
@@ -7853,8 +7917,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       if (!literal_type_p (TREE_TYPE (t)))
        {
          if (flags & tf_error)
-           error ("temporary of non-literal type %qT in a "
-                  "constant expression", TREE_TYPE (t));
+           {
+             error ("temporary of non-literal type %qT in a "
+                    "constant expression", TREE_TYPE (t));
+             explain_non_literal_class (TREE_TYPE (t));
+           }
          return false;
        }
     case INIT_EXPR:
index 4e2ebc3a155f4b64a41e43d30fa8619716ddc27d..d30d8b053c2fa243c33a677d9debcbd2a3d4dd82 100644 (file)
@@ -1,3 +1,12 @@
+2011-06-29  Jason Merrill  <jason@redhat.com>
+
+       PR c++/45923
+       * g++.dg/cpp0x/constexpr-diag3.C: New.
+       * g++.dg/cpp0x/constexpr-diag1.C: Adjust error message.
+       * g++.dg/cpp0x/constexpr-ex1.C: Adjust error message.
+       * g++.dg/cpp0x/constexpr-friend.C: Adjust error message.
+       * g++.dg/cpp0x/constexpr-incomplete2.C: Adjust error message.
+
 2011-06-29  Jason Merrill  <jason@redhat.com>
 
        * g++.dg/cpp0x/constexpr-is_literal.C: Adjust.
index 183d3f768fa14a703de392b70071ce89ecc6a9ac..44e6bc7e089da660922fc105633add0dd2ec813e 100644 (file)
@@ -13,7 +13,7 @@ struct B { B(); operator int(); };
 constexpr A<int> ai = { 42 };
 constexpr int i = ai.f();
 
-constexpr int b = A<B>().f();  // { dg-error "not a constexpr function" }
+constexpr int b = A<B>().f();  // { dg-error "non-constexpr function" }
 
 template <class T>
 constexpr int f (T t) { return 42; } // { dg-error "parameter" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-diag3.C
new file mode 100644 (file)
index 0000000..100c17e
--- /dev/null
@@ -0,0 +1,54 @@
+// PR c++/45923
+// { dg-options -std=c++0x }
+
+int f(int);
+
+template <class T>
+constexpr T g(T t) { return f(t); } // { dg-error "f.int" }
+
+int main()
+{
+  constexpr int i = g(1);      // { dg-error "g.T" }
+}
+
+// --------------------
+
+struct complex                         // { dg-message "no constexpr constructor" }
+{
+  complex(double r, double i) : re(r), im(i) { }
+  constexpr double real() { return re; } // { dg-error "not a literal type" }
+  double imag() const { return im; }
+
+private:
+  double re;
+  double im;
+};
+
+constexpr complex co1(0, 1);      // { dg-error "not literal" }
+constexpr double dd2 = co1.real(); // { dg-error "non-constexpr function" }
+
+// --------------------
+
+struct base                   // { dg-message "no constexpr constructor" }
+{
+  int _M_i;
+  base() : _M_i(5) { }
+};
+
+struct derived : public base   // { dg-message "base class" }
+{
+  constexpr derived(): base() { } // { dg-error "non-constexpr function" }
+};
+
+constexpr derived obj;         // { dg-error "not literal" }
+
+// --------------------
+
+struct Def
+{
+  int _M_i;                    // { dg-message "does not initialize" }
+
+  constexpr Def() = default;   // { dg-error "implicit declaration is not constexpr" }
+};
+
+constexpr Def defobj;          // { dg-error "uninitialized" }
index 4ab4677805f1cad78ddd68fe8ec9028f70a53ddc..584a5a09b69244cd037b830dfbaf502c16692753 100644 (file)
@@ -88,7 +88,7 @@ struct resource {
   }
 };
 constexpr resource f(resource d)
-{ return d; }                  // { dg-error "not .constexpr" }
+{ return d; }                  // { dg-error "non-constexpr" }
 constexpr resource d = f(9);   // { dg-error "resource" }
 
 // 4.4 floating-point constant expressions
index f1d9ccee790cd88f7f7cdda82f0aa2ecea5c9dbb..1831a2b003c6f609b3d57eadf4189e30b3f4bc2d 100644 (file)
@@ -19,5 +19,5 @@ struct C
 
 constexpr int i = f(C<int>());
 constexpr int j = C<int>().m(C<int>());
-constexpr int k = C<double>().m(A()); // { dg-error "not a constexpr function" }
-constexpr int l = g(C<double>(),A()); // { dg-error "not a constexpr function" }
+constexpr int k = C<double>().m(A()); // { dg-error "non-constexpr function" }
+constexpr int l = g(C<double>(),A()); // { dg-error "non-constexpr function" }
index dc0b7429dc65c7c52f92e2a9bfae3196b6df8966..f61535f06be517a23ff22d259db25d2c74186d74 100644 (file)
@@ -28,4 +28,4 @@ struct D
   C<D> c;
 };
 
-constexpr D d {};              // { dg-error "not a constexpr function" }
+constexpr D d {};              // { dg-error "non-constexpr function" }