/* Functions related to building classes and their related objects.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "hash-set.h"
+#include "machmode.h"
+#include "vec.h"
+#include "double-int.h"
+#include "input.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
+#include "wide-int.h"
+#include "inchash.h"
#include "tm.h"
#include "tree.h"
#include "stringpool.h"
#include "toplev.h"
#include "target.h"
#include "convert.h"
+#include "hash-map.h"
+#include "is-a.h"
+#include "plugin-api.h"
+#include "hard-reg-set.h"
+#include "input.h"
+#include "function.h"
+#include "ipa-ref.h"
#include "cgraph.h"
#include "dumpfile.h"
#include "splay-tree.h"
static tree get_vfield_name (tree);
static void finish_struct_anon (tree);
static tree get_vtable_name (tree);
-static tree get_basefndecls (tree, tree);
+static void get_basefndecls (tree, tree, vec<tree> *);
static int build_primary_vtable (tree, tree);
static int build_secondary_vtable (tree);
static void finish_vtbls (tree);
int want_pointer = TYPE_PTR_P (TREE_TYPE (expr));
bool has_empty = false;
bool virtual_access;
+ bool rvalue = false;
if (expr == error_mark_node || binfo == error_mark_node || !binfo)
return error_mark_node;
}
if (!want_pointer)
- /* This must happen before the call to save_expr. */
- expr = cp_build_addr_expr (expr, complain);
+ {
+ rvalue = !real_lvalue_p (expr);
+ /* This must happen before the call to save_expr. */
+ expr = cp_build_addr_expr (expr, complain);
+ }
else
expr = mark_rvalue_use (expr);
/* Don't bother with the calculations inside sizeof; they'll ICE if the
source type is incomplete and the pointer value doesn't matter. In a
- template (even in fold_non_dependent_expr), we don't have vtables set
- up properly yet, and the value doesn't matter there either; we're just
- interested in the result of overload resolution. */
+ template (even in instantiate_non_dependent_expr), we don't have vtables
+ set up properly yet, and the value doesn't matter there either; we're
+ just interested in the result of overload resolution. */
if (cp_unevaluated_operand != 0
|| in_template_function ())
{
expr = build_nop (ptr_target_type, expr);
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* If we're in an NSDMI, we don't have the full constructor context yet
{
expr = build1 (CONVERT_EXPR, ptr_target_type, expr);
CONVERT_EXPR_VBASE_PATH (expr) = true;
- if (!want_pointer)
- expr = build_indirect_ref (EXPR_LOCATION (expr), expr, RO_NULL);
- return expr;
+ goto indout;
}
/* Do we need to check for a null pointer? */
{
expr = cp_build_indirect_ref (expr, RO_NULL, complain);
expr = build_simple_base_path (expr, binfo);
+ if (rvalue)
+ expr = move (expr);
if (want_pointer)
expr = build_address (expr);
target_type = TREE_TYPE (expr);
v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
}
else
- v_offset = build_vfield_ref (cp_build_indirect_ref (expr, RO_NULL,
- complain),
- TREE_TYPE (TREE_TYPE (expr)));
-
+ {
+ tree t = expr;
+ if ((flag_sanitize & SANITIZE_VPTR) && fixed_type_p == 0)
+ {
+ t = cp_ubsan_maybe_instrument_cast_to_vbase (input_location,
+ probe, expr);
+ if (t == NULL_TREE)
+ t = expr;
+ }
+ v_offset = build_vfield_ref (cp_build_indirect_ref (t, RO_NULL,
+ complain),
+ TREE_TYPE (TREE_TYPE (expr)));
+ }
+
if (v_offset == error_mark_node)
return error_mark_node;
else
null_test = NULL;
+ indout:
if (!want_pointer)
- expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ {
+ expr = cp_build_indirect_ref (expr, RO_NULL, complain);
+ if (rvalue)
+ expr = move (expr);
+ }
out:
if (null_test)
alter_access (t, decl, access);
}
\f
-/* walk_tree callback for check_abi_tags: if the type at *TP involves any
- types with abi tags, add the corresponding identifiers to the VEC in
- *DATA and set IDENTIFIER_MARKED. */
+/* Data structure for find_abi_tags_r, below. */
struct abi_tag_data
{
- tree t;
- tree subob;
- // error_mark_node to get diagnostics; otherwise collect missing tags here
- tree tags;
+ tree t; // The type that we're checking for missing tags.
+ tree subob; // The subobject of T that we're getting tags from.
+ tree tags; // error_mark_node for diagnostics, or a list of missing tags.
};
+/* Subroutine of find_abi_tags_r. Handle a single TAG found on the class TP
+ in the context of P. TAG can be either an identifier (the DECL_NAME of
+ a tag NAMESPACE_DECL) or a STRING_CST (a tag attribute). */
+
+static void
+check_tag (tree tag, tree id, tree *tp, abi_tag_data *p)
+{
+ if (!IDENTIFIER_MARKED (id))
+ {
+ if (p->tags != error_mark_node)
+ {
+ /* We're collecting tags from template arguments or from
+ the type of a variable or function return type. */
+ p->tags = tree_cons (NULL_TREE, tag, p->tags);
+
+ /* Don't inherit this tag multiple times. */
+ IDENTIFIER_MARKED (id) = true;
+
+ if (TYPE_P (p->t))
+ {
+ /* Tags inherited from type template arguments are only used
+ to avoid warnings. */
+ ABI_TAG_IMPLICIT (p->tags) = true;
+ return;
+ }
+ /* For functions and variables we want to warn, too. */
+ }
+
+ /* Otherwise we're diagnosing missing tags. */
+ if (TREE_CODE (p->t) == FUNCTION_DECL)
+ {
+ if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
+ "that %qT (used in its return type) has",
+ p->t, tag, *tp))
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ else if (TREE_CODE (p->t) == VAR_DECL)
+ {
+ if (warning (OPT_Wabi_tag, "%qD inherits the %E ABI tag "
+ "that %qT (used in its type) has", p->t, tag, *tp))
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ else if (TYPE_P (p->subob))
+ {
+ if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
+ "that base %qT has", p->t, tag, p->subob))
+ inform (location_of (p->subob), "%qT declared here",
+ p->subob);
+ }
+ else
+ {
+ if (warning (OPT_Wabi_tag, "%qT does not have the %E ABI tag "
+ "that %qT (used in the type of %qD) has",
+ p->t, tag, *tp, p->subob))
+ {
+ inform (location_of (p->subob), "%qD declared here",
+ p->subob);
+ inform (location_of (*tp), "%qT declared here", *tp);
+ }
+ }
+ }
+}
+
+/* Find all the ABI tags in the attribute list ATTR and either call
+ check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
+
+static void
+mark_or_check_attr_tags (tree attr, tree *tp, abi_tag_data *p, bool val)
+{
+ if (!attr)
+ return;
+ for (; (attr = lookup_attribute ("abi_tag", attr));
+ attr = TREE_CHAIN (attr))
+ for (tree list = TREE_VALUE (attr); list;
+ list = TREE_CHAIN (list))
+ {
+ tree tag = TREE_VALUE (list);
+ tree id = get_identifier (TREE_STRING_POINTER (tag));
+ if (tp)
+ check_tag (tag, id, tp, p);
+ else
+ IDENTIFIER_MARKED (id) = val;
+ }
+}
+
+/* Find all the ABI tags on T and its enclosing scopes and either call
+ check_tag (if TP is non-null) or set IDENTIFIER_MARKED to val. */
+
+static void
+mark_or_check_tags (tree t, tree *tp, abi_tag_data *p, bool val)
+{
+ while (t != global_namespace)
+ {
+ tree attr;
+ if (TYPE_P (t))
+ {
+ attr = TYPE_ATTRIBUTES (t);
+ t = CP_TYPE_CONTEXT (t);
+ }
+ else
+ {
+ attr = DECL_ATTRIBUTES (t);
+ t = CP_DECL_CONTEXT (t);
+ }
+ mark_or_check_attr_tags (attr, tp, p, val);
+ }
+}
+
+/* walk_tree callback for check_abi_tags: if the type at *TP involves any
+ types with ABI tags, add the corresponding identifiers to the VEC in
+ *DATA and set IDENTIFIER_MARKED. */
+
static tree
find_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
{
anyway, but let's make sure of it. */
*walk_subtrees = false;
- if (tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (*tp)))
- {
- struct abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
- for (tree list = TREE_VALUE (attributes); list;
- list = TREE_CHAIN (list))
- {
- tree tag = TREE_VALUE (list);
- tree id = get_identifier (TREE_STRING_POINTER (tag));
- if (!IDENTIFIER_MARKED (id))
- {
- if (p->tags != error_mark_node)
- {
- /* We're collecting tags from template arguments. */
- tree str = build_string (IDENTIFIER_LENGTH (id),
- IDENTIFIER_POINTER (id));
- p->tags = tree_cons (NULL_TREE, str, p->tags);
- ABI_TAG_IMPLICIT (p->tags) = true;
-
- /* Don't inherit this tag multiple times. */
- IDENTIFIER_MARKED (id) = true;
- }
+ abi_tag_data *p = static_cast<struct abi_tag_data*>(data);
+
+ mark_or_check_tags (*tp, tp, p, false);
+
+ return NULL_TREE;
+}
+
+/* walk_tree callback for mark_abi_tags: if *TP is a class, set
+ IDENTIFIER_MARKED on its ABI tags. */
+
+static tree
+mark_abi_tags_r (tree *tp, int *walk_subtrees, void *data)
+{
+ if (!OVERLOAD_TYPE_P (*tp))
+ return NULL_TREE;
+
+ /* walk_tree shouldn't be walking into any subtrees of a RECORD_TYPE
+ anyway, but let's make sure of it. */
+ *walk_subtrees = false;
+
+ bool *valp = static_cast<bool*>(data);
+
+ mark_or_check_tags (*tp, NULL, NULL, *valp);
- /* Otherwise we're diagnosing missing tags. */
- else if (TYPE_P (p->subob))
- {
- if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
- "that base %qT has", p->t, tag, p->subob))
- inform (location_of (p->subob), "%qT declared here",
- p->subob);
- }
- else
- {
- if (warning (OPT_Wabi_tag, "%qT does not have the %E abi tag "
- "that %qT (used in the type of %qD) has",
- p->t, tag, *tp, p->subob))
- {
- inform (location_of (p->subob), "%qD declared here",
- p->subob);
- inform (location_of (*tp), "%qT declared here", *tp);
- }
- }
- }
- }
- }
return NULL_TREE;
}
-/* Set IDENTIFIER_MARKED on all the ABI tags on T and its (transitively
- complete) template arguments. */
+/* Set IDENTIFIER_MARKED on all the ABI tags on T and its enclosing
+ scopes. */
static void
-mark_type_abi_tags (tree t, bool val)
+mark_abi_tags (tree t, bool val)
{
- tree attributes = lookup_attribute ("abi_tag", TYPE_ATTRIBUTES (t));
- if (attributes)
+ mark_or_check_tags (t, NULL, NULL, val);
+ if (DECL_P (t))
{
- for (tree list = TREE_VALUE (attributes); list;
- list = TREE_CHAIN (list))
+ if (DECL_LANG_SPECIFIC (t) && DECL_USE_TEMPLATE (t)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
{
- tree tag = TREE_VALUE (list);
- tree id = get_identifier (TREE_STRING_POINTER (tag));
- IDENTIFIER_MARKED (id) = val;
+ /* Template arguments are part of the signature. */
+ tree level = INNERMOST_TEMPLATE_ARGS (DECL_TI_ARGS (t));
+ for (int j = 0; j < TREE_VEC_LENGTH (level); ++j)
+ {
+ tree arg = TREE_VEC_ELT (level, j);
+ cp_walk_tree_without_duplicates (&arg, mark_abi_tags_r, &val);
+ }
}
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ /* A function's parameter types are part of the signature, so
+ we don't need to inherit any tags that are also in them. */
+ for (tree arg = FUNCTION_FIRST_USER_PARMTYPE (t); arg;
+ arg = TREE_CHAIN (arg))
+ cp_walk_tree_without_duplicates (&TREE_VALUE (arg),
+ mark_abi_tags_r, &val);
}
}
-/* Check that class T has all the abi tags that subobject SUBOB has, or
- warn if not. */
+/* Check that T has all the ABI tags that subobject SUBOB has, or
+ warn if not. If T is a (variable or function) declaration, also
+ add any missing tags. */
static void
check_abi_tags (tree t, tree subob)
{
- mark_type_abi_tags (t, true);
+ bool inherit = DECL_P (t);
+
+ if (!inherit && !warn_abi_tag)
+ return;
+
+ tree decl = TYPE_P (t) ? TYPE_NAME (t) : t;
+ if (!TREE_PUBLIC (decl))
+ /* No need to worry about things local to this TU. */
+ return;
+
+ mark_abi_tags (t, true);
tree subtype = TYPE_P (subob) ? subob : TREE_TYPE (subob);
struct abi_tag_data data = { t, subob, error_mark_node };
+ if (inherit)
+ data.tags = NULL_TREE;
cp_walk_tree_without_duplicates (&subtype, find_abi_tags_r, &data);
- mark_type_abi_tags (t, false);
+ if (inherit && data.tags)
+ {
+ tree attr = lookup_attribute ("abi_tag", DECL_ATTRIBUTES (t));
+ if (attr)
+ TREE_VALUE (attr) = chainon (data.tags, TREE_VALUE (attr));
+ else
+ DECL_ATTRIBUTES (t)
+ = tree_cons (get_identifier ("abi_tag"), data.tags,
+ DECL_ATTRIBUTES (t));
+ }
+
+ mark_abi_tags (t, false);
+}
+
+/* Check that DECL has all the ABI tags that are used in parts of its type
+ that are not reflected in its mangled name. */
+
+void
+check_abi_tags (tree decl)
+{
+ if (TREE_CODE (decl) == VAR_DECL)
+ check_abi_tags (decl, TREE_TYPE (decl));
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && !mangle_return_type_p (decl))
+ check_abi_tags (decl, TREE_TYPE (TREE_TYPE (decl)));
}
void
inherit_targ_abi_tags (tree t)
{
- if (CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
+ if (!CLASS_TYPE_P (t)
+ || CLASSTYPE_TEMPLATE_INFO (t) == NULL_TREE)
return;
- mark_type_abi_tags (t, true);
+ mark_abi_tags (t, true);
tree args = CLASSTYPE_TI_ARGS (t);
struct abi_tag_data data = { t, NULL_TREE, NULL_TREE };
TYPE_ATTRIBUTES (t));
}
- mark_type_abi_tags (t, false);
+ mark_abi_tags (t, false);
}
/* Return true, iff class T has a non-virtual destructor that is
/* Copy whatever these are holding today. */
TYPE_VFIELD (variants) = TYPE_VFIELD (t);
- TYPE_METHODS (variants) = TYPE_METHODS (t);
TYPE_FIELDS (variants) = TYPE_FIELDS (t);
}
}
if (!t)
return;
+ tree attrs = TYPE_ATTRIBUTES (t);
+ unsigned align = TYPE_ALIGN (t);
+ bool user_align = TYPE_USER_ALIGN (t);
+
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);
+ TYPE_ATTRIBUTES (variants) = attrs;
+ unsigned valign = align;
+ if (TYPE_USER_ALIGN (variants))
+ valign = MAX (valign, TYPE_ALIGN (variants));
+ else
+ TYPE_USER_ALIGN (variants) = user_align;
+ TYPE_ALIGN (variants) = valign;
}
}
\f
/* Get the base virtual function declarations in T that have the
indicated NAME. */
-static tree
-get_basefndecls (tree name, tree t)
+static void
+get_basefndecls (tree name, tree t, vec<tree> *base_fndecls)
{
tree methods;
- tree base_fndecls = NULL_TREE;
int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
int i;
/* Find virtual functions in T with the indicated NAME. */
i = lookup_fnfields_1 (t, name);
+ bool found_decls = false;
if (i != -1)
for (methods = (*CLASSTYPE_METHOD_VEC (t))[i];
methods;
if (TREE_CODE (method) == FUNCTION_DECL
&& DECL_VINDEX (method))
- base_fndecls = tree_cons (NULL_TREE, method, base_fndecls);
+ {
+ base_fndecls->safe_push (method);
+ found_decls = true;
+ }
}
- if (base_fndecls)
- return base_fndecls;
+ if (found_decls)
+ return;
for (i = 0; i < n_baseclasses; i++)
{
tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
- base_fndecls = chainon (get_basefndecls (name, basetype),
- base_fndecls);
+ get_basefndecls (name, basetype, base_fndecls);
}
-
- return base_fndecls;
}
/* If this declaration supersedes the declaration of
{
DECL_VINDEX (decl) = decl;
overrides_found = true;
+ if (warn_override && !DECL_OVERRIDE_P (decl)
+ && !DECL_DESTRUCTOR_P (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wsuggest_override,
+ "%q+D can be marked override", decl);
}
if (DECL_VIRTUAL_P (decl))
tree fn;
tree name;
tree fndecl;
- tree base_fndecls;
tree base_binfo;
tree binfo;
int j;
have the same name. Figure out what name that is. */
name = DECL_NAME (OVL_CURRENT (fns));
/* There are no possibly hidden functions yet. */
- base_fndecls = NULL_TREE;
+ auto_vec<tree, 20> base_fndecls;
/* Iterate through all of the base classes looking for possibly
hidden functions. */
for (binfo = TYPE_BINFO (t), j = 0;
BINFO_BASE_ITERATE (binfo, j, base_binfo); j++)
{
tree basetype = BINFO_TYPE (base_binfo);
- base_fndecls = chainon (get_basefndecls (name, basetype),
- base_fndecls);
+ get_basefndecls (name, basetype, &base_fndecls);
}
/* If there are no functions to hide, continue. */
- if (!base_fndecls)
+ if (base_fndecls.is_empty ())
continue;
/* Remove any overridden functions. */
for (fn = fns; fn; fn = OVL_NEXT (fn))
{
fndecl = OVL_CURRENT (fn);
- if (DECL_VINDEX (fndecl))
+ if (TREE_CODE (fndecl) == FUNCTION_DECL
+ && DECL_VINDEX (fndecl))
{
- tree *prev = &base_fndecls;
-
- while (*prev)
/* If the method from the base class has the same
signature as the method from the derived class, it
has been overridden. */
- if (same_signature_p (fndecl, TREE_VALUE (*prev)))
- *prev = TREE_CHAIN (*prev);
- else
- prev = &TREE_CHAIN (*prev);
+ for (size_t k = 0; k < base_fndecls.length (); k++)
+ if (base_fndecls[k]
+ && same_signature_p (fndecl, base_fndecls[k]))
+ base_fndecls[k] = NULL_TREE;
}
}
/* Now give a warning for all base functions without overriders,
as they are hidden. */
- while (base_fndecls)
- {
- /* Here we know it is a hider, and no overrider exists. */
- warning (OPT_Woverloaded_virtual, "%q+D was hidden", TREE_VALUE (base_fndecls));
- warning (OPT_Woverloaded_virtual, " by %q+D", fns);
- base_fndecls = TREE_CHAIN (base_fndecls);
- }
+ size_t k;
+ tree base_fndecl;
+ FOR_EACH_VEC_ELT (base_fndecls, k, base_fndecl)
+ if (base_fndecl)
+ {
+ /* Here we know it is a hider, and no overrider exists. */
+ warning (OPT_Woverloaded_virtual, "%q+D was hidden", base_fndecl);
+ warning (OPT_Woverloaded_virtual, " by %q+D", fns);
+ }
}
}
parmlist = tree_cons (NULL_TREE, parms[i], parmlist);
tree fn = implicitly_declare_fn (sfk_inheriting_constructor,
t, false, ctor, parmlist);
+ gcc_assert (TYPE_MAIN_VARIANT (t) == t);
if (add_method (t, fn, NULL_TREE))
{
DECL_CHAIN (fn) = TYPE_METHODS (t);
TYPE_HAS_COPY_ASSIGN (t) = 1;
TYPE_HAS_CONST_COPY_ASSIGN (t) = !cant_have_const_assignment;
CLASSTYPE_LAZY_COPY_ASSIGN (t) = 1;
- if (move_ok)
+ if (move_ok && !LAMBDA_TYPE_P (t))
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
CLASSTYPE_NON_AGGREGATE (t) = 1;
/* If at least one non-static data member is non-literal, the whole
- class becomes non-literal. Note: if the type is incomplete we
- will complain later on. */
- if (COMPLETE_TYPE_P (type) && !literal_type_p (type))
+ class becomes non-literal. Per Core/1453, volatile non-static
+ data members and base classes are also not allowed.
+ Note: if the type is incomplete we will complain later on. */
+ if (COMPLETE_TYPE_P (type)
+ && (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type)))
CLASSTYPE_LITERAL_P (t) = false;
/* A standard-layout class is a class that:
CLASSTYPE_NON_STD_LAYOUT (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_REF_FIELDS_NEED_INIT (t, 1);
-
- /* ARM $12.6.2: [A member initializer list] (or, for an
- aggregate, initialization by a brace-enclosed list) is the
- only way to initialize nonstatic const and reference
- members. */
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ if (cxx_dialect < cxx11)
+ {
+ /* ARM $12.6.2: [A member initializer list] (or, for an
+ aggregate, initialization by a brace-enclosed list) is the
+ only way to initialize nonstatic const and reference
+ members. */
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
+ TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ }
}
type = strip_array_types (type);
/* Now that we've removed bit-field widths from DECL_INITIAL,
anything left in DECL_INITIAL is an NSDMI that makes the class
- non-aggregate. */
- if (DECL_INITIAL (x))
+ non-aggregate in C++11. */
+ if (DECL_INITIAL (x) && cxx_dialect < cxx14)
CLASSTYPE_NON_AGGREGATE (t) = true;
/* If any field is const, the structure type is pseudo-const. */
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
SET_CLASSTYPE_READONLY_FIELDS_NEED_INIT (t, 1);
-
- /* ARM $12.6.2: [A member initializer list] (or, for an
- aggregate, initialization by a brace-enclosed list) is the
- only way to initialize nonstatic const and reference
- members. */
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ if (cxx_dialect < cxx11)
+ {
+ /* ARM $12.6.2: [A member initializer list] (or, for an
+ aggregate, initialization by a brace-enclosed list) is the
+ only way to initialize nonstatic const and reference
+ members. */
+ TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
+ TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
+ }
}
/* A field that is pseudo-const makes the structure likewise. */
else if (CLASS_TYPE_P (type))
}
/* Note that this is an abstract function that is never emitted. */
- DECL_ABSTRACT (fn) = 1;
+ DECL_ABSTRACT_P (fn) = true;
}
/* DECL is an in charge constructor, which is being defined. This will
return false;
}
-/* Returns true iff class T has a user-provided default constructor. */
+/* Returns true iff class T has a non-user-provided (i.e. implicitly
+ declared or explicitly defaulted in the class body) default
+ constructor. */
bool
-type_has_user_provided_default_constructor (tree t)
+type_has_non_user_provided_default_constructor (tree t)
{
tree fns;
- if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+ if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t))
return false;
+ if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
+ return true;
for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == FUNCTION_DECL
- && user_provided_p (fn)
+ && !user_provided_p (fn)
&& sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (fn)))
return true;
}
type = strip_array_types (type);
if (!CLASS_TYPE_P (type))
return type;
- if (type_has_user_provided_default_constructor (type))
+ if (!type_has_non_user_provided_default_constructor (type))
return NULL_TREE;
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, t); ++i)
DECL_INITIAL (*fieldsp).
check_bitfield_decl eventually sets DECL_SIZE (*fieldsp)
to that width. */
- && integer_zerop (DECL_SIZE (*fieldsp)))
+ && (DECL_SIZE (*fieldsp) == NULL_TREE
+ || integer_zerop (DECL_SIZE (*fieldsp))))
*fieldsp = DECL_CHAIN (*fieldsp);
else
fieldsp = &DECL_CHAIN (*fieldsp);
inform (0, " %q+T is not an aggregate, does not have a trivial "
"default constructor, and has no constexpr constructor that "
"is not a copy or move constructor", t);
- if (TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
- && !type_has_user_provided_default_constructor (t))
+ if (type_has_non_user_provided_default_constructor (t))
{
/* Note that we can't simply call locate_ctor because when the
constructor is deleted it just returns NULL_TREE. */
if (CLASS_TYPE_P (ftype))
explain_non_literal_class (ftype);
}
+ if (CP_TYPE_VOLATILE_P (ftype))
+ inform (0, " non-static data member %q+D has "
+ "volatile type", field);
}
}
}
bool saved_nontrivial_dtor;
tree fn;
- /* Pick up any abi_tags from our template arguments before checking. */
- inherit_targ_abi_tags (t);
-
/* By default, we use const reference arguments and generate default
constructors. */
cant_have_const_ctor = 0;
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
+ /* If the only explicitly declared default constructor is user-provided,
+ set TYPE_HAS_COMPLEX_DFLT. */
+ if (!TYPE_HAS_COMPLEX_DFLT (t)
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
+ && !type_has_non_user_provided_default_constructor (t))
+ TYPE_HAS_COMPLEX_DFLT (t) = true;
+
/* Warn if a public base of a polymorphic type has an accessible
non-virtual destructor. It is only now that we know the class is
polymorphic. Although a polymorphic base will have a already
if (LAMBDA_TYPE_P (t))
{
- /* "The closure type associated with a lambda-expression has a deleted
- default constructor and a deleted copy assignment operator." */
- TYPE_NEEDS_CONSTRUCTING (t) = 1;
- TYPE_HAS_COMPLEX_DFLT (t) = 1;
- TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
- CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 0;
-
/* "This class type is not an aggregate." */
CLASSTYPE_NON_AGGREGATE (t) = 1;
}
padding = size_binop (MINUS_EXPR, DECL_SIZE (field),
TYPE_SIZE (integer_type));
}
-#ifdef PCC_BITFIELD_TYPE_MATTERS
+
/* An unnamed bitfield does not normally affect the
alignment of the containing class on a target where
PCC_BITFIELD_TYPE_MATTERS. But, the C++ ABI does not
was_unnamed_p = true;
DECL_NAME (field) = make_anon_name ();
}
-#endif
+
DECL_SIZE (field) = TYPE_SIZE (integer_type);
DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
DECL_USER_ALIGN (field) = TYPE_USER_ALIGN (integer_type);
/* This warning does not make sense for Java classes, since they
cannot have destructors. */
if (!TYPE_FOR_JAVA (t) && warn_nonvdtor
- && TYPE_POLYMORPHIC_P (t) && accessible_nvdtor_p (t))
+ && TYPE_POLYMORPHIC_P (t) && accessible_nvdtor_p (t)
+ && !CLASSTYPE_FINAL (t))
warning (OPT_Wnon_virtual_dtor,
"%q#T has virtual functions and accessible"
" non-virtual destructor", t);
if (f && TREE_CODE (TREE_TYPE (f)) == POINTER_TYPE)
{
f = next_initializable_field (DECL_CHAIN (f));
- if (f && TREE_CODE (TREE_TYPE (f)) == INTEGER_TYPE)
+ if (f && same_type_p (TREE_TYPE (f), size_type_node))
ok = true;
}
}
if (!ok)
- fatal_error ("definition of std::initializer_list does not match "
+ fatal_error (input_location,
+ "definition of std::initializer_list does not match "
"#include <initializer_list>");
}
tree fixed;
/* processing_template_decl can be false in a template if we're in
- fold_non_dependent_expr, but we still want to suppress this check. */
+ instantiate_non_dependent_expr, but we still want to suppress
+ this check. */
if (in_template_function ())
{
/* In a template we only care about the type of the result. */
static tree
resolve_address_of_overloaded_function (tree target_type,
tree overload,
- tsubst_flags_t flags,
+ tsubst_flags_t complain,
bool template_only,
tree explicit_targs,
tree access_path)
target_type = build_reference_type (target_type);
else
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("cannot resolve overloaded function %qD based on"
" conversion to type %qT",
DECL_NAME (OVL_FUNCTION (overload)), target_type);
if (matches == NULL_TREE)
{
/* There were *no* matches. */
- if (flags & tf_error)
+ if (complain & tf_error)
{
error ("no matches converting function %qD to type %q#T",
DECL_NAME (OVL_CURRENT (overload)),
if (match)
{
- if (flags & tf_error)
+ if (complain & tf_error)
{
error ("converting overloaded function %qD to type %q#T is ambiguous",
DECL_NAME (OVL_FUNCTION (overload)),
fn = TREE_PURPOSE (matches);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
- && !(flags & tf_ptrmem_ok) && !flag_ms_extensions)
+ && !(complain & tf_ptrmem_ok) && !flag_ms_extensions)
{
static int explained;
- if (!(flags & tf_error))
+ if (!(complain & tf_error))
return error_mark_node;
permerror (input_location, "assuming pointer to member %qD", fn);
if (fn == NULL)
return error_mark_node;
/* Mark all the versions corresponding to the dispatcher as used. */
- if (!(flags & tf_conv))
+ if (!(complain & tf_conv))
mark_versions_used (fn);
}
determining conversion sequences, we should not consider the
function used. If this conversion sequence is selected, the
function will be marked as used at this point. */
- if (!(flags & tf_conv))
+ if (!(complain & tf_conv))
{
/* Make =delete work with SFINAE. */
- if (DECL_DELETED_FN (fn) && !(flags & tf_error))
+ if (DECL_DELETED_FN (fn) && !(complain & tf_error))
+ return error_mark_node;
+ if (!mark_used (fn, complain) && !(complain & tf_error))
return error_mark_node;
-
- mark_used (fn);
}
/* We could not check access to member functions when this
if (DECL_FUNCTION_MEMBER_P (fn))
{
gcc_assert (access_path);
- perform_or_defer_access_check (access_path, fn, fn, flags);
+ perform_or_defer_access_check (access_path, fn, fn, complain);
}
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
- return cp_build_addr_expr (fn, flags);
+ return cp_build_addr_expr (fn, complain);
else
{
/* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op
/* This function will instantiate the type of the expression given in
RHS to match the type of LHSTYPE. If errors exist, then return
- error_mark_node. FLAGS is a bit mask. If TF_ERROR is set, then
+ error_mark_node. COMPLAIN is a bit mask. If TF_ERROR is set, then
we complain on errors. If we are not complaining, never modify rhs,
as overload resolution wants to try many possible instantiations, in
the hope that at least one will work.
function, or a pointer to member function. */
tree
-instantiate_type (tree lhstype, tree rhs, tsubst_flags_t flags)
+instantiate_type (tree lhstype, tree rhs, tsubst_flags_t complain)
{
- tsubst_flags_t flags_in = flags;
+ tsubst_flags_t complain_in = complain;
tree access_path = NULL_TREE;
- flags &= ~tf_ptrmem_ok;
+ complain &= ~tf_ptrmem_ok;
if (lhstype == unknown_type_node)
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("not enough type information");
return error_mark_node;
}
;
else
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("cannot convert %qE from type %qT to type %qT",
rhs, TREE_TYPE (rhs), fntype);
return error_mark_node;
deduce any type information. */
if (TREE_CODE (rhs) == NON_DEPENDENT_EXPR)
{
- if (flags & tf_error)
+ if (complain & tf_error)
error ("not enough type information");
return error_mark_node;
}
{
tree member = TREE_OPERAND (rhs, 1);
- member = instantiate_type (lhstype, member, flags);
+ member = instantiate_type (lhstype, member, complain);
if (member != error_mark_node
&& TREE_SIDE_EFFECTS (TREE_OPERAND (rhs, 0)))
/* Do not lose object's side effects. */
case OFFSET_REF:
rhs = TREE_OPERAND (rhs, 1);
if (BASELINK_P (rhs))
- return instantiate_type (lhstype, rhs, flags_in);
+ return instantiate_type (lhstype, rhs, complain_in);
/* This can happen if we are forming a pointer-to-member for a
member template. */
tree args = TREE_OPERAND (rhs, 1);
return
- resolve_address_of_overloaded_function (lhstype, fns, flags_in,
+ resolve_address_of_overloaded_function (lhstype, fns, complain_in,
/*template_only=*/true,
args, access_path);
}
case OVERLOAD:
case FUNCTION_DECL:
return
- resolve_address_of_overloaded_function (lhstype, rhs, flags_in,
+ resolve_address_of_overloaded_function (lhstype, rhs, complain_in,
/*template_only=*/false,
/*explicit_targs=*/NULL_TREE,
access_path);
case ADDR_EXPR:
{
if (PTRMEM_OK_P (rhs))
- flags |= tf_ptrmem_ok;
+ complain |= tf_ptrmem_ok;
- return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), flags);
+ return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
}
case ERROR_MARK: