diff options
author | Jason Merrill <jason@redhat.com> | 2013-03-20 23:25:35 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-03-20 23:25:35 -0400 |
commit | deaae9d7c73f87cfd2a0125411fdc54824b5d410 (patch) | |
tree | 875a9ad5038acb1c7903c9adf6be0a805d2de46e | |
parent | 766053b33a997fb268791967df46c5c3f9f94a64 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/decl.c | 29 | ||||
-rw-r--r-- | gcc/cp/expr.c | 4 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 3 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-static11.C | 14 |
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; |