if (!want_pointer)
/* This must happen before the call to save_expr. */
- expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error);
+ expr = cp_build_addr_expr (expr, tf_warning_or_error);
else
expr = mark_rvalue_use (expr);
when processing a template because they do not handle C++-specific
trees. */
gcc_assert (!processing_template_decl);
- expr = cp_build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1,
- tf_warning_or_error);
+ expr = cp_build_addr_expr (expr, tf_warning_or_error);
if (!integer_zerop (BINFO_OFFSET (base)))
expr = fold_build2_loc (input_location,
POINTER_PLUS_EXPR, pointer_type, expr,
vtable entry is treated as a function pointer. */
if (TARGET_VTABLE_USES_DESCRIPTORS)
aref = build1 (NOP_EXPR, TREE_TYPE (aref),
- cp_build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1,
- tf_warning_or_error));
+ cp_build_addr_expr (aref, tf_warning_or_error));
/* Remember this as a method reference, for later devirtualization. */
aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx);
gcc_assert (COMPLETE_TYPE_P (basetype));
+ /* If any base class is non-literal, so is the derived class. */
+ if (!CLASSTYPE_LITERAL_P (basetype))
+ CLASSTYPE_LITERAL_P (t) = false;
+
/* Effective C++ rule 14. We only need to check TYPE_POLYMORPHIC_P
here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
+ }
+}
+
+/* Early variant fixups: we apply attributes at the beginning of the class
+ definition, and we need to fix up any variants that have already been
+ made via elaborated-type-specifier so that check_qualified_type works. */
+
+void
+fixup_attribute_variants (tree t)
+{
+ tree variants;
+
+ if (!t)
+ return;
- /* All variants of a class have the same attributes. */
+ for (variants = TYPE_NEXT_VARIANT (t);
+ variants;
+ variants = TYPE_NEXT_VARIANT (variants))
+ {
+ /* These are the two fields that check_qualified_type looks at and
+ are affected by attributes. */
TYPE_ATTRIBUTES (variants) = TYPE_ATTRIBUTES (t);
+ TYPE_ALIGN (variants) = TYPE_ALIGN (t);
}
}
-
\f
/* Set memoizing fields and bits of T (and its variants) for later
use. */
tree atype;
tree vtable;
- atype = build_cplus_array_type (vtable_entry_type,
- build_index_type (size_int (n - 1)));
+ atype = build_array_of_n_type (vtable_entry_type, n);
layout_type (atype);
/* We may have to grow the vtable. */
tree_pair_p p;
unsigned ix;
- for (ix = 0; VEC_iterate (tree_pair_s, indices, ix, p); ix++)
+ FOR_EACH_VEC_ELT (tree_pair_s, indices, ix, p)
if ((DECL_DESTRUCTOR_P (fn) && DECL_DESTRUCTOR_P (p->purpose))
|| same_signature_p (fn, p->purpose))
return p->value;
{
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
CLASSTYPE_LAZY_DEFAULT_CTOR (t) = 1;
+ if (cxx_dialect >= cxx0x)
+ TYPE_HAS_CONSTEXPR_CTOR (t)
+ = synthesized_default_constructor_is_constexpr (t);
}
/* [class.ctor]
STRIP_NOPS (w);
/* detect invalid field size. */
- w = integral_constant_value (w);
+ w = cxx_constant_value (w);
if (TREE_CODE (w) != INTEGER_CST)
{
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
CLASSTYPE_NON_AGGREGATE (t) = 1;
+ /* If at least one non-static data member is non-literal, the whole
+ class becomes non-literal. */
+ if (!literal_type_p (type))
+ CLASSTYPE_LITERAL_P (t) = false;
+
/* A standard-layout class is a class that:
...
has the same access control (Clause 11) for all non-static data members,
return false;
}
+/* Returns true iff for class T, a synthesized default constructor
+ would be constexpr. */
+
+bool
+synthesized_default_constructor_is_constexpr (tree t)
+{
+ /* A defaulted default constructor is constexpr
+ if there is nothing to initialize. */
+ /* FIXME adjust for non-static data member initializers. */
+ return is_really_empty_class (t);
+}
+
+/* Returns true iff class T has a constexpr default constructor. */
+
+bool
+type_has_constexpr_default_constructor (tree t)
+{
+ tree fns;
+
+ if (!CLASS_TYPE_P (t))
+ return false;
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+ return synthesized_default_constructor_is_constexpr (t);
+ fns = get_default_ctor (t);
+ return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
+}
+
/* Returns true iff class TYPE has a virtual destructor. */
bool
return has_two_argument_delete_p;
}
+/* Finish computing the `literal type' property of class type T.
+
+ At this point, we have already processed base classes and
+ non-static data members. We need to check whether the copy
+ constructor is trivial, the destructor is trivial, and there
+ is a trivial default constructor or at least one constexpr
+ constructor other than the copy constructor. */
+
+static void
+finalize_literal_type_property (tree t)
+{
+ if (cxx_dialect < cxx0x
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+ /* FIXME These constraints seem unnecessary; remove from standard.
+ || !TYPE_HAS_TRIVIAL_COPY_CTOR (t)
+ || TYPE_HAS_COMPLEX_MOVE_CTOR (t)*/ )
+ CLASSTYPE_LITERAL_P (t) = false;
+ else if (CLASSTYPE_LITERAL_P (t) && !TYPE_HAS_TRIVIAL_DFLT (t)
+ && !TYPE_HAS_CONSTEXPR_CTOR (t))
+ CLASSTYPE_LITERAL_P (t) = false;
+
+ if (!CLASSTYPE_LITERAL_P (t) && !CLASSTYPE_TEMPLATE_INSTANTIATION (t))
+ {
+ tree fn;
+ for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
+ if (DECL_DECLARED_CONSTEXPR_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn))
+ {
+ error ("enclosing class of %q+D is not a literal type", fn);
+ DECL_DECLARED_CONSTEXPR_P (fn) = false;
+ }
+ }
+}
+
/* Check the validity of the bases and members declared in T. Add any
implicitly-generated functions (like copy-constructors and
assignment operators). Compute various flag bits (like
CLASSTYPE_NON_AGGREGATE (t) = 1;
}
+ /* Compute the 'literal type' property before we
+ do anything with non-static member functions. */
+ finalize_literal_type_property (t);
+
/* Create the in-charge and not-in-charge variants of constructors
and destructors. */
clone_constructors_and_destructors (t);
CLASSTYPE_EMPTY_P (t) = 1;
CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
+ CLASSTYPE_LITERAL_P (t) = true;
/* Do end-of-class semantic processing: checking the validity of the
bases and members and add implicitly generated methods. */
}
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
- return cp_build_unary_op (ADDR_EXPR, fn, 0, flags);
+ return cp_build_addr_expr (fn, flags);
else
{
/* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
- cp_set_underlying_type (value);
+ set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);
}
/* Returns true if TYPE contains no actual data, just various
- possible combinations of empty classes. */
+ possible combinations of empty classes and possibly a vptr. */
bool
is_really_empty_class (tree type)
{
- if (is_empty_class (type))
- return true;
if (CLASS_TYPE_P (type))
{
tree field;
tree base_binfo;
int i;
+ /* CLASSTYPE_EMPTY_P isn't set properly until the class is actually laid
+ out, but we'd like to be able to check this before then. */
+ if (COMPLETE_TYPE_P (type) && is_empty_class (type))
+ return true;
+
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
if (!is_really_empty_class (BINFO_TYPE (base_binfo)))
= current_class_stack[current_class_depth - 1].names_used;
if (!names_used)
return;
-
+ /* The C language allows members to be declared with a type of the same
+ name, and the C++ standard says this diagnostic is not required. So
+ allow it in extern "C" blocks unless predantic is specified.
+ Allow it in all cases if -ms-extensions is specified. */
+ if ((!pedantic && current_lang_name == lang_name_c)
+ || flag_ms_extensions)
+ return;
n = splay_tree_lookup (names_used, (splay_tree_key) name);
if (n)
{
return;
/* Figure out the type of the VTT. */
- type = build_index_type (size_int (VEC_length (constructor_elt, inits) - 1));
- type = build_cplus_array_type (const_ptr_type_node, type);
+ type = build_array_of_n_type (const_ptr_type_node,
+ VEC_length (constructor_elt, inits));
/* Now, build the VTT object itself. */
vtt = build_vtable (t, mangle_vtt_for_type (t), type);
}
/* Figure out the type of the construction vtable. */
- type = build_index_type (size_int (VEC_length (constructor_elt, v) - 1));
- type = build_cplus_array_type (vtable_entry_type, type);
+ type = build_array_of_n_type (vtable_entry_type,
+ VEC_length (constructor_elt, v));
layout_type (type);
TREE_TYPE (vtbl) = type;
DECL_SIZE (vtbl) = DECL_SIZE_UNIT (vtbl) = NULL_TREE;
if (DECL_PURE_VIRTUAL_P (fn_original))
{
fn = abort_fndecl;
- if (abort_fndecl_addr == NULL)
- abort_fndecl_addr = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
- init = abort_fndecl_addr;
+ if (!TARGET_VTABLE_USES_DESCRIPTORS)
+ {
+ if (abort_fndecl_addr == NULL)
+ abort_fndecl_addr
+ = fold_convert (vfunc_ptr_type_node,
+ build_fold_addr_expr (fn));
+ init = abort_fndecl_addr;
+ }
}
else
{
}
/* Take the address of the function, considering it to be of an
appropriate generic type. */
- init = build1 (ADDR_EXPR, vfunc_ptr_type_node, fn);
+ if (!TARGET_VTABLE_USES_DESCRIPTORS)
+ init = fold_convert (vfunc_ptr_type_node,
+ build_fold_addr_expr (fn));
}
}
for (i = 0; i < TARGET_VTABLE_USES_DESCRIPTORS; ++i)
{
tree fdesc = build2 (FDESC_EXPR, vfunc_ptr_type_node,
- TREE_OPERAND (init, 0),
- build_int_cst (NULL_TREE, i));
+ fn, build_int_cst (NULL_TREE, i));
TREE_CONSTANT (fdesc) = 1;
CONSTRUCTOR_APPEND_ELT (*inits, NULL_TREE, fdesc);
signature as FN, then we do not need a second vcall offset.
Check the list of functions already present in the derived
class vtable. */
- for (i = 0; VEC_iterate (tree, vid->fns, i, derived_entry); ++i)
+ FOR_EACH_VEC_ELT (tree, vid->fns, i, derived_entry)
{
if (same_signature_p (derived_entry, orig_fn)
/* We only use one vcall offset for virtual destructors,