PR c++/79592 - missing explanation of invalid constexpr.
authorJason Merrill <jason@redhat.com>
Tue, 17 Dec 2019 21:46:40 +0000 (16:46 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 17 Dec 2019 21:46:40 +0000 (16:46 -0500)
We changed months back to use the pre-generic form for constexpr evaluation,
but explain_invalid_constexpr_fn was still using DECL_SAVED_TREE.  This
mostly works, but misses some issues due to folding.  So with this patch we
save the pre-generic form of constexpr functions even when we know they
can't produce a constant result.

* constexpr.c (register_constexpr_fundef): Do store the body of a
template instantiation that is not potentially constant.
(explain_invalid_constexpr_fn): Look it up.
(cxx_eval_call_expression): Check fundef->result.

From-SVN: r279473

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C [new file with mode: 0644]

index e5824d57cc009cc50986a77854a6622138056f6d..91837d36d6e02ab9047d1df66966ffa64e8b08aa 100644 (file)
@@ -1,3 +1,11 @@
+2019-12-17  Jason Merrill  <jason@redhat.com>
+
+       PR c++/79592 - missing explanation of invalid constexpr.
+       * constexpr.c (register_constexpr_fundef): Do store the body of a
+       template instantiation that is not potentially constant.
+       (explain_invalid_constexpr_fn): Look it up.
+       (cxx_eval_call_expression): Check fundef->result.
+
 2019-12-17  Jason Merrill  <jason@redhat.com>
 
        PR c++/92576 - redeclaration of variable template.
index f3f03e7d6215ac46fb7e311a168ebe434e3cdc89..87d78d2672899b7cf2f2132c1204574405882b05 100644 (file)
@@ -885,16 +885,16 @@ register_constexpr_fundef (tree fun, tree body)
       return NULL;
     }
 
-  if (!potential_rvalue_constant_expression (massaged))
-    {
-      if (!DECL_GENERATED_P (fun))
-       require_potential_rvalue_constant_expression (massaged);
-      return NULL;
-    }
+  bool potential = potential_rvalue_constant_expression (massaged);
+  if (!potential && !DECL_GENERATED_P (fun))
+    require_potential_rvalue_constant_expression (massaged);
 
   if (DECL_CONSTRUCTOR_P (fun)
       && cx_check_missing_mem_inits (DECL_CONTEXT (fun),
                                     massaged, !DECL_GENERATED_P (fun)))
+    potential = false;
+
+  if (!potential && !DECL_GENERATED_P (fun))
     return NULL;
 
   /* Create the constexpr function table if necessary.  */
@@ -917,6 +917,12 @@ register_constexpr_fundef (tree fun, tree body)
   if (clear_ctx)
     DECL_CONTEXT (DECL_RESULT (fun)) = NULL_TREE;
 
+  if (!potential)
+    /* For a template instantiation, we want to remember the pre-generic body
+       for explain_invalid_constexpr_fn, but do tell cxx_eval_call_expression
+       that it doesn't need to bother trying to expand the function.  */
+    entry.result = error_mark_node;
+
   gcc_assert (*slot == NULL);
   *slot = ggc_alloc<constexpr_fundef> ();
   **slot = entry;
@@ -962,11 +968,15 @@ explain_invalid_constexpr_fn (tree fun)
     {
       /* Then if it's OK, the body.  */
       if (!DECL_DECLARED_CONSTEXPR_P (fun)
-         && !LAMBDA_TYPE_P (CP_DECL_CONTEXT (fun)))
+         && DECL_DEFAULTED_FN (fun))
        explain_implicit_non_constexpr (fun);
       else
        {
-         body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun));
+         if (constexpr_fundef *fd = retrieve_constexpr_fundef (fun))
+           body = fd->body;
+         else
+           body = DECL_SAVED_TREE (fun);
+         body = massage_constexpr_body (fun, body);
          require_potential_rvalue_constant_expression (body);
          if (DECL_CONSTRUCTOR_P (fun))
            cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true);
@@ -1919,6 +1929,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
     {
       new_call.fundef = retrieve_constexpr_fundef (fun);
       if (new_call.fundef == NULL || new_call.fundef->body == NULL
+         || new_call.fundef->result == error_mark_node
          || fun == current_function_decl)
         {
          if (!ctx->quiet)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi1.C
new file mode 100644 (file)
index 0000000..b94cf30
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/79592
+// { dg-do compile { target c++11 } }
+
+struct pthread_mutex {
+  void *m_ptr;
+};
+
+struct M {
+  pthread_mutex m = { ((void *) 1LL) }; // { dg-error "reinterpret_cast" }
+};
+
+constexpr M m;                 // { dg-error "M::M" }