aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2015-04-28 17:27:17 -0400
committerJason Merrill <jason@gcc.gnu.org>2015-04-28 17:27:17 -0400
commit3f8e2835ae414fe8f6895ed7cfe7171cea506c70 (patch)
treef164f28394dd9a352b0fea7f1bd3117604375ebb
parentdb6113067cc3a35141c9a341aa7ffb60786e3e5b (diff)
downloadgcc-3f8e2835ae414fe8f6895ed7cfe7171cea506c70.zip
gcc-3f8e2835ae414fe8f6895ed7cfe7171cea506c70.tar.gz
gcc-3f8e2835ae414fe8f6895ed7cfe7171cea506c70.tar.bz2
re PR c++/65896 (Erroneous uninitialized variable access error in constexpr function with temporary variables)
PR c++/65896 * constexpr.c (cxx_eval_store_expression): Don't try to actually store an empty class. From-SVN: r222549
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/constexpr.c15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-empty9.C18
3 files changed, 36 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index acf4d49..a2d2a7c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2015-04-28 Jason Merrill <jason@redhat.com>
+ PR c++/65896
+ * constexpr.c (cxx_eval_store_expression): Don't try to actually
+ store an empty class.
+
PR c++/65656
* constexpr.c (cxx_eval_builtin_function_call): Fix
__builtin_constant_p.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 403c7cf..9ebb640 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2580,12 +2580,25 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
/* First we figure out where we're storing to. */
tree target = TREE_OPERAND (t, 0);
+ tree type = TREE_TYPE (target);
target = cxx_eval_constant_expression (ctx, target,
true,
non_constant_p, overflow_p);
if (*non_constant_p)
return t;
+ if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type))
+ {
+ /* For initialization of an empty base, the original target will be
+ *(base*)this, which the above evaluation resolves to the object
+ argument, which has the derived type rather than the base type. In
+ this situation, just evaluate the initializer and return, since
+ there's no actual data to store. */
+ gcc_assert (is_empty_class (type));
+ return cxx_eval_constant_expression (ctx, init, false,
+ non_constant_p, overflow_p);
+ }
+
/* And then find the underlying variable. */
vec<tree,va_gc> *refs = make_tree_vector();
tree object = NULL_TREE;
@@ -2622,7 +2635,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
*non_constant_p = true;
return t;
}
- tree type = TREE_TYPE (object);
+ type = TREE_TYPE (object);
while (!refs->is_empty())
{
if (*valp == NULL_TREE)
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-empty9.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty9.C
new file mode 100644
index 0000000..26b4863
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-empty9.C
@@ -0,0 +1,18 @@
+// PR c++/65896
+// { dg-do compile { target c++11 } }
+
+struct base {};
+
+struct derived : base {
+ constexpr derived():
+ base{},
+ m_value(0) {
+ }
+ int m_value;
+};
+
+constexpr int by_ref(derived && value) {
+ return value.m_value;
+}
+
+constexpr int value = by_ref(derived{});