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.
\f
/* 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)
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);
+ }
}
}
{
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);
}
/* 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. */
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;
}
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)))