#include "target.h"
#include "convert.h"
#include "tree-flow.h"
+#include "cgraph.h"
static tree bot_manip (tree *, int *, void *);
static tree bot_replace (tree *, int *, void *);
static int list_hash_eq (const void *, const void *);
static hashval_t list_hash_pieces (tree, tree, tree);
static hashval_t list_hash (const void *);
-static cp_lvalue_kind lvalue_p_1 (tree, int);
+static cp_lvalue_kind lvalue_p_1 (const_tree);
static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
static tree handle_init_priority_attribute (tree *, tree, tree, int, bool *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
- Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
- nonzero, rvalues of class type are considered lvalues. */
+ Otherwise, returns clk_none. */
static cp_lvalue_kind
-lvalue_p_1 (tree ref,
- int treat_class_rvalues_as_lvalues)
+lvalue_p_1 (const_tree ref)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
if (TREE_CODE (ref) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
== REFERENCE_TYPE)
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{
&& TREE_CODE (ref) != PARM_DECL
&& TREE_CODE (ref) != VAR_DECL
&& TREE_CODE (ref) != COMPONENT_REF)
- {
- if (CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (ref))))
- return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
- else
- return clk_none;
- }
+ return clk_rvalueref;
/* lvalue references and named rvalue references are lvalues. */
return clk_ordinary;
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 0));
case COMPONENT_REF:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
/* Look at the member designator. */
if (!op1_lvalue_kind)
;
return clk_ordinary;
case CONST_DECL:
+ /* CONST_DECL without TREE_STATIC are enumeration values and
+ thus not lvalues. With TREE_STATIC they are used by ObjC++
+ in objc_build_string_object and need to be considered as
+ lvalues. */
+ if (! TREE_STATIC (ref))
+ return clk_none;
case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref)
if (TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 0))
|| TREE_SIDE_EFFECTS (TREE_OPERAND (ref, 1)))
return clk_none;
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
? TREE_OPERAND (ref, 1)
- : TREE_OPERAND (ref, 0),
- treat_class_rvalues_as_lvalues);
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
- treat_class_rvalues_as_lvalues);
+ : TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 1),
- treat_class_rvalues_as_lvalues);
+ return lvalue_p_1 (TREE_OPERAND (ref, 1));
case TARGET_EXPR:
- return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
+ return clk_class;
case VA_ARG_EXPR:
- return (treat_class_rvalues_as_lvalues
- && CLASS_TYPE_P (TREE_TYPE (ref))
- ? clk_class : clk_none);
+ return (CLASS_TYPE_P (TREE_TYPE (ref)) ? clk_class : clk_none);
case CALL_EXPR:
/* Any class-valued call would be wrapped in a TARGET_EXPR. */
case BASELINK:
/* We now represent a reference to a single static member function
with a BASELINK. */
- return lvalue_p_1 (BASELINK_FUNCTIONS (ref),
- treat_class_rvalues_as_lvalues);
+ /* This CONST_CAST is okay because BASELINK_FUNCTIONS returns
+ its argument unmodified and we assign it to a const_tree. */
+ return lvalue_p_1 (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
/* Otherwise, it's an lvalue, and it has all the odd properties
contributed by either operand. */
op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
- /* It's not an ordinary lvalue if it involves either a bit-field or
- a class rvalue. */
+ /* It's not an ordinary lvalue if it involves any other kind. */
if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
op1_lvalue_kind &= ~clk_ordinary;
+ /* It can't be both a pseudo-lvalue and a non-addressable lvalue.
+ A COND_EXPR of those should be wrapped in a TARGET_EXPR. */
+ if ((op1_lvalue_kind & (clk_rvalueref|clk_class))
+ && (op1_lvalue_kind & (clk_bitfield|clk_packed)))
+ op1_lvalue_kind = clk_none;
return op1_lvalue_kind;
}
cp_lvalue_kind
real_lvalue_p (tree ref)
{
- return lvalue_p_1 (ref,
- /*treat_class_rvalues_as_lvalues=*/0);
+ cp_lvalue_kind kind = lvalue_p_1 (ref);
+ if (kind & (clk_rvalueref|clk_class))
+ return clk_none;
+ else
+ return kind;
}
-/* This differs from real_lvalue_p in that class rvalues are
- considered lvalues. */
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
-int
-lvalue_p (tree ref)
+bool
+lvalue_p (const_tree ref)
+{
+ return (lvalue_p_1 (ref) != clk_none);
+}
+
+/* This differs from real_lvalue_p in that rvalues formed by dereferencing
+ rvalue references are considered rvalues. */
+
+bool
+lvalue_or_rvalue_with_address_p (const_tree ref)
{
- return
- (lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
+ cp_lvalue_kind kind = lvalue_p_1 (ref);
+ if (kind & clk_class)
+ return false;
+ else
+ return (kind != clk_none);
}
/* Test whether DECL is a builtin that may appear in a
static tree
build_local_temp (tree type)
{
- tree slot = build_decl (VAR_DECL, NULL_TREE, type);
+ tree slot = build_decl (input_location,
+ VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (slot) = 1;
DECL_IGNORED_P (slot) = 1;
DECL_CONTEXT (slot) = current_function_decl;
return rval;
}
+/* Return a TARGET_EXPR which expresses the direct-initialization of one
+ array from another. */
+
+tree
+build_array_copy (tree init)
+{
+ tree type = TREE_TYPE (init);
+ tree slot = build_local_temp (type);
+ init = build2 (VEC_INIT_EXPR, type, slot, init);
+ SET_EXPR_LOCATION (init, input_location);
+ init = build_target_expr (slot, init);
+ TARGET_EXPR_IMPLICIT_P (init) = 1;
+
+ return init;
+}
+
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
Non-class rvalues always have cv-unqualified types. */
type = TREE_TYPE (expr);
- if (!CLASS_TYPE_P (type) && cp_type_quals (type))
- type = TYPE_MAIN_VARIANT (type);
+ if (!CLASS_TYPE_P (type) && cv_qualified_p (type))
+ type = cv_unqualified (type);
- if (!processing_template_decl && real_lvalue_p (expr))
+ /* We need to do this for rvalue refs as well to get the right answer
+ from decltype; see c++/36628. */
+ if (!processing_template_decl && lvalue_or_rvalue_with_address_p (expr))
expr = build1 (NON_LVALUE_EXPR, type, expr);
else if (type != TREE_TYPE (expr))
expr = build_nop (type, expr);
else
{
/* Build a new array type. */
- t = make_node (ARRAY_TYPE);
+ t = cxx_make_type (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
if (TYPE_REF_IS_RVALUE (t))
return t;
- t = copy_node (lvalue_ref);
+ t = build_distinct_type_copy (lvalue_ref);
TYPE_REF_IS_RVALUE (t) = true;
TYPE_NEXT_REF_TO (t) = TYPE_NEXT_REF_TO (lvalue_ref);
TYPE_NEXT_REF_TO (lvalue_ref) = t;
- TYPE_MAIN_VARIANT (t) = t;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
}
+/* Returns EXPR cast to rvalue reference type, like std::move. */
+
+tree
+move (tree expr)
+{
+ tree type = TREE_TYPE (expr);
+ gcc_assert (TREE_CODE (type) != REFERENCE_TYPE);
+ type = cp_build_reference_type (type, /*rval*/true);
+ return build_static_cast (type, expr, tf_warning_or_error);
+}
+
/* Used by the C++ front end to build qualified array types. However,
the C version of this function does not properly maintain canonical
types (which are not used in C). */
&& (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result))
== TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type))))
TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) = NULL;
-
return result;
}
-/* Returns the canonical version of TYPE. In other words, if TYPE is
- a typedef, returns the underlying type. The cv-qualification of
- the type returned matches the type input; they will always be
- compatible types. */
+/* Return TYPE with const and volatile removed. */
tree
-canonical_type_variant (tree t)
+cv_unqualified (tree type)
+{
+ int quals = TYPE_QUALS (type);
+ quals &= ~(TYPE_QUAL_CONST|TYPE_QUAL_VOLATILE);
+ return cp_build_qualified_type (type, quals);
+}
+
+/* Builds a qualified variant of T that is not a typedef variant.
+ E.g. consider the following declarations:
+ typedef const int ConstInt;
+ typedef ConstInt* PtrConstInt;
+ If T is PtrConstInt, this function returns a type representing
+ const int*.
+ In other words, if T is a typedef, the function returns the underlying type.
+ The cv-qualification and attributes of the type returned match the
+ input type.
+ They will always be compatible types.
+ The returned type is built so that all of its subtypes
+ recursively have their typedefs stripped as well.
+
+ This is different from just returning TYPE_CANONICAL (T)
+ Because of several reasons:
+ * If T is a type that needs structural equality
+ its TYPE_CANONICAL (T) will be NULL.
+ * TYPE_CANONICAL (T) desn't carry type attributes
+ and looses template parameter names. */
+
+tree
+strip_typedefs (tree t)
{
- if (t == error_mark_node)
- return error_mark_node;
+ tree result = NULL, type = NULL, t0 = NULL;
+
+ if (!t || t == error_mark_node || t == TYPE_CANONICAL (t))
+ return t;
+
+ gcc_assert (TYPE_P (t));
+
+ switch (TREE_CODE (t))
+ {
+ case POINTER_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_pointer_type (type);
+ break;
+ case REFERENCE_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
+ break;
+ case OFFSET_TYPE:
+ t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t));
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_offset_type (t0, type);
+ break;
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ {
+ t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ result = build_ptrmemfunc_type (t0);
+ }
+ break;
+ case ARRAY_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ t0 = strip_typedefs (TYPE_DOMAIN (t));;
+ result = build_cplus_array_type (type, t0);
+ break;
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree arg_types = NULL, arg_node, arg_type;
+ for (arg_node = TYPE_ARG_TYPES (t);
+ arg_node;
+ arg_node = TREE_CHAIN (arg_node))
+ {
+ if (arg_node == void_list_node)
+ break;
+ arg_type = strip_typedefs (TREE_VALUE (arg_node));
+ gcc_assert (arg_type);
+
+ arg_types =
+ tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types);
+ }
+
+ if (arg_types)
+ arg_types = nreverse (arg_types);
+
+ /* A list of parameters not ending with an ellipsis
+ must end with void_list_node. */
+ if (arg_node)
+ arg_types = chainon (arg_types, void_list_node);
+
+ type = strip_typedefs (TREE_TYPE (t));
+ if (TREE_CODE (t) == METHOD_TYPE)
+ {
+ tree class_type = TREE_TYPE (TREE_VALUE (arg_types));
+ gcc_assert (class_type);
+ result =
+ build_method_type_directly (class_type, type,
+ TREE_CHAIN (arg_types));
+ }
+ else
+ result = build_function_type (type,
+ arg_types);
+
+ if (TYPE_RAISES_EXCEPTIONS (t))
+ result = build_exception_variant (result,
+ TYPE_RAISES_EXCEPTIONS (t));
+ }
+ break;
+ default:
+ break;
+ }
- return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
+ if (!result)
+ result = TYPE_MAIN_VARIANT (t);
+ if (TYPE_ATTRIBUTES (t))
+ result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
+ return cp_build_qualified_type (result, cp_type_quals (t));
}
+
+/* Returns true iff TYPE is a type variant created for a typedef. */
+
+bool
+typedef_variant_p (tree type)
+{
+ return is_typedef_decl (TYPE_NAME (type));
+}
+
\f
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
return error_mark_node;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
+ if (type)
+ t = convert_from_reference (t);
return t;
}
{
gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == COMPONENT_REF)
+ if (TREE_CODE (from) == OFFSET_REF
+ || TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
\f
#define PRINT_RING_SIZE 4
-const char *
-cxx_printable_name (tree decl, int v)
+static const char *
+cxx_printable_name_internal (tree decl, int v, bool translate)
{
static unsigned int uid_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
+ static bool trans_ring[PRINT_RING_SIZE];
static int ring_counter;
int i;
if (v < 2
|| TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
- return lang_decl_name (decl, v);
+ return lang_decl_name (decl, v, translate);
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
- if (uid_ring[i] == DECL_UID (decl))
+ if (uid_ring[i] == DECL_UID (decl) && translate == trans_ring[i])
/* yes, so return it. */
return print_ring[i];
if (current_function_decl != NULL_TREE)
{
- if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
- ring_counter += 1;
- if (ring_counter == PRINT_RING_SIZE)
- ring_counter = 0;
+ /* There may be both translated and untranslated versions of the
+ name cached. */
+ for (i = 0; i < 2; i++)
+ {
+ if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
+ ring_counter += 1;
+ if (ring_counter == PRINT_RING_SIZE)
+ ring_counter = 0;
+ }
gcc_assert (uid_ring[ring_counter] != DECL_UID (current_function_decl));
}
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
- print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
+ print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v, translate));
uid_ring[ring_counter] = DECL_UID (decl);
+ trans_ring[ring_counter] = translate;
return print_ring[ring_counter];
}
+
+const char *
+cxx_printable_name (tree decl, int v)
+{
+ return cxx_printable_name_internal (decl, v, false);
+}
+
+const char *
+cxx_printable_name_translate (tree decl, int v)
+{
+ return cxx_printable_name_internal (decl, v, true);
+}
\f
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
tree t2;
t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
- decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);
+ decl = build_decl (input_location,
+ TYPE_DECL, DECL_NAME (decl), NULL_TREE);
/* These nodes have to be created to reflect new TYPE_DECL and template
arguments. */
TEMPLATE_TYPE_PARM_INDEX (t2) = copy_node (TEMPLATE_TYPE_PARM_INDEX (t));
TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (t2)) = decl;
TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
- = tree_cons (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t),
- newargs, NULL_TREE);
+ = build_template_info (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (t), newargs);
TREE_TYPE (decl) = t2;
TYPE_NAME (t2) = decl;
/* Check if the type T depends on a type with no linkage and if so, return
it. If RELAXED_P then do not consider a class type declared within
- a TREE_PUBLIC function to have no linkage. */
+ a vague-linkage function to have no linkage. */
tree
no_linkage_check (tree t, bool relaxed_p)
switch (TREE_CODE (t))
{
- tree fn;
-
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
goto ptrmem;
+ /* Lambda types that don't have mangling scope have no linkage. We
+ check CLASSTYPE_LAMBDA_EXPR here rather than LAMBDA_TYPE_P because
+ when we get here from pushtag none of the lambda information is
+ set up yet, so we want to assume that the lambda has linkage and
+ fix it up later if not. */
+ if (CLASSTYPE_LAMBDA_EXPR (t)
+ && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE)
+ return t;
/* Fall through. */
case UNION_TYPE:
if (!CLASS_TYPE_P (t))
return NULL_TREE;
/* Fall through. */
case ENUMERAL_TYPE:
- if (TYPE_ANONYMOUS_P (t))
- return t;
- fn = decl_function_context (TYPE_MAIN_DECL (t));
- if (fn && (!relaxed_p || !TREE_PUBLIC (fn)))
+ /* Only treat anonymous types as having no linkage if they're at
+ namespace scope. This doesn't have a core issue number yet. */
+ if (TYPE_ANONYMOUS_P (t) && TYPE_NAMESPACE_SCOPE_P (t))
return t;
+
+ for (r = CP_TYPE_CONTEXT (t); ; )
+ {
+ /* If we're a nested type of a !TREE_PUBLIC class, we might not
+ have linkage, or we might just be in an anonymous namespace.
+ If we're in a TREE_PUBLIC class, we have linkage. */
+ if (TYPE_P (r) && !TREE_PUBLIC (TYPE_NAME (r)))
+ return no_linkage_check (TYPE_CONTEXT (t), relaxed_p);
+ else if (TREE_CODE (r) == FUNCTION_DECL)
+ {
+ if (!relaxed_p || !vague_linkage_fn_p (r))
+ return t;
+ else
+ r = CP_DECL_CONTEXT (r);
+ }
+ else
+ break;
+ }
+
return NULL_TREE;
case ARRAY_TYPE:
tree
array_type_nelts_top (tree type)
{
- return fold_build2 (PLUS_EXPR, sizetype,
+ return fold_build2_loc (input_location,
+ PLUS_EXPR, sizetype,
array_type_nelts (type),
size_one_node);
}
while (TREE_CODE (type) == ARRAY_TYPE)
{
tree n = array_type_nelts_top (type);
- sz = fold_build2 (MULT_EXPR, sizetype, sz, n);
+ sz = fold_build2_loc (input_location,
+ MULT_EXPR, sizetype, sz, n);
type = TREE_TYPE (type);
}
return sz;
built. */
tree
-build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
+build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
{
- tree t = build_nt_call_list (fn, arglist);
+ tree t = build_nt_call_vec (fn, argvec);
TREE_TYPE (t) = TREE_TYPE (non_dep);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
return t;
/* For comparing uses of parameters in late-specified return types
with an out-of-class definition of the function. */
if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
- && parm_index (t1) == parm_index (t2))
+ && DECL_PARM_INDEX (t1) == DECL_PARM_INDEX (t2))
return true;
else
return false;
case TEMPLATE_PARM_INDEX:
return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
+ && (TEMPLATE_PARM_PARAMETER_PACK (t1)
+ == TEMPLATE_PARM_PARAMETER_PACK (t2))
&& same_type_p (TREE_TYPE (TEMPLATE_PARM_DECL (t1)),
TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
&& TREE_OPERAND (ob, 0) == void_zero_node);
}
+/* Returns 1 iff type T is something we want to treat as a scalar type for
+ the purpose of deciding whether it is trivial/POD/standard-layout. */
+
+static bool
+scalarish_type_p (const_tree t)
+{
+ if (t == error_mark_node)
+ return 1;
+
+ return (SCALAR_TYPE_P (t)
+ || TREE_CODE (t) == VECTOR_TYPE);
+}
+
+/* Returns true iff T requires non-trivial default initialization. */
+
+bool
+type_has_nontrivial_default_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_DFLT (t);
+ else
+ return 0;
+}
+
+/* Returns true iff copying an object of type T is non-trivial. */
+
+bool
+type_has_nontrivial_copy_init (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return TYPE_HAS_COMPLEX_INIT_REF (t);
+ else
+ return 0;
+}
+
+/* Returns 1 iff type T is a trivial type, as defined in [basic.types]. */
+
+bool
+trivial_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return (TYPE_HAS_TRIVIAL_DFLT (t)
+ && TYPE_HAS_TRIVIAL_INIT_REF (t)
+ && TYPE_HAS_TRIVIAL_ASSIGN_REF (t)
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (t));
+ else
+ return scalarish_type_p (t);
+}
+
/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
-int
+bool
pod_type_p (const_tree t)
{
/* This CONST_CAST is okay because strip_array_types returns its
argument unmodified and we assign it to a const_tree. */
t = strip_array_types (CONST_CAST_TREE(t));
- if (t == error_mark_node)
- return 1;
- if (INTEGRAL_TYPE_P (t))
- return 1; /* integral, character or enumeral type */
- if (FLOAT_TYPE_P (t))
- return 1;
- if (TYPE_PTR_P (t))
- return 1; /* pointer to non-member */
- if (TYPE_PTR_TO_MEMBER_P (t))
- return 1; /* pointer to member */
-
- if (TREE_CODE (t) == VECTOR_TYPE)
- return 1; /* vectors are (small) arrays of scalars */
-
- if (! RECORD_OR_UNION_CODE_P (TREE_CODE (t)))
- return 0; /* other non-class type (reference or function) */
- if (! CLASS_TYPE_P (t))
- return 1; /* struct created by the back end */
- if (CLASSTYPE_NON_POD_P (t))
- return 0;
- return 1;
+ if (CLASS_TYPE_P (t))
+ /* [class]/10: A POD struct is a class that is both a trivial class and a
+ standard-layout class, and has no non-static data members of type
+ non-POD struct, non-POD union (or array of such types).
+
+ We don't need to check individual members because if a member is
+ non-std-layout or non-trivial, the class will be too. */
+ return (std_layout_type_p (t) && trivial_type_p (t));
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is POD for the purpose of layout, as defined in the
+ C++ ABI. */
+
+bool
+layout_pod_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_LAYOUT_POD_P (t);
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns true iff T is a standard-layout type, as defined in
+ [basic.types]. */
+
+bool
+std_layout_type_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return !CLASSTYPE_NON_STD_LAYOUT (t);
+ else
+ return scalarish_type_p (t);
}
/* Nonzero iff type T is a class template implicit specialization. */
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
- if (TREE_CODE (new_type) == FUNCTION_TYPE
+ if ((TREE_CODE (new_type) == FUNCTION_TYPE
+ || TREE_CODE (new_type) == METHOD_TYPE)
&& (TYPE_RAISES_EXCEPTIONS (new_type)
!= TYPE_RAISES_EXCEPTIONS (type)))
new_type = build_exception_variant (new_type,
DECL_LANG_SPECIFIC. */
if (DECL_COPY_CONSTRUCTOR_P (decl))
return sfk_copy_constructor;
+ if (DECL_MOVE_CONSTRUCTOR_P (decl))
+ return sfk_move_constructor;
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
template instantiations have internal linkage (in the object
file), but the symbols should still be treated as having external
linkage from the point of view of the language. */
- if (TREE_CODE (decl) != TYPE_DECL && DECL_LANG_SPECIFIC (decl)
+ if ((TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
&& DECL_COMDAT (decl))
return lk_external;
|| type == error_mark_node);
}
+/* Return true if we need to fix linkage information of DECL. */
+
+static bool
+cp_fix_function_decl_p (tree decl)
+{
+ /* Skip if DECL is not externally visible. */
+ if (!TREE_PUBLIC (decl))
+ return false;
+
+ /* We need to fix DECL if it a appears to be exported but with no
+ function body. Thunks do not have CFGs and we may need to
+ handle them specially later. */
+ if (!gimple_has_body_p (decl)
+ && !DECL_THUNK_P (decl)
+ && !DECL_EXTERNAL (decl))
+ {
+ struct cgraph_node *node = cgraph_get_node (decl);
+
+ /* Don't fix same_body aliases. Although they don't have their own
+ CFG, they share it with what they alias to. */
+ if (!node
+ || node->decl == decl
+ || !node->same_body)
+ return true;
+ }
+
+ return false;
+}
+
+/* Clean the C++ specific parts of the tree T. */
+
+void
+cp_free_lang_data (tree t)
+{
+ if (TREE_CODE (t) == METHOD_TYPE
+ || TREE_CODE (t) == FUNCTION_TYPE)
+ {
+ /* Default args are not interesting anymore. */
+ tree argtypes = TYPE_ARG_TYPES (t);
+ while (argtypes)
+ {
+ TREE_PURPOSE (argtypes) = 0;
+ argtypes = TREE_CHAIN (argtypes);
+ }
+ }
+ else if (TREE_CODE (t) == FUNCTION_DECL
+ && cp_fix_function_decl_p (t))
+ {
+ /* If T is used in this translation unit at all, the definition
+ must exist somewhere else since we have decided to not emit it
+ in this TU. So make it an external reference. */
+ DECL_EXTERNAL (t) = 1;
+ TREE_STATIC (t) = 0;
+ }
+ if (CP_AGGREGATE_TYPE_P (t)
+ && TYPE_NAME (t))
+ {
+ tree name = TYPE_NAME (t);
+ if (TREE_CODE (name) == TYPE_DECL)
+ name = DECL_NAME (name);
+ /* Drop anonymous names. */
+ if (name != NULL_TREE
+ && ANON_AGGRNAME_P (name))
+ TYPE_NAME (t) = NULL_TREE;
+ }
+}
+
\f
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree