aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-08-22 12:58:25 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-08-22 12:58:25 -0400
commit2d7d7f0fe49688f097720cd921ae65921034cd59 (patch)
treef630fb30ab136daa63badb4f992fceeb4416e73c /gcc
parent9b517712d78d2d457884dcf23519c7f65c3c28dd (diff)
downloadgcc-2d7d7f0fe49688f097720cd921ae65921034cd59.zip
gcc-2d7d7f0fe49688f097720cd921ae65921034cd59.tar.gz
gcc-2d7d7f0fe49688f097720cd921ae65921034cd59.tar.bz2
re PR c++/62129 (internal compiler error: in output_constant, at varasm.c:4755)
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. From-SVN: r214333
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/class.c21
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c17
-rw-r--r--gcc/cp/expr.c8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-ptrmem3.C16
6 files changed, 64 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8505e9c..8102054 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2014-08-22 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 c7ecf70..fd22930 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7132,6 +7132,27 @@ 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;
+ for (int i = current_class_depth; 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 64049c4..34373b7 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5154,6 +5154,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 cc54cca..2e4e7f8 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14311,8 +14311,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)
@@ -14337,12 +14337,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);
}
@@ -14366,7 +14367,7 @@ complete_vars (tree type)
tree var = iv->decl;
tree type = TREE_TYPE (var);
- if (TYPE_PTRMEM_P (type))
+ if (decl_constant_var_p (var))
DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var));
else
{
diff --git a/gcc/cp/expr.c b/gcc/cp/expr.c
index a62e0f9..99f8006 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 0000000..c5e2101
--- /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[];