C++ PATCH to fix wrong-code with constexpr call table cache (PR c++/83116)
Marek Polacek
polacek@redhat.com
Mon Dec 18 15:09:00 GMT 2017
Here the problem was that cxx_eval_call_expression can cache the result of a
constexpr call in constexpr_call_table, but we have to be careful, after
store_init_value the result might be invalid. So I believe we also have to
clear the constexpr call table. I've lumped it together with clearing
cv_cache.
Bootstrapped/regtested on x86_64-linux, ok for trunk and 7?
2017-12-18 Marek Polacek <polacek@redhat.com>
PR c++/83116
* constexpr.c (clear_cv_cache): Renamed to ...
(clear_constexpr_cache): ... this. Also clear constexpr_call_table.
(clear_cv_and_fold_caches): Renamed to ...
(clear_constexpr_and_fold_caches): ... this.
* cp-tree.h (clear_constexpr_and_fold_caches): Update declaration.
* decl.c (finish_enum_value_list): Call clear_constexpr_and_fold_caches
instead of clear_cv_and_fold_caches.
* typeck2.c (store_init_value): Likewise.
* g++.dg/cpp1y/constexpr-83116.C: New test.
diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 0455be1d6da..e0299e731f0 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -4992,21 +4992,23 @@ maybe_constant_value (tree t, tree decl)
return r;
}
-/* Dispose of the whole CV_CACHE. */
+/* Dispose of the whole CV_CACHE and CONSTEXPR_CALL_TABLE. */
static void
-clear_cv_cache (void)
+clear_constexpr_cache (void)
{
if (cv_cache != NULL)
cv_cache->empty ();
+ if (constexpr_call_table != NULL)
+ constexpr_call_table->empty ();
}
-/* Dispose of the whole CV_CACHE and FOLD_CACHE. */
+/* Clear the constexpr caches and FOLD_CACHE. */
void
-clear_cv_and_fold_caches (void)
+clear_constexpr_and_fold_caches (void)
{
- clear_cv_cache ();
+ clear_constexpr_cache ();
clear_fold_cache ();
}
diff --git gcc/cp/cp-tree.h gcc/cp/cp-tree.h
index f5f974da728..6e553c4f62d 100644
--- gcc/cp/cp-tree.h
+++ gcc/cp/cp-tree.h
@@ -7409,7 +7409,7 @@ extern bool var_in_maybe_constexpr_fn (tree);
extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
extern tree fold_sizeof_expr (tree);
-extern void clear_cv_and_fold_caches (void);
+extern void clear_constexpr_and_fold_caches (void);
/* In cp-ubsan.c */
extern void cp_ubsan_maybe_instrument_member_call (tree);
diff --git gcc/cp/decl.c gcc/cp/decl.c
index ca9e0c7b205..bed2280b9e4 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -14341,7 +14341,7 @@ finish_enum_value_list (tree enumtype)
/* Each enumerator now has the type of its enumeration. Clear the cache
so that this change in types doesn't confuse us later on. */
- clear_cv_and_fold_caches ();
+ clear_constexpr_and_fold_caches ();
}
/* Finishes the enum type. This is called only the first time an
diff --git gcc/cp/typeck2.c gcc/cp/typeck2.c
index e5bb249b2be..787e59b70d8 100644
--- gcc/cp/typeck2.c
+++ gcc/cp/typeck2.c
@@ -845,7 +845,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
value = replace_placeholders (value, decl);
/* DECL may change value; purge caches. */
- clear_cv_and_fold_caches ();
+ clear_constexpr_and_fold_caches ();
/* If the initializer is not a constant, fill in DECL_INITIAL with
the bits that are constant, and then return an expression that
diff --git gcc/testsuite/g++.dg/cpp1y/constexpr-83116.C gcc/testsuite/g++.dg/cpp1y/constexpr-83116.C
index e69de29bb2d..18d79e2e1cc 100644
--- gcc/testsuite/g++.dg/cpp1y/constexpr-83116.C
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-83116.C
@@ -0,0 +1,18 @@
+// PR c++/83116
+// { dg-do run { target c++14 } }
+// { dg-options "-O2" }
+
+struct S {
+ constexpr S () : s(0) { foo (); }
+ constexpr int foo () { return s; }
+ int s;
+};
+
+int
+main ()
+{
+ static S var;
+ var.s = 5;
+ if (var.s != 5 || var.foo () != 5)
+ __builtin_abort ();
+}
Marek
More information about the Gcc-patches
mailing list