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 (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 *);
/* If REF is an lvalue, returns the kind of lvalue that REF is.
Otherwise, returns clk_none. */
-static cp_lvalue_kind
-lvalue_p_1 (const_tree ref)
+cp_lvalue_kind
+lvalue_kind (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));
+ return lvalue_kind (TREE_OPERAND (ref, 0));
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 0));
+ return lvalue_kind (TREE_OPERAND (ref, 0));
case COMPONENT_REF:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0));
+ op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
/* Look at the member designator. */
if (!op1_lvalue_kind)
;
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));
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1));
+ op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 0));
+ op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1));
break;
case COND_EXPR:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1)
+ op1_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 1)
? TREE_OPERAND (ref, 1)
: TREE_OPERAND (ref, 0));
- op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2));
+ op2_lvalue_kind = lvalue_kind (TREE_OPERAND (ref, 2));
break;
case MODIFY_EXPR:
return clk_ordinary;
case COMPOUND_EXPR:
- return lvalue_p_1 (TREE_OPERAND (ref, 1));
+ return lvalue_kind (TREE_OPERAND (ref, 1));
case TARGET_EXPR:
return clk_class;
with a BASELINK. */
/* 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)));
+ return lvalue_kind (BASELINK_FUNCTIONS (CONST_CAST_TREE (ref)));
case NON_DEPENDENT_EXPR:
/* We must consider NON_DEPENDENT_EXPRs to be lvalues so that
computes the C++ definition of lvalue. */
cp_lvalue_kind
-real_lvalue_p (tree ref)
+real_lvalue_p (const_tree ref)
{
- cp_lvalue_kind kind = lvalue_p_1 (ref);
+ cp_lvalue_kind kind = lvalue_kind (ref);
if (kind & (clk_rvalueref|clk_class))
return clk_none;
else
bool
lvalue_p (const_tree ref)
{
- return (lvalue_p_1 (ref) != clk_none);
+ return (lvalue_kind (ref) != clk_none);
}
/* This differs from real_lvalue_p in that rvalues formed by dereferencing
bool
lvalue_or_rvalue_with_address_p (const_tree ref)
{
- cp_lvalue_kind kind = lvalue_p_1 (ref);
+ cp_lvalue_kind kind = lvalue_kind (ref);
if (kind & clk_class)
return false;
else
if (TREE_CODE (rval) == AGGR_INIT_EXPR)
slot = AGGR_INIT_EXPR_SLOT (rval);
- else if (TREE_CODE (rval) == CALL_EXPR)
+ else if (TREE_CODE (rval) == CALL_EXPR
+ || TREE_CODE (rval) == CONSTRUCTOR)
slot = build_local_temp (type);
else
return rval;
return rval;
}
-/* Return a TARGET_EXPR which expresses the direct-initialization of one
- array from another. */
+/* Return a TARGET_EXPR which expresses the initialization of an array to
+ be named later, either default-initialization or copy-initialization
+ from another array of the same type. */
tree
-build_array_copy (tree init)
+build_vec_init_expr (tree type, tree init)
{
- tree type = TREE_TYPE (init);
- tree slot = build_local_temp (type);
+ tree slot;
+ tree inner_type = strip_array_types (type);
+
+ gcc_assert (init == NULL_TREE
+ || (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init))));
+
+ /* Since we're deferring building the actual constructor calls until
+ gimplification time, we need to build one now and throw it away so
+ that the relevant constructor gets mark_used before cgraph decides
+ what functions are needed. Here we assume that init is either
+ NULL_TREE or another array to copy. */
+ if (CLASS_TYPE_P (inner_type))
+ {
+ VEC(tree,gc) *argvec = make_tree_vector ();
+ if (init)
+ {
+ tree dummy = build_dummy_object (inner_type);
+ if (!real_lvalue_p (init))
+ dummy = move (dummy);
+ VEC_quick_push (tree, argvec, dummy);
+ }
+ build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &argvec, inner_type, LOOKUP_NORMAL,
+ tf_warning_or_error);
+ }
+
+ 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);
return init;
}
+tree
+build_array_copy (tree init)
+{
+ return build_vec_init_expr (TREE_TYPE (init), init);
+}
+
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
/* See if we already have an identically qualified type. Tests
should be equivalent to those in check_qualified_type. */
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
- if (cp_type_quals (t) == type_quals
+ if (TREE_TYPE (t) == element_type
&& TYPE_NAME (t) == TYPE_NAME (type)
&& TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
&& attribute_list_equal (TYPE_ATTRIBUTES (t),
return cp_build_qualified_type (result, cp_type_quals (t));
}
-/* Setup a TYPE_DECL node as a typedef representation.
- See comments of set_underlying_type in c-common.c. */
-
-void
-cp_set_underlying_type (tree t)
-{
- set_underlying_type (t);
- /* If T is a template type parm, make it require structural equality.
- This is useful when comparing two template type parms,
- because it forces the comparison of the template parameters of their
- decls. */
- if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
- SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
-}
-
-\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,
and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
/* Everything else has internal linkage. */
return lk_internal;
}
+
+/* Returns the storage duration of the object or reference associated with
+ the indicated DECL, which should be a VAR_DECL or PARM_DECL. */
+
+duration_kind
+decl_storage_duration (tree decl)
+{
+ if (TREE_CODE (decl) == PARM_DECL)
+ return dk_auto;
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return dk_static;
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ if (!TREE_STATIC (decl)
+ && !DECL_EXTERNAL (decl))
+ return dk_auto;
+ if (DECL_THREAD_LOCAL_P (decl))
+ return dk_thread;
+ return dk_static;
+}
\f
/* EXP is an expression that we want to pre-evaluate. Returns (in
*INITP) an expression that will perform the pre-evaluation. The
if (!TREE_SIDE_EFFECTS (exp))
init_expr = NULL_TREE;
- else if (!real_lvalue_p (exp)
- || !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp)))
+ /* There are no expressions with REFERENCE_TYPE, but there can be call
+ arguments with such a type; just treat it as a pointer. */
+ else if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE
+ || !lvalue_or_rvalue_with_address_p (exp))
{
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
}
else
{
+ bool xval = !real_lvalue_p (exp);
exp = cp_build_addr_expr (exp, tf_warning_or_error);
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
exp = cp_build_indirect_ref (exp, RO_NULL, tf_warning_or_error);
+ if (xval)
+ exp = move (exp);
}
*initp = init_expr;
cast_valid_in_integral_constant_expression_p (tree type)
{
return (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || cxx_dialect >= cxx0x
|| dependent_type_p (type)
|| type == error_mark_node);
}
&& ANON_AGGRNAME_P (name))
TYPE_NAME (t) = NULL_TREE;
}
+ if (TREE_CODE (t) == NAMESPACE_DECL)
+ {
+ /* The list of users of a namespace isn't useful for the middle-end
+ or debug generators. */
+ DECL_NAMESPACE_USERS (t) = NULL_TREE;
+ /* Neither do we need the leftover chaining of namespaces
+ from the binding level. */
+ DECL_CHAIN (t) = NULL_TREE;
+ }
}
/* Stub for c-common. Please keep in sync with c-decl.c.