This test segvs since r269078, this hunk in particular:

@@ -4581,8 +4713,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
       break;

     case SIZEOF_EXPR:
-      r = fold_sizeof_expr (t);
-      VERIFY_CONSTANT (r);
+      r = cxx_eval_constant_expression (ctx, fold_sizeof_expr (t), lval,
+                   non_constant_p, overflow_p,
+                   jump_target);
       break;

In a template, fold_sizeof_expr will just create a new SIZEOF_EXPR, that is the
same, but not identical; see cxx_sizeof_expr.  Then cxx_eval_constant_expression
calls itself on this new expr, then fold_sizeof_expr creates another 
SIZEOF_EXPR.
Then we call cxx_eval_constant_expression...

The call to cxx_eval_constant_expression is there to keep constexpr-vla1.C
working.  But we can avoid calling it in a template and it'll still work, and
we avoid this nasty recursion.

Bootstrapped/regtested on x86_64-linux, ok for trunk and 9?

2019-06-10  Marek Polacek  <pola...@redhat.com>

        PR c++/90825 - endless recursion when evaluating sizeof.
        * constexpr.c (cxx_eval_constant_expression): Don't recurse on the
        result of fold_sizeof_expr in a template.

        * g++.dg/cpp0x/constexpr-sizeof2.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index a2f29694462..a68aac3b531 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -4808,9 +4808,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, 
tree t,
       break;
 
     case SIZEOF_EXPR:
-      r = cxx_eval_constant_expression (ctx, fold_sizeof_expr (t), lval,
-                                       non_constant_p, overflow_p,
-                                       jump_target);
+      r = fold_sizeof_expr (t);
+      /* Don't recurse in a template, because then fold_sizeof_expr merely
+        creates a new SIZEOF_EXPR, leading to an infinite recursion.  */
+      if (!processing_template_decl)
+       r = cxx_eval_constant_expression (ctx, r, lval,
+                                         non_constant_p, overflow_p,
+                                         jump_target);
       break;
 
     case COMPOUND_EXPR:
diff --git gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C 
gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C
new file mode 100644
index 00000000000..2d3a169d28c
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-sizeof2.C
@@ -0,0 +1,14 @@
+// PR c++/90825 - endless recursion when evaluating sizeof.
+// { dg-do compile { target c++11 } }
+
+class address {
+  char host_[63];
+public:
+  static constexpr unsigned buffer_size() noexcept { return sizeof(host_); }
+};
+
+template <class Archive>
+void load()
+{
+  char host[address::buffer_size()];
+}

Reply via email to