diff options
| author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-25 13:13:41 +0000 |
|---|---|---|
| committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-25 13:13:41 +0000 |
| commit | 094dff73bfa24ca0a8949f8f758fc96aeb482217 (patch) | |
| tree | 3e7b5b1d5c4243c51bae30e3103650541dbccb72 | |
| parent | 1ee1a97733078459782dfd038ca53e13a484b16a (diff) | |
| download | ppe42-gcc-094dff73bfa24ca0a8949f8f758fc96aeb482217.tar.gz ppe42-gcc-094dff73bfa24ca0a8949f8f758fc96aeb482217.zip | |
PR c++/62129
* class.c (outermost_open_class): New.
* cp-tree.h: Declare it.
* decl.c (maybe_register_incomplete_var): Use it.
(complete_vars): Handle any constant variable.
* expr.c (cplus_expand_constant): Handle CONSTRUCTOR.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_9-branch@214424 138bc75d-0d04-0410-961f-82ee72b054a4
| -rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
| -rw-r--r-- | gcc/cp/class.c | 23 | ||||
| -rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
| -rw-r--r-- | gcc/cp/decl.c | 24 | ||||
| -rw-r--r-- | gcc/cp/expr.c | 8 | ||||
| -rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C | 16 |
6 files changed, 71 insertions, 10 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index bb1068e0b2c..71a2d39e548 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2014-08-25 Jason Merrill <jason@redhat.com> + + PR c++/62129 + * class.c (outermost_open_class): New. + * cp-tree.h: Declare it. + * decl.c (maybe_register_incomplete_var): Use it. + (complete_vars): Handle any constant variable. + * expr.c (cplus_expand_constant): Handle CONSTRUCTOR. + 2014-08-22 Igor Zamyatin <igor.zamyatin@intel.com> PR other/62008 diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f4fb4c97290..042a43d2875 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -7251,6 +7251,29 @@ currently_open_derived_class (tree t) return NULL_TREE; } +/* Return the outermost enclosing class type that is still open, or + NULL_TREE. */ + +tree +outermost_open_class (void) +{ + if (!current_class_type) + return NULL_TREE; + tree r = NULL_TREE; + if (TYPE_BEING_DEFINED (current_class_type)) + r = current_class_type; + for (int i = current_class_depth - 1; i > 0; --i) + { + if (current_class_stack[i].hidden) + break; + tree t = current_class_stack[i].type; + if (!TYPE_BEING_DEFINED (t)) + break; + r = t; + } + return r; +} + /* Returns the innermost class type which is not a lambda closure type. */ tree diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 26a63d0b270..0b52dff3fdb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5112,6 +5112,7 @@ extern void resort_type_method_vec (void *, void *, extern bool add_method (tree, tree, tree); extern bool currently_open_class (tree); extern tree currently_open_derived_class (tree); +extern tree outermost_open_class (void); extern tree current_nonlambda_class_type (void); extern tree finish_struct (tree, tree); extern void finish_struct_1 (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 19944abd186..1f3a552f94f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -14177,8 +14177,8 @@ 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. - Also handle constexpr pointer to member variables where the initializer - is an unlowered PTRMEM_CST because the class isn't complete yet. */ + Also handle constexpr variables where the initializer involves + an unlowered PTRMEM_CST because the class isn't complete yet. */ void maybe_register_incomplete_var (tree var) @@ -14203,12 +14203,13 @@ 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) + else if (!(DECL_LANG_SPECIFIC (var) && DECL_TEMPLATE_INFO (var)) + && decl_constant_var_p (var) + && (TYPE_PTRMEM_P (inner_type) || CLASS_TYPE_P (inner_type))) { - tree context = TYPE_PTRMEM_CLASS_TYPE (inner_type); - gcc_assert (TYPE_BEING_DEFINED (context)); + /* When the outermost open class is complete we can resolve any + pointers-to-members. */ + tree context = outermost_open_class (); incomplete_var iv = {var, context}; vec_safe_push (incomplete_vars, iv); } @@ -14232,9 +14233,8 @@ complete_vars (tree type) tree var = iv->decl; tree type = TREE_TYPE (var); - if (TYPE_PTRMEM_P (type)) - DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var)); - else + if (TYPE_MAIN_VARIANT (strip_array_types (type)) + == iv->incomplete_type) { /* Complete the type of the variable. The VAR_DECL itself will be laid out in expand_expr. */ @@ -14242,6 +14242,10 @@ complete_vars (tree type) cp_apply_type_quals_to_decl (cp_type_quals (type), var); } + if (DECL_INITIAL (var) + && decl_constant_var_p (var)) + DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (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 a62e0f9b5df..99f8006fbd8 100644 --- a/gcc/cp/expr.c +++ b/gcc/cp/expr.c @@ -74,6 +74,14 @@ cplus_expand_constant (tree cst) } break; + case CONSTRUCTOR: + { + constructor_elt *elt; + unsigned HOST_WIDE_INT idx; + FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt) + elt->value = cplus_expand_constant (elt->value); + } + default: /* There's nothing to do. */ break; diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C new file mode 100644 index 00000000000..c5e2101c0e5 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C @@ -0,0 +1,16 @@ +// PR c++/62129 +// { dg-do compile { target c++11 } } + +class Evaluator +{ + int MakeChangelist (); + typedef int (Evaluator::*fac_t)(); + struct CreatorEntry + { + const char *type; + fac_t factory; + }; + static constexpr CreatorEntry kCreators[] = { "", &Evaluator::MakeChangelist }; +}; + +constexpr Evaluator::CreatorEntry Evaluator::kCreators[]; |

