+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
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
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);
/* 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)
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);
}
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
{
}
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;
--- /dev/null
+// 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[];