aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-03-20 23:25:35 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-03-20 23:25:35 -0400
commitdeaae9d7c73f87cfd2a0125411fdc54824b5d410 (patch)
tree875a9ad5038acb1c7903c9adf6be0a805d2de46e /gcc
parent766053b33a997fb268791967df46c5c3f9f94a64 (diff)
downloadgcc-deaae9d7c73f87cfd2a0125411fdc54824b5d410.zip
gcc-deaae9d7c73f87cfd2a0125411fdc54824b5d410.tar.gz
gcc-deaae9d7c73f87cfd2a0125411fdc54824b5d410.tar.bz2
re PR c++/54532 ([C++0x][constexpr] internal error when initializing static constexpr with pointer to non-static member variable)
PR c++/54532 * expr.c (cplus_expand_constant): Do nothing if the class is incomplete. * semantics.c (reduced_constant_expression_p): Allow PTRMEM_CST. * typeck2.c (store_init_value): Use reduced_constant_expression_p. * decl.c (maybe_register_incomplete_var): Handle PTRMEM_CST. (complete_vars): Likewise. From-SVN: r196852
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c29
-rw-r--r--gcc/cp/expr.c4
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/cp/typeck2.c2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C14
6 files changed, 54 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 719f70c..64a085c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
2013-03-20 Jason Merrill <jason@redhat.com>
+ PR c++/54532
+ * expr.c (cplus_expand_constant): Do nothing if the class is
+ incomplete.
+ * semantics.c (reduced_constant_expression_p): Allow PTRMEM_CST.
+ * typeck2.c (store_init_value): Use reduced_constant_expression_p.
+ * decl.c (maybe_register_incomplete_var): Handle PTRMEM_CST.
+ (complete_vars): Likewise.
+
* name-lookup.c (get_anonymous_namespace_name): Never use
get_file_function_name.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index facaae7..4ccb541 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14018,7 +14018,10 @@ grokmethod (cp_decl_specifier_seq *declspecs,
/* VAR is a VAR_DECL. If its type is incomplete, remember VAR so that
- we can lay it out later, when and if its type becomes complete. */
+ we can lay it out later, when and if its type becomes complete.
+
+ Also handle constexpr pointer to member variables where the initializer
+ is an unlowered PTRMEM_CST because the class isn't complete yet. */
void
maybe_register_incomplete_var (tree var)
@@ -14043,6 +14046,15 @@ maybe_register_incomplete_var (tree var)
incomplete_var iv = {var, inner_type};
vec_safe_push (incomplete_vars, iv);
}
+ else if (TYPE_PTRMEM_P (inner_type)
+ && DECL_INITIAL (var)
+ && TREE_CODE (DECL_INITIAL (var)) == PTRMEM_CST)
+ {
+ tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type);
+ gcc_assert (TYPE_BEING_DEFINED (context));
+ incomplete_var iv = {var, context};
+ vec_safe_push (incomplete_vars, iv);
+ }
}
}
@@ -14062,10 +14074,17 @@ complete_vars (tree type)
{
tree var = iv->decl;
tree type = TREE_TYPE (var);
- /* Complete the type of the variable. The VAR_DECL itself
- will be laid out in expand_expr. */
- complete_type (type);
- cp_apply_type_quals_to_decl (cp_type_quals (type), var);
+
+ if (TYPE_PTRMEM_P (type))
+ DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
+ else
+ {
+ /* Complete the type of the variable. The VAR_DECL itself
+ will be laid out in expand_expr. */
+ complete_type (type);
+ cp_apply_type_quals_to_decl (cp_type_quals (type), var);
+ }
+
/* Remove this entry from the list. */
incomplete_vars->unordered_remove (ix);
}
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index ffd18ca..f15b049 100644
--- a/gcc/cp/expr.c
+++ b/gcc/cp/expr.c
@@ -43,6 +43,10 @@ cplus_expand_constant (tree cst)
/* Find the member. */
member = PTRMEM_CST_MEMBER (cst);
+ /* We can't lower this until the class is complete. */
+ if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
+ return cst;
+
if (TREE_CODE (member) == FIELD_DECL)
{
/* Find the offset for the field. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 5143e4b..3691d86 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6838,6 +6838,9 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
bool
reduced_constant_expression_p (tree t)
{
+ if (TREE_CODE (t) == PTRMEM_CST)
+ /* Even if we can't lower this yet, it's constant. */
+ return true;
/* FIXME are we calling this too much? */
return initializer_constant_valid_p (t, TREE_TYPE (t)) != NULL_TREE;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 3bac67c..6ef46a1 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -792,7 +792,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
will perform the dynamic initialization. */
if (value != error_mark_node
&& (TREE_SIDE_EFFECTS (value)
- || ! initializer_constant_valid_p (value, TREE_TYPE (value))))
+ || ! reduced_constant_expression_p (value)))
{
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C
new file mode 100644
index 0000000..91cc25a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C
@@ -0,0 +1,14 @@
+// PR c++/54532
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert(X,#X)
+
+struct A {
+ int i;
+ constexpr static int A::*p = &A::i;
+};
+
+constexpr A a = { 42 };
+SA(a.*A::p == 42);
+
+constexpr int A::* A::p;