/* Language-dependent node constructors for parse phase of GNU compiler.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
-#include "toplev.h"
#include "tree-inline.h"
#include "debug.h"
#include "convert.h"
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)
+ if (TREE_TYPE (ref)
+ && TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
{
/* unnamed rvalue references are rvalues */
if (TYPE_REF_IS_RVALUE (TREE_TYPE (ref))
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)
;
return clk_ordinary;
break;
- /* A currently unresolved scope ref. */
+ /* A scope ref in a template, left as SCOPE_REF to support later
+ access checking. */
case SCOPE_REF:
- gcc_unreachable ();
+ gcc_assert (!type_dependent_expression_p (CONST_CAST_TREE(ref)));
+ return lvalue_kind (TREE_OPERAND (ref, 1));
+
case MAX_EXPR:
case MIN_EXPR:
/* Disallow <? and >? as lvalues if either argument side-effects. */
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);
+ tree elt_init = integer_zero_node;
+ bool value_init = false;
+
+ /* 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, void_type_node (indicating value-initialization), or
+ another array to copy. */
+ if (integer_zerop (array_type_nelts_total (type)))
+ {
+ /* No actual initialization to do. */;
+ init = NULL_TREE;
+ }
+ else if (init == void_type_node)
+ {
+ elt_init = build_value_init (inner_type, tf_warning_or_error);
+ value_init = true;
+ init = NULL_TREE;
+ }
+ else
+ {
+ gcc_assert (init == NULL_TREE
+ || (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init))));
+
+ 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);
+ }
+ elt_init
+ = 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);
+
+ if (current_function_decl
+ && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+ {
+ if (potential_constant_expression (elt_init))
+ VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
+ else if (!processing_template_decl)
+ require_potential_constant_expression (elt_init);
+ }
+ VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
+
init = build_target_expr (slot, init);
TARGET_EXPR_IMPLICIT_P (init) = 1;
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. */
{
gcc_assert (!VOID_TYPE_P (type));
- if (TREE_CODE (init) == TARGET_EXPR)
+ if (TREE_CODE (init) == TARGET_EXPR
+ || init == error_mark_node)
return init;
else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
&& !VOID_TYPE_P (TREE_TYPE (init))
/* 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),
TYPE_RAISES_EXCEPTIONS (t));
}
break;
+ case TYPENAME_TYPE:
+ result = make_typename_type (strip_typedefs (TYPE_CONTEXT (t)),
+ TYPENAME_TYPE_FULLNAME (t),
+ typename_type, tf_none);
+ break;
default:
break;
}
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.
splay_tree target_remap = ((splay_tree) data);
tree t = *tp;
- if (!TYPE_P (t) && TREE_CONSTANT (t))
+ if (!TYPE_P (t) && TREE_CONSTANT (t) && !TREE_SIDE_EFFECTS (t))
{
/* There can't be any TARGET_EXPRs or their slot variables below
- this point. We used to check !TREE_SIDE_EFFECTS, but then we
- failed to copy an ADDR_EXPR of the slot VAR_DECL. */
+ this point. */
*walk_subtrees = 0;
return NULL_TREE;
}
BASELINK_FUNCTIONS (t2)));
case TEMPLATE_PARM_INDEX:
+ if (TEMPLATE_PARM_NUM_SIBLINGS (t1)
+ != TEMPLATE_PARM_NUM_SIBLINGS (t2))
+ return false;
return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
&& (TEMPLATE_PARM_PARAMETER_PACK (t1)
int
varargs_function_p (const_tree function)
{
- const_tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
- for (; parm; parm = TREE_CHAIN (parm))
- if (TREE_VALUE (parm) == void_type_node)
- return 0;
- return 1;
+ return stdarg_p (TREE_TYPE (function));
}
/* Returns 1 if decl is a member of a class. */
if (binfop)
*binfop = binfo;
- if (current_class_ref && context == current_class_type
- /* Kludge: Make sure that current_class_type is actually
- correct. It might not be if we're in the middle of
- tsubst_default_argument. */
- && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
- current_class_type))
+ if (current_class_ref
+ /* current_class_ref might not correspond to current_class_type if
+ we're in tsubst_default_argument or a lambda-declarator; in either
+ case, we want to use current_class_ref if it matches CONTEXT. */
+ && (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (current_class_ref), context)))
decl = current_class_ref;
else if (current != current_class_type
&& context == nonlambda_method_basetype ())
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
{
- gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE);
+ gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
+ || TREE_CODE (typea) == METHOD_TYPE);
return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
/* 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)))
+ else if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp))
+ || !lvalue_or_rvalue_with_address_p (exp))
{
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
}
else
{
- exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
+ 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.