/* 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
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010, 2011,
+ 2012 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
#include "tree.h"
#include "cp-tree.h"
#include "flags.h"
-#include "toplev.h"
#include "tree-inline.h"
#include "debug.h"
#include "convert.h"
-#include "tree-flow.h"
#include "cgraph.h"
#include "splay-tree.h"
+#include "gimple.h" /* gimple_has_body_p */
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 (const_tree);
-static tree build_target_expr (tree, tree);
+static tree build_target_expr (tree, tree, tsubst_flags_t);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
static tree build_local_temp (tree);
/* 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;
INDIRECT_REFs. INDIRECT_REFs are just internal compiler
representation, not part of the language, so we have to look
through them. */
- if (TREE_CODE (ref) == INDIRECT_REF
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0)))
- == REFERENCE_TYPE)
- return lvalue_p_1 (TREE_OPERAND (ref, 0));
+ if (REFERENCE_REF_P (ref))
+ 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))
&& TREE_CODE (ref) != PARM_DECL
&& TREE_CODE (ref) != VAR_DECL
- && TREE_CODE (ref) != COMPONENT_REF)
+ && TREE_CODE (ref) != COMPONENT_REF
+ /* Functions are always lvalues. */
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (ref))) != FUNCTION_TYPE)
return clk_rvalueref;
/* lvalue references and named rvalue references are lvalues. */
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)
;
&& DECL_IN_AGGR_P (ref))
return clk_none;
case INDIRECT_REF:
+ case ARROW_EXPR:
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
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 ();
+ {
+ tree op = TREE_OPERAND (ref, 1);
+ /* The member must be an lvalue; assume it isn't a bit-field. */
+ if (TREE_CODE (op) == IDENTIFIER_NODE)
+ return clk_ordinary;
+ gcc_assert (!type_dependent_expression_p (CONST_CAST_TREE (ref)));
+ return lvalue_kind (op);
+ }
+
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:
+ case TYPEID_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;
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. */
+ /* We can see calls outside of TARGET_EXPR in templates. */
+ if (CLASS_TYPE_P (TREE_TYPE (ref)))
+ return clk_class;
return clk_none;
case FUNCTION_DECL:
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
- things like "&E" where "E" is an expression with a
- non-dependent type work. It is safe to be lenient because an
- error will be issued when the template is instantiated if "E"
- is not an lvalue. */
- return clk_ordinary;
+ /* We just return clk_ordinary for NON_DEPENDENT_EXPR in C++98, but
+ in C++11 lvalues don't bind to rvalue references, so we need to
+ work harder to avoid bogus errors (c++/44870). */
+ if (cxx_dialect < cxx0x)
+ return clk_ordinary;
+ else
+ return lvalue_kind (TREE_OPERAND (ref, 0));
default:
+ if (!TREE_TYPE (ref))
+ return clk_none;
+ if (CLASS_TYPE_P (TREE_TYPE (ref)))
+ return clk_class;
break;
}
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
/* Build a TARGET_EXPR, initializing the DECL with the VALUE. */
static tree
-build_target_expr (tree decl, tree value)
+build_target_expr (tree decl, tree value, tsubst_flags_t complain)
{
tree t;
+ tree type = TREE_TYPE (decl);
#ifdef ENABLE_CHECKING
gcc_assert (VOID_TYPE_P (TREE_TYPE (value))
|| TREE_TYPE (decl) == TREE_TYPE (value)
+ /* On ARM ctors return 'this'. */
+ || (TREE_CODE (TREE_TYPE (value)) == POINTER_TYPE
+ && TREE_CODE (value) == CALL_EXPR)
|| useless_type_conversion_p (TREE_TYPE (decl),
TREE_TYPE (value)));
#endif
- t = build4 (TARGET_EXPR, TREE_TYPE (decl), decl, value,
- cxx_maybe_build_cleanup (decl), NULL_TREE);
+ t = cxx_maybe_build_cleanup (decl, complain);
+ if (t == error_mark_node)
+ return error_mark_node;
+ t = build4 (TARGET_EXPR, type, decl, value, t, NULL_TREE);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
ignore the TARGET_EXPR. If there really turn out to be no
side-effects, then the optimizer should be able to get rid of
whatever code is generated anyhow. */
TREE_SIDE_EFFECTS (t) = 1;
+ if (literal_type_p (type))
+ TREE_CONSTANT (t) = TREE_CONSTANT (value);
return t;
}
callable. */
tree
-build_aggr_init_expr (tree type, tree init)
+build_aggr_init_expr (tree type, tree init, tsubst_flags_t /*complain*/)
{
tree fn;
tree slot;
tree rval;
int is_ctor;
- /* Make sure that we're not trying to create an instance of an
- abstract class. */
- abstract_virtuals_error (NULL_TREE, type);
-
if (TREE_CODE (init) == CALL_EXPR)
fn = CALL_EXPR_FN (init);
else if (TREE_CODE (init) == AGGR_INIT_EXPR)
AGGR_INIT_EXPR_ARGP (init));
TREE_SIDE_EFFECTS (rval) = 1;
AGGR_INIT_VIA_CTOR_P (rval) = is_ctor;
+ TREE_NOTHROW (rval) = TREE_NOTHROW (init);
}
else
rval = init;
and language-specific expression expanders. */
tree
-build_cplus_new (tree type, tree init)
+build_cplus_new (tree type, tree init, tsubst_flags_t complain)
{
- tree rval = build_aggr_init_expr (type, init);
+ tree rval = build_aggr_init_expr (type, init, complain);
tree slot;
+ /* Make sure that we're not trying to create an instance of an
+ abstract class. */
+ if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+ return error_mark_node;
+
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;
- rval = build_target_expr (slot, rval);
- TARGET_EXPR_IMPLICIT_P (rval) = 1;
+ rval = build_target_expr (slot, rval, complain);
+
+ if (rval != error_mark_node)
+ TARGET_EXPR_IMPLICIT_P (rval) = 1;
return rval;
}
-/* Return a TARGET_EXPR which expresses the direct-initialization of one
- array from another. */
+/* Subroutine of build_vec_init_expr: Build up a single element
+ intialization as a proxy for the full array initialization to get things
+ marked as used and any appropriate diagnostics.
+
+ 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. */
+
+static tree
+build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
+{
+ tree inner_type = strip_array_types (type);
+ VEC(tree,gc) *argvec;
+
+ if (integer_zerop (array_type_nelts_total (type))
+ || !CLASS_TYPE_P (inner_type))
+ /* No interesting initialization to do. */
+ return integer_zero_node;
+ else if (init == void_type_node)
+ return build_value_init (inner_type, complain);
+
+ gcc_assert (init == NULL_TREE
+ || (same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (init))));
+
+ argvec = make_tree_vector ();
+ if (init)
+ {
+ tree init_type = strip_array_types (TREE_TYPE (init));
+ tree dummy = build_dummy_object (init_type);
+ if (!real_lvalue_p (init))
+ dummy = move (dummy);
+ VEC_quick_push (tree, argvec, dummy);
+ }
+ init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &argvec, inner_type, LOOKUP_NORMAL,
+ complain);
+ release_tree_vector (argvec);
+
+ /* For a trivial constructor, build_over_call creates a TARGET_EXPR. But
+ we don't want one here because we aren't creating a temporary. */
+ if (TREE_CODE (init) == TARGET_EXPR)
+ init = TARGET_EXPR_INITIAL (init);
+
+ return init;
+}
+
+/* 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, tsubst_flags_t complain)
{
- tree type = TREE_TYPE (init);
- tree slot = build_local_temp (type);
+ tree slot;
+ bool value_init = false;
+ tree elt_init = build_vec_init_elt (type, init, complain);
+
+ if (init == void_type_node)
+ {
+ value_init = true;
+ init = NULL_TREE;
+ }
+
+ slot = build_local_temp (type);
init = build2 (VEC_INIT_EXPR, type, slot, init);
+ TREE_SIDE_EFFECTS (init) = true;
SET_EXPR_LOCATION (init, input_location);
- init = build_target_expr (slot, init);
- TARGET_EXPR_IMPLICIT_P (init) = 1;
+
+ if (cxx_dialect >= cxx0x
+ && potential_constant_expression (elt_init))
+ VEC_INIT_EXPR_IS_CONSTEXPR (init) = true;
+ VEC_INIT_EXPR_VALUE_INIT (init) = value_init;
return init;
}
+/* Give a helpful diagnostic for a non-constexpr VEC_INIT_EXPR in a context
+ that requires a constant expression. */
+
+void
+diagnose_non_constexpr_vec_init (tree expr)
+{
+ tree type = TREE_TYPE (VEC_INIT_EXPR_SLOT (expr));
+ tree init, elt_init;
+ if (VEC_INIT_EXPR_VALUE_INIT (expr))
+ init = void_type_node;
+ else
+ init = VEC_INIT_EXPR_INIT (expr);
+
+ elt_init = build_vec_init_elt (type, init, tf_warning_or_error);
+ require_potential_constant_expression (elt_init);
+}
+
+tree
+build_array_copy (tree init)
+{
+ return build_vec_init_expr (TREE_TYPE (init), init, tf_warning_or_error);
+}
+
/* Build a TARGET_EXPR using INIT to initialize a new temporary of the
indicated TYPE. */
tree
-build_target_expr_with_type (tree init, tree type)
+build_target_expr_with_type (tree init, tree type, tsubst_flags_t complain)
{
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_TRIVIAL_INIT_REF (type)
+ else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
&& !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
another one here. A CONSTRUCTOR is aggregate initialization, which
is handled separately. A VA_ARG_EXPR is magic creation of an
aggregate; there's no additional work to be done. */
- return force_rvalue (init);
+ return force_rvalue (init, complain);
- return force_target_expr (type, init);
+ return force_target_expr (type, init, complain);
}
/* Like the above function, but without the checking. This function should
only be used by code which is deliberately trying to subvert the type
- system, such as call_builtin_trap. */
+ system, such as call_builtin_trap. Or build_over_call, to avoid
+ infinite recursion. */
tree
-force_target_expr (tree type, tree init)
+force_target_expr (tree type, tree init, tsubst_flags_t complain)
{
tree slot;
gcc_assert (!VOID_TYPE_P (type));
slot = build_local_temp (type);
- return build_target_expr (slot, init);
+ return build_target_expr (slot, init, complain);
}
/* Like build_target_expr_with_type, but use the type of INIT. */
tree
-get_target_expr (tree init)
+get_target_expr_sfinae (tree init, tsubst_flags_t complain)
{
if (TREE_CODE (init) == AGGR_INIT_EXPR)
- return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init);
+ return build_target_expr (AGGR_INIT_EXPR_SLOT (init), init, complain);
+ else if (TREE_CODE (init) == VEC_INIT_EXPR)
+ return build_target_expr (VEC_INIT_EXPR_SLOT (init), init, complain);
else
- return build_target_expr_with_type (init, TREE_TYPE (init));
+ return build_target_expr_with_type (init, TREE_TYPE (init), complain);
+}
+
+tree
+get_target_expr (tree init)
+{
+ return get_target_expr_sfinae (init, tf_warning_or_error);
}
/* If EXPR is a bitfield reference, convert it to the declared type of
}
}
else
- t = build_array_type (elt_type, index_type);
+ {
+ if (!TYPE_STRUCTURAL_EQUALITY_P (elt_type)
+ && !(index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type))
+ && (TYPE_CANONICAL (elt_type) != elt_type
+ || (index_type && TYPE_CANONICAL (index_type) != index_type)))
+ /* Make sure that the canonical type is on the appropriate
+ variants list. */
+ build_cplus_array_type
+ (TYPE_CANONICAL (elt_type),
+ index_type ? TYPE_CANONICAL (index_type) : index_type);
+ t = build_array_type (elt_type, index_type);
+ }
/* We want TYPE_MAIN_VARIANT of an array to strip cv-quals from the
element type as well, so fix it up if needed. */
{
tree m = build_cplus_array_type (TYPE_MAIN_VARIANT (elt_type),
index_type);
+
if (TYPE_MAIN_VARIANT (t) != m)
{
TYPE_MAIN_VARIANT (t) = m;
/* 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),
* 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. */
+ and loses template parameter names. */
tree
strip_typedefs (tree 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;
+ case DECLTYPE_TYPE:
+ result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
+ if (result == DECLTYPE_TYPE_EXPR (t))
+ return t;
+ else
+ result = (finish_decltype_type
+ (result,
+ DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t),
+ tf_none));
+ break;
default:
break;
}
if (!result)
result = TYPE_MAIN_VARIANT (t);
+ if (TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (result)
+ || TYPE_ALIGN (t) != TYPE_ALIGN (result))
+ {
+ gcc_assert (TYPE_USER_ALIGN (t));
+ if (TYPE_ALIGN (t) == TYPE_ALIGN (result))
+ result = build_variant_type_copy (result);
+ else
+ result = build_aligned_type (result, TYPE_ALIGN (t));
+ TYPE_USER_ALIGN (result) = true;
+ }
if (TYPE_ATTRIBUTES (t))
result = cp_build_type_attribute_variant (result, 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. */
+/* Like strip_typedefs above, but works on expressions, so that in
-void
-cp_set_underlying_type (tree t)
+ template<class T> struct A
+ {
+ typedef T TT;
+ B<sizeof(TT)> b;
+ };
+
+ sizeof(TT) is replaced by sizeof(T). */
+
+tree
+strip_typedefs_expr (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));
+ unsigned i,n;
+ tree r, type, *ops;
+ enum tree_code code;
+
+ if (t == NULL_TREE || t == error_mark_node)
+ return t;
+
+ if (DECL_P (t) || CONSTANT_CLASS_P (t))
+ return t;
+
+ /* Some expressions have type operands, so let's handle types here rather
+ than check TYPE_P in multiple places below. */
+ if (TYPE_P (t))
+ return strip_typedefs (t);
+
+ code = TREE_CODE (t);
+ switch (code)
+ {
+ case IDENTIFIER_NODE:
+ case TEMPLATE_PARM_INDEX:
+ case OVERLOAD:
+ case BASELINK:
+ case ARGUMENT_PACK_SELECT:
+ return t;
+
+ case TRAIT_EXPR:
+ {
+ tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t));
+ tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t));
+ if (type1 == TRAIT_EXPR_TYPE1 (t)
+ && type2 == TRAIT_EXPR_TYPE2 (t))
+ return t;
+ r = copy_node (t);
+ TRAIT_EXPR_TYPE1 (t) = type1;
+ TRAIT_EXPR_TYPE2 (t) = type2;
+ return r;
+ }
+
+ case TREE_LIST:
+ {
+ VEC(tree,gc) *vec = make_tree_vector ();
+ bool changed = false;
+ tree it;
+ for (it = t; it; it = TREE_CHAIN (it))
+ {
+ tree val = strip_typedefs_expr (TREE_VALUE (t));
+ VEC_safe_push (tree, gc, vec, val);
+ if (val != TREE_VALUE (t))
+ changed = true;
+ gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
+ }
+ if (changed)
+ {
+ r = NULL_TREE;
+ FOR_EACH_VEC_ELT_REVERSE (tree, vec, i, it)
+ r = tree_cons (NULL_TREE, it, r);
+ }
+ else
+ r = t;
+ release_tree_vector (vec);
+ return r;
+ }
+
+ case TREE_VEC:
+ {
+ bool changed = false;
+ VEC(tree,gc)* vec = make_tree_vector ();
+ n = TREE_VEC_LENGTH (t);
+ VEC_reserve (tree, gc, vec, n);
+ for (i = 0; i < n; ++i)
+ {
+ tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i));
+ VEC_quick_push (tree, vec, op);
+ if (op != TREE_VEC_ELT (t, i))
+ changed = true;
+ }
+ if (changed)
+ {
+ r = copy_node (t);
+ for (i = 0; i < n; ++i)
+ TREE_VEC_ELT (r, i) = VEC_index (tree, vec, i);
+ }
+ else
+ r = t;
+ release_tree_vector (vec);
+ return r;
+ }
+
+ case CONSTRUCTOR:
+ {
+ bool changed = false;
+ VEC(constructor_elt,gc) *vec
+ = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
+ n = CONSTRUCTOR_NELTS (t);
+ type = strip_typedefs (TREE_TYPE (t));
+ for (i = 0; i < n; ++i)
+ {
+ constructor_elt *e = VEC_index (constructor_elt, vec, i);
+ tree op = strip_typedefs_expr (e->value);
+ if (op != e->value)
+ {
+ changed = true;
+ e->value = op;
+ }
+ gcc_checking_assert (e->index == strip_typedefs_expr (e->index));
+ }
+
+ if (!changed && type == TREE_TYPE (t))
+ {
+ VEC_free (constructor_elt, gc, vec);
+ return t;
+ }
+ else
+ {
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ CONSTRUCTOR_ELTS (r) = vec;
+ return r;
+ }
+ }
+
+ case LAMBDA_EXPR:
+ gcc_unreachable ();
+
+ default:
+ break;
+ }
+
+ gcc_assert (EXPR_P (t));
+
+ n = TREE_OPERAND_LENGTH (t);
+ ops = XALLOCAVEC (tree, n);
+ type = TREE_TYPE (t);
+
+ switch (code)
+ {
+ CASE_CONVERT:
+ case IMPLICIT_CONV_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CAST_EXPR:
+ case NEW_EXPR:
+ type = strip_typedefs (type);
+ /* fallthrough */
+
+ default:
+ for (i = 0; i < n; ++i)
+ ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i));
+ break;
+ }
+
+ /* If nothing changed, return t. */
+ for (i = 0; i < n; ++i)
+ if (ops[i] != TREE_OPERAND (t, i))
+ break;
+ if (i == n && type == TREE_TYPE (t))
+ return t;
+
+ r = copy_node (t);
+ TREE_TYPE (r) = type;
+ for (i = 0; i < n; ++i)
+ TREE_OPERAND (r, i) = ops[i];
+ return r;
}
-\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.
TREE_CHAIN (*igo_prev) = new_binfo;
*igo_prev = new_binfo;
- if (binfo)
+ if (binfo && !BINFO_DEPENDENT_BASE_P (binfo))
{
int ix;
tree base_binfo;
- gcc_assert (!BINFO_DEPENDENT_BASE_P (binfo));
gcc_assert (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), type));
BINFO_OFFSET (new_binfo) = BINFO_OFFSET (binfo);
for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++)
{
tree new_base_binfo;
-
- gcc_assert (!BINFO_DEPENDENT_BASE_P (base_binfo));
new_base_binfo = copy_binfo (base_binfo, BINFO_TYPE (base_binfo),
t, igo_prev,
BINFO_VIRTUAL_P (base_binfo));
return error_mark_node;
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
+ PTRMEM_OK_P (t) = true;
if (type)
t = convert_from_reference (t);
return t;
|| TREE_CODE (x) == OVERLOAD);
}
+/* X is the CALL_EXPR_FN of a CALL_EXPR. If X represents a dependent name
+ (14.6.2), return the IDENTIFIER_NODE for that name. Otherwise, return
+ NULL_TREE. */
+
+tree
+dependent_name (tree x)
+{
+ if (TREE_CODE (x) == IDENTIFIER_NODE)
+ return x;
+ if (TREE_CODE (x) != COMPONENT_REF
+ && TREE_CODE (x) != OFFSET_REF
+ && TREE_CODE (x) != BASELINK
+ && is_overloaded_fn (x))
+ return DECL_NAME (get_first_fn (x));
+ return NULL_TREE;
+}
+
/* Returns true iff X is an expression for an overloaded function
whose type cannot be known without performing overload
resolution. */
{
if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
return decl;
- if (chain && TREE_CODE (chain) != OVERLOAD)
- chain = ovl_cons (chain, NULL_TREE);
return ovl_cons (decl, chain);
}
+/* Return the scope where the overloaded functions OVL were found. */
+
+tree
+ovl_scope (tree ovl)
+{
+ if (TREE_CODE (ovl) == OFFSET_REF
+ || TREE_CODE (ovl) == COMPONENT_REF)
+ ovl = TREE_OPERAND (ovl, 1);
+ if (TREE_CODE (ovl) == BASELINK)
+ return BINFO_TYPE (BASELINK_BINFO (ovl));
+ if (TREE_CODE (ovl) == TEMPLATE_ID_EXPR)
+ ovl = TREE_OPERAND (ovl, 0);
+ /* Skip using-declarations. */
+ while (TREE_CODE (ovl) == OVERLOAD && OVL_USED (ovl) && OVL_CHAIN (ovl))
+ ovl = OVL_CHAIN (ovl);
+ return CP_DECL_CONTEXT (OVL_CURRENT (ovl));
+}
+
+/* Return TRUE if FN is a non-static member function, FALSE otherwise.
+ This function looks into BASELINK and OVERLOAD nodes. */
+
+bool
+non_static_member_function_p (tree fn)
+{
+ if (fn == NULL_TREE)
+ return false;
+
+ if (is_overloaded_fn (fn))
+ fn = get_first_fn (fn);
+
+ return (DECL_P (fn)
+ && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn));
+}
+
\f
#define PRINT_RING_SIZE 4
gcc_assert (uid_ring[ring_counter] != DECL_UID (current_function_decl));
}
- if (print_ring[ring_counter])
- free (print_ring[ring_counter]);
+ free (print_ring[ring_counter]);
print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v, translate));
uid_ring[ring_counter] = DECL_UID (decl);
tree
build_exception_variant (tree type, tree raises)
{
- tree v = TYPE_MAIN_VARIANT (type);
- int type_quals = TYPE_QUALS (type);
+ tree v;
+ int type_quals;
- for (; v; v = TYPE_NEXT_VARIANT (v))
+ if (comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (type), ce_exact))
+ return type;
+
+ type_quals = TYPE_QUALS (type);
+ for (v = TYPE_MAIN_VARIANT (type); v; v = TYPE_NEXT_VARIANT (v))
if (check_qualified_type (v, type, type_quals)
- && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), 1))
+ && comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (v), ce_exact))
return v;
/* Need to build a new variant. */
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. */
+ /* There can't be any TARGET_EXPRs or their slot variables below this
+ point. But we must make a copy, in case subsequent processing
+ alters any part of it. For example, during gimplification a cast
+ of the form (T) &X::f (where "f" is a member function) will lead
+ to replacing the PTRMEM_CST for &X::f with a VAR_DECL. */
*walk_subtrees = 0;
+ *tp = unshare_expr (t);
return NULL_TREE;
}
if (TREE_CODE (t) == TARGET_EXPR)
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1));
+ {
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
+ if (AGGR_INIT_ZERO_FIRST (TREE_OPERAND (t, 1)))
+ AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
+ }
else
- u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
+ u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
+ tf_warning_or_error);
+
+ TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t);
+ TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t);
+ TARGET_EXPR_DIRECT_INIT_P (u) = TARGET_EXPR_DIRECT_INIT_P (t);
/* Map the old variable to the new one. */
splay_tree_insert (target_remap,
}
/* Make a copy of this node. */
- return copy_tree_r (tp, walk_subtrees, NULL);
+ t = copy_tree_r (tp, walk_subtrees, NULL);
+ if (TREE_CODE (*tp) == CALL_EXPR)
+ set_flags_from_callee (*tp);
+ return t;
}
/* Replace all remapped VAR_DECLs in T with their new equivalents.
if (n)
*t = (tree) n->value;
}
+ else if (TREE_CODE (*t) == PARM_DECL
+ && DECL_NAME (*t) == this_identifier)
+ {
+ /* In an NSDMI we need to replace the 'this' parameter we used for
+ parsing with the real one for this function. */
+ *t = current_class_ptr;
+ }
+ else if (TREE_CODE (*t) == CONVERT_EXPR
+ && CONVERT_EXPR_VBASE_PATH (*t))
+ {
+ /* In an NSDMI build_base_path defers building conversions to virtual
+ bases, and we handle it here. */
+ tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (*t)));
+ VEC(tree,gc) *vbases = CLASSTYPE_VBASECLASSES (current_class_type);
+ int i; tree binfo;
+ FOR_EACH_VEC_ELT (tree, vbases, i, binfo)
+ if (BINFO_TYPE (binfo) == basetype)
+ break;
+ *t = build_base_path (PLUS_EXPR, TREE_OPERAND (*t, 0), binfo, true,
+ tf_warning_or_error);
+ }
return NULL_TREE;
}
/* When we parse a default argument expression, we may create
temporary variables via TARGET_EXPRs. When we actually use the
- default-argument expression, we make a copy of the expression, but
- we must replace the temporaries with appropriate local versions. */
+ default-argument expression, we make a copy of the expression
+ and replace the temporaries with appropriate local versions. */
tree
break_out_target_exprs (tree t)
va_start (p, non_dep);
+ if (REFERENCE_REF_P (non_dep))
+ non_dep = TREE_OPERAND (non_dep, 0);
+
t = make_node (code);
length = TREE_CODE_LENGTH (code);
TREE_TYPE (t) = TREE_TYPE (non_dep);
COMPOUND_EXPR_OVERLOADED (t) = 1;
va_end (p);
- return t;
+ return convert_from_reference (t);
}
/* Similar to `build_nt_call_vec', but for template definitions of
build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
{
tree t = build_nt_call_vec (fn, argvec);
+ if (REFERENCE_REF_P (non_dep))
+ non_dep = TREE_OPERAND (non_dep, 0);
TREE_TYPE (t) = TREE_TYPE (non_dep);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
- return t;
+ return convert_from_reference (t);
}
tree
}
}
+/* Subroutine of cp_tree_equal: t1 and t2 are the CALL_EXPR_FNs of two
+ CALL_EXPRS. Return whether they are equivalent. */
+
+static bool
+called_fns_equal (tree t1, tree t2)
+{
+ /* Core 1321: dependent names are equivalent even if the overload sets
+ are different. But do compare explicit template arguments. */
+ tree name1 = dependent_name (t1);
+ tree name2 = dependent_name (t2);
+ if (name1 || name2)
+ {
+ tree targs1 = NULL_TREE, targs2 = NULL_TREE;
+
+ if (name1 != name2)
+ return false;
+
+ if (TREE_CODE (t1) == TEMPLATE_ID_EXPR)
+ targs1 = TREE_OPERAND (t1, 1);
+ if (TREE_CODE (t2) == TEMPLATE_ID_EXPR)
+ targs2 = TREE_OPERAND (t2, 1);
+ return cp_tree_equal (targs1, targs2);
+ }
+ else
+ return cp_tree_equal (t1, t2);
+}
+
/* Return truthvalue of whether T1 is the same tree structure as T2.
Return 1 if they are the same. Return 0 if they are different. */
/* We need to do this when determining whether or not two
non-type pointer to member function template arguments
are the same. */
- if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
- /* The first operand is RTL. */
- && TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
+ if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+ || CONSTRUCTOR_NELTS (t1) != CONSTRUCTOR_NELTS (t2))
return false;
- return cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1));
+ {
+ tree field, value;
+ unsigned int i;
+ FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t1), i, field, value)
+ {
+ constructor_elt *elt2 = CONSTRUCTOR_ELT (t2, i);
+ if (!cp_tree_equal (field, elt2->index)
+ || !cp_tree_equal (value, elt2->value))
+ return false;
+ }
+ }
+ return true;
case TREE_LIST:
if (!cp_tree_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2)))
{
tree arg1, arg2;
call_expr_arg_iterator iter1, iter2;
- if (!cp_tree_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
+ if (!called_fns_equal (CALL_EXPR_FN (t1), CALL_EXPR_FN (t2)))
return false;
for (arg1 = first_call_expr_arg (t1, &iter1),
arg2 = first_call_expr_arg (t2, &iter2);
case PARM_DECL:
/* 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))
- && DECL_PARM_INDEX (t1) == DECL_PARM_INDEX (t2))
- return true;
- else
- return false;
+ with an out-of-class definition of the function, but can also come
+ up for expressions that involve 'this' in a member function
+ template. */
+ if (same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ {
+ if (DECL_ARTIFICIAL (t1) ^ DECL_ARTIFICIAL (t2))
+ return false;
+ if (DECL_ARTIFICIAL (t1)
+ || (DECL_PARM_LEVEL (t1) == DECL_PARM_LEVEL (t2)
+ && DECL_PARM_INDEX (t1) == DECL_PARM_INDEX (t2)))
+ return true;
+ }
+ return false;
case VAR_DECL:
case CONST_DECL:
+ case FIELD_DECL:
case FUNCTION_DECL:
case TEMPLATE_DECL:
case IDENTIFIER_NODE:
case BASELINK:
return (BASELINK_BINFO (t1) == BASELINK_BINFO (t2)
&& BASELINK_ACCESS_BINFO (t1) == BASELINK_ACCESS_BINFO (t2)
+ && BASELINK_QUALIFIED_P (t1) == BASELINK_QUALIFIED_P (t2)
&& cp_tree_equal (BASELINK_FUNCTIONS (t1),
BASELINK_FUNCTIONS (t2)));
TREE_TYPE (TEMPLATE_PARM_DECL (t2))));
case TEMPLATE_ID_EXPR:
+ return (cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
+ && cp_tree_equal (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
+
+ case TREE_VEC:
{
unsigned ix;
- tree vec1, vec2;
-
- if (!cp_tree_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)))
+ if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
return false;
- vec1 = TREE_OPERAND (t1, 1);
- vec2 = TREE_OPERAND (t2, 1);
-
- if (!vec1 || !vec2)
- return !vec1 && !vec2;
-
- if (TREE_VEC_LENGTH (vec1) != TREE_VEC_LENGTH (vec2))
- return false;
-
- for (ix = TREE_VEC_LENGTH (vec1); ix--;)
- if (!cp_tree_equal (TREE_VEC_ELT (vec1, ix),
- TREE_VEC_ELT (vec2, ix)))
+ for (ix = TREE_VEC_LENGTH (t1); ix--;)
+ if (!cp_tree_equal (TREE_VEC_ELT (t1, ix),
+ TREE_VEC_ELT (t2, ix)))
return false;
-
return true;
}
return same_type_p (TRAIT_EXPR_TYPE1 (t1), TRAIT_EXPR_TYPE1 (t2))
&& same_type_p (TRAIT_EXPR_TYPE2 (t1), TRAIT_EXPR_TYPE2 (t2));
+ case CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
+ case NEW_EXPR:
+ if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+ return false;
+ /* Now compare operands as usual. */
+ break;
+
+ case DEFERRED_NOEXCEPT:
+ return (cp_tree_equal (DEFERRED_NOEXCEPT_PATTERN (t1),
+ DEFERRED_NOEXCEPT_PATTERN (t2))
+ && comp_template_args (DEFERRED_NOEXCEPT_ARGS (t1),
+ DEFERRED_NOEXCEPT_ARGS (t2)));
+ break;
+
default:
break;
}
{
int i, n;
- n = TREE_OPERAND_LENGTH (t1);
+ n = cp_tree_operand_length (t1);
if (TREE_CODE_CLASS (code1) == tcc_vl_exp
&& n != TREE_OPERAND_LENGTH (t2))
return false;
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 ())
/* In a lambda, need to go through 'this' capture. */
- decl = (cp_build_indirect_ref
+ decl = (build_x_indirect_ref
((lambda_expr_this_capture
(CLASSTYPE_LAMBDA_EXPR (current_class_type))),
RO_NULL, tf_warning_or_error));
return 0;
}
-/* Returns true iff copying an object of type T is non-trivial. */
+/* Returns true iff copying an object of type T (including via move
+ constructor) is non-trivial. That is, T has no non-trivial copy
+ constructors and no non-trivial move constructors. */
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);
+ {
+ gcc_assert (COMPLETE_TYPE_P (t));
+ return ((TYPE_HAS_COPY_CTOR (t)
+ && TYPE_HAS_COMPLEX_COPY_CTOR (t))
+ || TYPE_HAS_COMPLEX_MOVE_CTOR (t));
+ }
else
return 0;
}
-/* Returns 1 iff type T is a trivial type, as defined in [basic.types]. */
+/* Returns 1 iff type T is a trivially copyable type, as defined in
+ [basic.types] and [class]. */
+
+bool
+trivially_copyable_p (const_tree t)
+{
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (CLASS_TYPE_P (t))
+ return ((!TYPE_HAS_COPY_CTOR (t)
+ || !TYPE_HAS_COMPLEX_COPY_CTOR (t))
+ && !TYPE_HAS_COMPLEX_MOVE_CTOR (t)
+ && (!TYPE_HAS_COPY_ASSIGN (t)
+ || !TYPE_HAS_COMPLEX_COPY_ASSIGN (t))
+ && !TYPE_HAS_COMPLEX_MOVE_ASSIGN (t)
+ && TYPE_HAS_TRIVIAL_DESTRUCTOR (t));
+ else
+ return scalarish_type_p (t);
+}
+
+/* Returns 1 iff type T is a trivial type, as defined in [basic.types] and
+ [class]. */
bool
trivial_type_p (const_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));
+ && trivially_copyable_p (t));
else
return scalarish_type_p (t);
}
/* Table of valid C++ attributes. */
const struct attribute_spec cxx_attribute_table[] =
{
- /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- { "java_interface", 0, 0, false, false, false, handle_java_interface_attribute },
- { "com_interface", 0, 0, false, false, false, handle_com_interface_attribute },
- { "init_priority", 1, 1, true, false, false, handle_init_priority_attribute },
- { NULL, 0, 0, false, false, false, NULL }
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
+ affects_type_identity } */
+ { "java_interface", 0, 0, false, false, false,
+ handle_java_interface_attribute, false },
+ { "com_interface", 0, 0, false, false, false,
+ handle_com_interface_attribute, false },
+ { "init_priority", 1, 1, true, false, false,
+ handle_init_priority_attribute, false },
+ { NULL, 0, 0, false, false, false, NULL, false }
};
/* Handle a "java_interface" attribute; arguments as in
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
- if ((TREE_CODE (new_type) == FUNCTION_TYPE
- || TREE_CODE (new_type) == METHOD_TYPE)
- && (TYPE_RAISES_EXCEPTIONS (new_type)
- != TYPE_RAISES_EXCEPTIONS (type)))
+ if (TREE_CODE (new_type) == FUNCTION_TYPE
+ || TREE_CODE (new_type) == METHOD_TYPE)
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (type));
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), 1);
+ TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
case TEMPLATE_TYPE_PARM:
case TYPENAME_TYPE:
case TYPEOF_TYPE:
+ case UNDERLYING_TYPE:
/* None of these have subtrees other than those already walked
above. */
*walk_subtrees_p = 0;
case TYPE_PACK_EXPANSION:
WALK_SUBTREE (TREE_TYPE (*tp));
+ WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0;
break;
case EXPR_PACK_EXPANSION:
WALK_SUBTREE (TREE_OPERAND (*tp, 0));
+ WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0;
break;
case STATIC_CAST_EXPR:
case CONST_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
if (TREE_TYPE (*tp))
WALK_SUBTREE (TREE_TYPE (*tp));
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
- return sfk_assignment_operator;
+ {
+ if (copy_fn_p (decl))
+ return sfk_copy_assignment;
+ if (move_fn_p (decl))
+ return sfk_move_assignment;
+ }
if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
return sfk_destructor;
if (DECL_COMPLETE_DESTRUCTOR_P (decl))
/* 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 (VOID_TYPE_P (TREE_TYPE (exp)))
+ {
+ *initp = exp;
+ return void_zero_node;
+ }
+ /* 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
+ || SCALAR_TYPE_P (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;
if (TREE_CODE (t) == INIT_EXPR
&& TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != CONSTRUCTOR
&& TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
{
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
t = TARGET_EXPR_INITIAL (t);
if (TREE_CODE (t) == COMPOUND_EXPR)
t = expr_last (t);
- if (TREE_CODE (t) == CONSTRUCTOR
- && EMPTY_CONSTRUCTOR_P (t))
- /* Default-initialization. */
- return true;
+ if (TREE_CODE (t) == CONSTRUCTOR)
+ {
+ /* Aggregate initialization: stabilize each of the field
+ initializers. */
+ unsigned i;
+ constructor_elt *ce;
+ bool good = true;
+ VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (t);
+ for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
+ {
+ tree type = TREE_TYPE (ce->value);
+ tree subinit;
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ || SCALAR_TYPE_P (type))
+ ce->value = stabilize_expr (ce->value, &subinit);
+ else if (!stabilize_init (ce->value, &subinit))
+ good = false;
+ *initp = add_stmt_to_compound (*initp, subinit);
+ }
+ return good;
+ }
/* If the initializer is a COND_EXPR, we can't preevaluate
anything. */
/* The initialization is being performed via a bitwise copy -- and
the item copied may have side effects. */
- return TREE_SIDE_EFFECTS (init);
+ return !TREE_SIDE_EFFECTS (init);
}
/* Like "fold", but should be used whenever we might be processing the
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);
}
/* 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)
+ if (!node || !node->alias
+ || !VEC_length (ipa_ref_t, node->ref_list.references))
return true;
}
DECL_EXTERNAL (t) = 1;
TREE_STATIC (t) = 0;
}
- if (CP_AGGREGATE_TYPE_P (t)
- && TYPE_NAME (t))
+ if (TREE_CODE (t) == NAMESPACE_DECL)
{
- 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;
+ /* 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.
+ FIXME: If address space support is target specific, then this
+ should be a C target hook. But currently this is not possible,
+ because this function is called via REGISTER_TARGET_PRAGMAS. */
+void
+c_register_addr_space (const char *word ATTRIBUTE_UNUSED,
+ addr_space_t as ATTRIBUTE_UNUSED)
+{
+}
+
+/* Return the number of operands in T that we care about for things like
+ mangling. */
+
+int
+cp_tree_operand_length (const_tree t)
+{
+ enum tree_code code = TREE_CODE (t);
+
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ case PREDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ return 1;
+
+ case ARRAY_REF:
+ return 2;
+
+ case EXPR_PACK_EXPANSION:
+ return 1;
+
+ default:
+ return TREE_OPERAND_LENGTH (t);
+ }
+}
\f
#if defined ENABLE_TREE_CHECKING && (GCC_VERSION >= 2007)
/* Complain that some language-specific thing hanging off a tree