summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-25 13:13:41 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2014-08-25 13:13:41 +0000
commit094dff73bfa24ca0a8949f8f758fc96aeb482217 (patch)
tree3e7b5b1d5c4243c51bae30e3103650541dbccb72
parent1ee1a97733078459782dfd038ca53e13a484b16a (diff)
downloadppe42-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/ChangeLog9
-rw-r--r--gcc/cp/class.c23
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c24
-rw-r--r--gcc/cp/expr.c8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C16
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[];
OpenPOWER on IntegriCloud