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);
out:
if (null_test)
expr = fold_build3_loc (input_location, COND_EXPR, target_type, null_test, expr,
- fold_build1_loc (input_location, NOP_EXPR, target_type,
- integer_zero_node));
+ build_zero_cst (target_type));
return 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 (CLASSTYPE_FINAL (basetype))
+ error ("cannot derive from %<final%> base %qT in derived type %qT",
+ basetype, t);
+
+ /* 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;
{
tree main_binfo = TYPE_BINFO (BINFO_TYPE (b));
tree bv = chain_index (ix, BINFO_VIRTUALS (main_binfo));
- if (BINFO_LOST_PRIMARY_P (b))
- lost = true;
if (!DECL_THUNK_P (TREE_VALUE (bv)))
break;
+ if (BINFO_LOST_PRIMARY_P (b))
+ lost = true;
}
first_defn = b;
}
void
check_for_override (tree decl, tree ctype)
{
+ bool overrides_found = false;
if (TREE_CODE (decl) == TEMPLATE_DECL)
/* In [temp.mem] we have:
/* Set DECL_VINDEX to a value that is neither an INTEGER_CST nor
the error_mark_node so that we know it is an overriding
function. */
- DECL_VINDEX (decl) = decl;
+ {
+ DECL_VINDEX (decl) = decl;
+ overrides_found = true;
+ }
if (DECL_VIRTUAL_P (decl))
{
if (!DECL_VINDEX (decl))
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
+ if (DECL_DESTRUCTOR_P (decl))
+ TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true;
}
+ else if (DECL_FINAL_P (decl))
+ error ("%q+#D marked final, but is not virtual", decl);
+ if (DECL_OVERRIDE_P (decl) && !overrides_found)
+ error ("%q+#D marked override, but does not override", decl);
}
/* Warn about hidden virtual functions that are not overridden in t.
t, CLASSTYPE_DECL_LIST (type));
}
+/* This function is called from declare_virt_assop_and_dtor via
+ dfs_walk_all.
+
+ DATA is a type that direcly or indirectly inherits the base
+ represented by BINFO. If BINFO contains a virtual assignment [copy
+ assignment or move assigment] operator or a virtual constructor,
+ declare that function in DATA if it hasn't been already declared. */
+
+static tree
+dfs_declare_virt_assop_and_dtor (tree binfo, void *data)
+{
+ tree bv, fn, t = (tree)data;
+ tree opname = ansi_assopname (NOP_EXPR);
+
+ gcc_assert (t && CLASS_TYPE_P (t));
+ gcc_assert (binfo && TREE_CODE (binfo) == TREE_BINFO);
+
+ if (!TYPE_CONTAINS_VPTR_P (BINFO_TYPE (binfo)))
+ /* A base without a vtable needs no modification, and its bases
+ are uninteresting. */
+ return dfs_skip_bases;
+
+ if (BINFO_PRIMARY_P (binfo))
+ /* If this is a primary base, then we have already looked at the
+ virtual functions of its vtable. */
+ return NULL_TREE;
+
+ for (bv = BINFO_VIRTUALS (binfo); bv; bv = TREE_CHAIN (bv))
+ {
+ fn = BV_FN (bv);
+
+ if (DECL_NAME (fn) == opname)
+ {
+ if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
+ lazily_declare_fn (sfk_copy_assignment, t);
+ if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
+ lazily_declare_fn (sfk_move_assignment, t);
+ }
+ else if (DECL_DESTRUCTOR_P (fn)
+ && CLASSTYPE_LAZY_DESTRUCTOR (t))
+ lazily_declare_fn (sfk_destructor, t);
+ }
+
+ return NULL_TREE;
+}
+
+/* If the class type T has a direct or indirect base that contains a
+ virtual assignment operator or a virtual destructor, declare that
+ function in T if it hasn't been already declared. */
+
+static void
+declare_virt_assop_and_dtor (tree t)
+{
+ if (!(TYPE_POLYMORPHIC_P (t)
+ && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
+ || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
+ || CLASSTYPE_LAZY_DESTRUCTOR (t))))
+ return;
+
+ dfs_walk_all (TYPE_BINFO (t),
+ dfs_declare_virt_assop_and_dtor,
+ NULL, t);
+}
+
/* Create default constructors, assignment operators, and so forth for
the type indicated by T, if they are needed. CANT_HAVE_CONST_CTOR,
and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason,
{
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]
/* We can't be lazy about declaring functions that might override
a virtual function from a base class. */
- if (TYPE_POLYMORPHIC_P (t)
- && (CLASSTYPE_LAZY_COPY_ASSIGN (t)
- || CLASSTYPE_LAZY_MOVE_ASSIGN (t)
- || CLASSTYPE_LAZY_DESTRUCTOR (t)))
- {
- tree binfo = TYPE_BINFO (t);
- tree base_binfo;
- int ix;
- tree opname = ansi_assopname (NOP_EXPR);
- for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ++ix)
- {
- tree bv;
- for (bv = BINFO_VIRTUALS (base_binfo); bv; bv = TREE_CHAIN (bv))
- {
- tree fn = BV_FN (bv);
- if (DECL_NAME (fn) == opname)
- {
- if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
- lazily_declare_fn (sfk_copy_assignment, t);
- if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
- lazily_declare_fn (sfk_move_assignment, t);
- }
- else if (DECL_DESTRUCTOR_P (fn)
- && CLASSTYPE_LAZY_DESTRUCTOR (t))
- lazily_declare_fn (sfk_destructor, t);
- }
- }
- }
+ declare_virt_assop_and_dtor (t);
}
/* Subroutine of finish_struct_1. Recursively count the number of fields
}
else
{
+ location_t loc = input_location;
/* Avoid the non_lvalue wrapper added by fold for PLUS_EXPRs. */
STRIP_NOPS (w);
/* detect invalid field size. */
- w = integral_constant_value (w);
+ input_location = DECL_SOURCE_LOCATION (field);
+ w = cxx_constant_value (w);
+ input_location = loc;
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))
+ {
+ /* The caller should have stripped an enclosing array. */
+ gcc_assert (TREE_CODE (t) != ARRAY_TYPE);
+ return false;
+ }
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+ return synthesized_default_constructor_is_constexpr (t);
+ fns = locate_ctor (t);
+ return (fns && DECL_DECLARED_CONSTEXPR_P (fns));
+}
+
/* Returns true iff class TYPE has a virtual destructor. */
bool
return false;
}
+/* Nonzero if we need to build up a constructor call when initializing an
+ object of this class, either because it has a user-provided constructor
+ or because it doesn't have a default constructor (so we need to give an
+ error if no initializer is provided). Use TYPE_NEEDS_CONSTRUCTING when
+ what you care about is whether or not an object can be produced by a
+ constructor (e.g. so we don't set TREE_READONLY on const variables of
+ such type); use this function when what you care about is whether or not
+ to try to call a constructor to create an object. The latter case is
+ the former plus some cases of constructors that cannot be called. */
+
+bool
+type_build_ctor_call (tree t)
+{
+ tree inner;
+ if (TYPE_NEEDS_CONSTRUCTING (t))
+ return true;
+ inner = strip_array_types (t);
+ return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
+ && !ANON_AGGR_TYPE_P (inner));
+}
+
/* Remove all zero-width bit-fields from T. */
static void
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)
+{
+ tree fn;
+
+ 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))
+ for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn))
+ if (DECL_DECLARED_CONSTEXPR_P (fn)
+ && TREE_CODE (fn) != TEMPLATE_DECL
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && !DECL_CONSTRUCTOR_P (fn))
+ {
+ DECL_DECLARED_CONSTEXPR_P (fn) = false;
+ if (!DECL_TEMPLATE_INFO (fn))
+ error ("enclosing class of %q+#D is not a literal type", fn);
+ }
+}
+
/* 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. */
itself. */
if (TREE_CODE (instance) == VAR_DECL
&& DECL_INITIAL (instance)
+ && !type_dependent_expression_p_push (DECL_INITIAL (instance))
&& !htab_find (ht, instance))
{
tree type;
{
tree t = TREE_TYPE (instance);
int cdtorp = 0;
- tree fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
+ tree fixed;
+
+ if (processing_template_decl)
+ {
+ /* In a template we only care about the type of the result. */
+ if (nonnull)
+ *nonnull = true;
+ return true;
+ }
+
+ fixed = fixed_type_or_null (instance, nonnull, &cdtorp);
if (fixed == NULL_TREE)
return 0;
if (POINTER_TYPE_P (t))
DECL_NAME (OVL_CURRENT (overload)),
target_type);
- /* print_candidates expects a chain with the functions in
- TREE_VALUE slots, so we cons one up here (we're losing anyway,
- so why be clever?). */
- for (; overload; overload = OVL_NEXT (overload))
- matches = tree_cons (NULL_TREE, OVL_CURRENT (overload),
- matches);
-
- print_candidates (matches);
+ print_candidates (overload);
}
return error_mark_node;
}
}
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,
/* Find the overriding function. */
fn = find_final_overrider (vid->rtti_binfo, binfo, orig_fn);
if (fn == error_mark_node)
- vcall_offset = build1 (NOP_EXPR, vtable_entry_type,
- integer_zero_node);
+ vcall_offset = build_zero_cst (vtable_entry_type);
else
{
base = TREE_VALUE (fn);
CONSTRUCTOR_APPEND_ELT (vid->inits, NULL_TREE, init);
}
-/* Fold a OBJ_TYPE_REF expression to the address of a function.
- KNOWN_TYPE carries the true type of OBJ_TYPE_REF_OBJECT(REF). */
-
-tree
-cp_fold_obj_type_ref (tree ref, tree known_type)
-{
- HOST_WIDE_INT index = tree_low_cst (OBJ_TYPE_REF_TOKEN (ref), 1);
- HOST_WIDE_INT i = 0;
- tree v = BINFO_VIRTUALS (TYPE_BINFO (known_type));
- tree fndecl;
-
- while (i != index)
- {
- i += (TARGET_VTABLE_USES_DESCRIPTORS
- ? TARGET_VTABLE_USES_DESCRIPTORS : 1);
- v = TREE_CHAIN (v);
- }
-
- fndecl = BV_FN (v);
-
-#ifdef ENABLE_CHECKING
- gcc_assert (tree_int_cst_equal (OBJ_TYPE_REF_TOKEN (ref),
- DECL_VINDEX (fndecl)));
-#endif
-
- cgraph_node (fndecl)->local.vtable_method = true;
-
- return build_address (fndecl);
-}
-
#include "gt-cp-class.h"