cxx_eval_pointer_plus_expression was assuming that array_type_nelts_top would be a constant expression, which it might not be.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit b9f0335823eff3e6d6f562268cb36c05b41790ab Author: Jason Merrill <ja...@redhat.com> Date: Mon Aug 1 10:28:50 2016 -0400 PR c++/72766 - ICE with VLA * constexpr.c (cxx_eval_pointer_plus_expression): Check constancy of nelts. * cp-gimplify.c (cp_fully_fold): Only maybe_constant_value in C++11 and up. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 8bda973..edade48 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -3581,6 +3581,10 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t, tree type = TREE_TYPE (op00); t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (op00, 1)); tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (op00, 0))); + nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p, + overflow_p); + if (*non_constant_p) + return NULL_TREE; /* Don't fold an out-of-bound access. */ if (!tree_int_cst_le (t, nelts)) return NULL_TREE; diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 59953a6..e28c9df 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -1967,7 +1967,8 @@ cp_fully_fold (tree x) return x; /* FIXME cp_fold ought to be a superset of maybe_constant_value so we don't have to call both. */ - x = maybe_constant_value (x); + if (cxx_dialect >= cxx11) + x = maybe_constant_value (x); return cp_fold (x); } diff --git a/gcc/testsuite/g++.dg/ext/vla16.C b/gcc/testsuite/g++.dg/ext/vla16.C new file mode 100644 index 0000000..c3e6ea1 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vla16.C @@ -0,0 +1,8 @@ +// PR c++/72766 +// { dg-options "-Wno-vla" } + +long fn1() { + const int a = fn1(); + int b[a]; + int c = *(&b[0] + sizeof(0)); +}