/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "debug.h"
#include "target.h"
#include "convert.h"
+#include "tree-flow.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, int);
static tree build_target_expr (tree, tree);
static tree count_trees_r (tree *, int *, void *);
static tree verify_stmt_tree_r (tree *, int *, void *);
nonzero, rvalues of class type are considered lvalues. */
static cp_lvalue_kind
-lvalue_p_1 (tree ref,
+lvalue_p_1 (const_tree ref,
int treat_class_rvalues_as_lvalues)
{
cp_lvalue_kind op1_lvalue_kind = clk_none;
&& TREE_CODE (ref) != COMPONENT_REF)
return clk_none;
- /* lvalue references and named rvalue refences are lvalues */
+ /* lvalue references and named rvalue references are lvalues. */
return clk_ordinary;
}
switch (TREE_CODE (ref))
{
+ case SAVE_EXPR:
+ return clk_none;
/* preincrements and predecrements are valid lvals, provided
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
- case SAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case REALPART_EXPR:
break;
case COND_EXPR:
- op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+ 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);
computes the C++ definition of lvalue. */
cp_lvalue_kind
-real_lvalue_p (tree ref)
+real_lvalue_p (const_tree ref)
{
return lvalue_p_1 (ref,
/*treat_class_rvalues_as_lvalues=*/0);
considered lvalues. */
int
-lvalue_p (tree ref)
+lvalue_p (const_tree ref)
{
return
(lvalue_p_1 (ref, /*class rvalue ok*/ 1) != clk_none);
constant-expression. */
bool
-builtin_valid_in_constant_expr_p (tree decl)
+builtin_valid_in_constant_expr_p (const_tree decl)
{
/* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
in constant-expressions. We may want to add other builtins later. */
{
tree t;
+#ifdef ENABLE_CHECKING
+ gcc_assert (VOID_TYPE_P (TREE_TYPE (value))
+ || TREE_TYPE (decl) == TREE_TYPE (value)
+ || 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);
/* We always set TREE_SIDE_EFFECTS so that expand_expr does not
}
/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
- target. TYPE is the type that this initialization should appear to
- have.
+ target. TYPE is the type to be initialized.
- Build an encapsulation of the initialization to perform
- and return it so that it can be processed by language-independent
- and language-specific expression expanders. */
+ Build an AGGR_INIT_EXPR to represent the initialization. This function
+ differs from build_cplus_new in that an AGGR_INIT_EXPR can only be used
+ to initialize another object, whereas a TARGET_EXPR can either
+ initialize another object or create its own temporary object, and as a
+ result building up a TARGET_EXPR requires that the type's destructor be
+ callable. */
tree
-build_cplus_new (tree type, tree init)
+build_aggr_init_expr (tree type, tree init)
{
tree fn;
tree slot;
&& TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
&& DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)));
- slot = build_local_temp (type);
-
/* We split the CALL_EXPR into its function and its arguments here.
Then, in expand_expr, we put them back together. The reason for
this is that this expression might be a default argument
type, don't mess with AGGR_INIT_EXPR. */
if (is_ctor || TREE_ADDRESSABLE (type))
{
+ slot = build_local_temp (type);
+
if (TREE_CODE(init) == CALL_EXPR)
rval = build_aggr_init_array (void_type_node, fn, slot,
call_expr_nargs (init),
else
rval = init;
+ return rval;
+}
+
+/* INIT is a CALL_EXPR or AGGR_INIT_EXPR which needs info about its
+ target. TYPE is the type that this initialization should appear to
+ have.
+
+ Build an encapsulation of the initialization to perform
+ and return it so that it can be processed by language-independent
+ and language-specific expression expanders. */
+
+tree
+build_cplus_new (tree type, tree init)
+{
+ tree rval = build_aggr_init_expr (type, init);
+ tree slot;
+
+ if (TREE_CODE (rval) == AGGR_INIT_EXPR)
+ slot = AGGR_INIT_EXPR_SLOT (rval);
+ else if (TREE_CODE (rval) == CALL_EXPR)
+ slot = build_local_temp (type);
+ else
+ return rval;
+
rval = build_target_expr (slot, rval);
TARGET_EXPR_IMPLICIT_P (rval) = 1;
if (TREE_CODE (init) == TARGET_EXPR)
return init;
else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)
+ && !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
&& TREE_CODE (init) != VA_ARG_EXPR)
- /* We need to build up a copy constructor call. COND_EXPR is a special
+ /* We need to build up a copy constructor call. A void initializer
+ means we're being called from bot_manip. COND_EXPR is a special
case because we already have copies on the arms and we don't want
another one here. A CONSTRUCTOR is aggregate initialization, which
is handled separately. A VA_ARG_EXPR is magic creation of an
hashval_t hash;
const_tree const t = (const_tree) k;
- hash = (htab_hash_pointer (TREE_TYPE (t))
- ^ htab_hash_pointer (TYPE_DOMAIN (t)));
-
+ hash = TYPE_UID (TREE_TYPE (t));
+ if (TYPE_DOMAIN (t))
+ hash ^= TYPE_UID (TYPE_DOMAIN (t));
return hash;
}
const_tree const t1 = (const_tree) k1;
const cplus_array_info *const t2 = (const cplus_array_info*) k2;
- if (!comptypes (TREE_TYPE (t1), t2->type, COMPARE_STRUCTURAL))
- return 0;
-
- if (!TYPE_DOMAIN (t1))
- return !t2->domain;
-
- if (!t2->domain)
- return 0;
-
- return comptypes (TYPE_DOMAIN (t1), t2->domain, COMPARE_STRUCTURAL);
+ return (TREE_TYPE (t1) == t2->type && TYPE_DOMAIN (t1) == t2->domain);
}
+/* Hash table containing all of the C++ array types, including
+ dependent array types and array types whose element type is
+ cv-qualified. */
static GTY ((param_is (union tree_node))) htab_t cplus_array_htab;
if (elt_type == error_mark_node || index_type == error_mark_node)
return error_mark_node;
- if (dependent_type_p (elt_type)
- || (index_type
- && value_dependent_expression_p (TYPE_MAX_VALUE (index_type))))
+ if (processing_template_decl
+ && (dependent_type_p (elt_type)
+ || (index_type && !TREE_CONSTANT (TYPE_MAX_VALUE (index_type)))))
{
void **e;
cplus_array_info cai;
hashval_t hash;
-
+
if (cplus_array_htab == NULL)
cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
&cplus_array_compare, NULL);
- hash = (htab_hash_pointer (elt_type)
- ^ htab_hash_pointer (index_type));
+ hash = TYPE_UID (elt_type);
+ if (index_type)
+ hash ^= TYPE_UID (index_type);
cai.type = elt_type;
cai.domain = index_type;
e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash, INSERT);
if (*e)
- /* We have found the type: we're done. */
+ /* We have found the type: we're done. */
return (tree) *e;
else
{
- /* Build a new array type. */
+ /* Build a new array type. */
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
- /* Complete building the array type. */
+ /* Store it in the hash table. */
+ *e = t;
+
+ /* Set the canonical type for this new node. */
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
|| (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (elt_type) != elt_type
|| (index_type
&& TYPE_CANONICAL (index_type) != index_type))
- TYPE_CANONICAL (t)
- = TYPE_CANONICAL
- (build_cplus_array_type_1 (TYPE_CANONICAL (elt_type),
- index_type?
- TYPE_CANONICAL (index_type)
- : index_type));
-
- /* Store it in the hash table. */
- *e = t;
+ TYPE_CANONICAL (t)
+ = build_cplus_array_type
+ (TYPE_CANONICAL (elt_type),
+ index_type ? TYPE_CANONICAL (index_type) : index_type);
+ else
+ TYPE_CANONICAL (t) = t;
}
}
else
return t;
}
+/* Return an ARRAY_TYPE with element type ELT and length N. */
+
+tree
+build_array_of_n_type (tree elt, int n)
+{
+ return build_cplus_array_type (elt, build_index_type (size_int (n - 1)));
+}
+
/* Return a reference type node referring to TO_TYPE. If RVAL is
true, return an rvalue reference type, otherwise return an lvalue
reference type. If a type node exists, reuse it, otherwise create
}
+/* 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). */
+tree
+c_build_qualified_type (tree type, int type_quals)
+{
+ return cp_build_qualified_type (type, type_quals);
+}
\f
/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
arrays correctly. In particular, if TYPE is an array of T's, and
TYPE_QUALS is non-empty, returns an array of qualified T's.
- FLAGS determines how to deal with illformed qualifications. If
+ FLAGS determines how to deal with ill-formed qualifications. If
tf_ignore_bad_quals is set, then bad qualifications are dropped
(this is permitted if TYPE was introduced via a typedef or template
type parameter). If bad qualifications are dropped and tf_warning
break;
if (!t)
- {
- tree domain = TYPE_DOMAIN (type);
-
- /* Make a new array type, just like the old one, but with the
- appropriately qualified element type. */
- t = build_variant_type_copy (type);
- TREE_TYPE (t) = element_type;
-
- /* This is a new type. */
- TYPE_CANONICAL (t) = t;
-
- if (dependent_type_p (element_type)
- || (domain
- && value_dependent_expression_p (TYPE_MAX_VALUE (domain))))
- {
- /* The new dependent array type we just created might be
- equivalent to an existing dependent array type, so we
- need to keep track of this new array type with a
- lookup into CPLUS_ARRAY_HTAB. Note that we cannot
- directly call build_cplus_array_type (that would
- recurse) or build_cplus_array_type_1 (that would lose
- attributes). */
- void **e;
- cplus_array_info cai;
- hashval_t hash;
-
- if (cplus_array_htab == NULL)
- cplus_array_htab = htab_create_ggc (61, &cplus_array_hash,
- &cplus_array_compare,
- NULL);
-
- hash = (htab_hash_pointer (element_type)
- ^ htab_hash_pointer (domain));
- cai.type = element_type;
- cai.domain = domain;
-
- e = htab_find_slot_with_hash (cplus_array_htab, &cai, hash,
- INSERT);
- if (! *e)
- /* Save this new type. */
- *e = t;
- }
+ {
+ t = build_cplus_array_type_1 (element_type, TYPE_DOMAIN (type));
- if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t))
- || (TYPE_DOMAIN (t)
- && TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (t))))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else
- TYPE_CANONICAL (t)
- = TYPE_CANONICAL
- (build_array_type (TYPE_CANONICAL (TREE_TYPE (t)),
- TYPE_DOMAIN (t)?
- TYPE_CANONICAL (TYPE_DOMAIN(t))
- : TYPE_DOMAIN (t)));
- }
+ if (TYPE_MAIN_VARIANT (t) != TYPE_MAIN_VARIANT (type))
+ {
+ /* Set the main variant of the newly-created ARRAY_TYPE
+ (with cv-qualified element type) to the main variant of
+ the unqualified ARRAY_TYPE we started with. */
+ tree last_variant = t;
+ tree m = TYPE_MAIN_VARIANT (type);
+
+ /* Find the last variant on the new ARRAY_TYPEs list of
+ variants, setting the main variant of each of the other
+ types to the main variant of our unqualified
+ ARRAY_TYPE. */
+ while (TYPE_NEXT_VARIANT (last_variant))
+ {
+ TYPE_MAIN_VARIANT (last_variant) = m;
+ last_variant = TYPE_NEXT_VARIANT (last_variant);
+ }
+
+ /* Splice in the newly-created variants. */
+ TYPE_NEXT_VARIANT (last_variant) = TYPE_NEXT_VARIANT (m);
+ TYPE_NEXT_VARIANT (m) = t;
+ TYPE_MAIN_VARIANT (last_variant) = m;
+ }
+ }
/* Even if we already had this variant, we update
TYPE_NEEDS_CONSTRUCTING and TYPE_HAS_NONTRIVIAL_DESTRUCTOR in case
t = cp_build_qualified_type_real (t, type_quals, complain);
return build_ptrmemfunc_type (t);
}
+ else if (TREE_CODE (type) == TYPE_PACK_EXPANSION)
+ {
+ tree t = PACK_EXPANSION_PATTERN (type);
+
+ t = cp_build_qualified_type_real (t, type_quals, complain);
+ return make_pack_expansion (t);
+ }
- /* A reference or method type shall not be cv qualified.
- [dcl.ref], [dct.fct] */
+ /* A reference or method type shall not be cv-qualified.
+ [dcl.ref], [dcl.fct] */
if (type_quals & (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE)
&& (TREE_CODE (type) == REFERENCE_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
between the unqualified and qualified types. */
if (result != type
&& TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)
+ && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+ && TYPE_LANG_SPECIFIC (result) == TYPE_LANG_SPECIFIC (type))
TYPE_LANG_SPECIFIC (result) = NULL;
+ /* We may also have ended up building a new copy of the canonical
+ type of a pointer-to-method type, which could have the same
+ sharing problem described above. */
+ if (TYPE_CANONICAL (result) != TYPE_CANONICAL (type)
+ && TREE_CODE (type) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE
+ && (TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result))
+ == TYPE_LANG_SPECIFIC (TYPE_CANONICAL (type))))
+ TYPE_LANG_SPECIFIC (TYPE_CANONICAL (result)) = NULL;
+
+
return result;
}
tree
canonical_type_variant (tree t)
{
+ if (t == error_mark_node)
+ return error_mark_node;
+
return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
}
\f
const char *
cxx_printable_name (tree decl, int v)
{
- static tree decl_ring[PRINT_RING_SIZE];
+ static unsigned int uid_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
static int ring_counter;
int i;
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
- if (decl_ring[i] == decl)
+ if (uid_ring[i] == DECL_UID (decl))
/* yes, so return it. */
return print_ring[i];
if (current_function_decl != NULL_TREE)
{
- if (decl_ring[ring_counter] == current_function_decl)
+ if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
ring_counter += 1;
if (ring_counter == PRINT_RING_SIZE)
ring_counter = 0;
- gcc_assert (decl_ring[ring_counter] != current_function_decl);
+ 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));
- decl_ring[ring_counter] = decl;
+ uid_ring[ring_counter] = DECL_UID (decl);
return print_ring[ring_counter];
}
\f
tree decl = TYPE_NAME (t);
tree t2;
- t2 = make_aggr_type (BOUND_TEMPLATE_TEMPLATE_PARM);
+ t2 = cxx_make_type (BOUND_TEMPLATE_TEMPLATE_PARM);
decl = build_decl (TYPE_DECL, DECL_NAME (decl), NULL_TREE);
/* These nodes have to be created to reflect new TYPE_DECL and template
count_trees (tree t)
{
int n_trees = 0;
- walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
+ cp_walk_tree_without_duplicates (&t, count_trees_r, &n_trees);
return n_trees;
}
{
htab_t statements;
statements = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
- walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
+ cp_walk_tree (&t, verify_stmt_tree_r, &statements, NULL);
htab_delete (statements);
}
{
return fold_build2 (PLUS_EXPR, sizetype,
array_type_nelts (type),
- integer_one_node);
+ size_one_node);
}
/* Return, as an INTEGER_CST node, the number of elements for TYPE
tree u;
if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
- u = build_cplus_new
- (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
+ u = build_cplus_new (TREE_TYPE (t), TREE_OPERAND (t, 1));
else
- u = build_target_expr_with_type
- (break_out_target_exprs (TREE_OPERAND (t, 1)), TREE_TYPE (t));
+ u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t));
/* Map the old variable to the new one. */
splay_tree_insert (target_remap,
(splay_tree_key) TREE_OPERAND (t, 0),
(splay_tree_value) TREE_OPERAND (u, 0));
+ TREE_OPERAND (u, 1) = break_out_target_exprs (TREE_OPERAND (u, 1));
+
/* Replace the old expression with the new version. */
*tp = u;
/* We don't have to go below this point; the recursive call to
target_remap = splay_tree_new (splay_tree_compare_pointers,
/*splay_tree_delete_key_fn=*/NULL,
/*splay_tree_delete_value_fn=*/NULL);
- walk_tree (&t, bot_manip, target_remap, NULL);
- walk_tree (&t, bot_replace, target_remap, NULL);
+ cp_walk_tree (&t, bot_manip, target_remap, NULL);
+ cp_walk_tree (&t, bot_replace, target_remap, NULL);
if (!--target_remap_count)
{
nested, or false otherwise. */
bool
-decl_anon_ns_mem_p (tree decl)
+decl_anon_ns_mem_p (const_tree decl)
{
while (1)
{
return false;
for (code1 = TREE_CODE (t1);
- code1 == NOP_EXPR || code1 == CONVERT_EXPR
+ CONVERT_EXPR_CODE_P (code1)
|| code1 == NON_LVALUE_EXPR;
code1 = TREE_CODE (t1))
t1 = TREE_OPERAND (t1, 0);
for (code2 = TREE_CODE (t2);
- code2 == NOP_EXPR || code2 == CONVERT_EXPR
+ CONVERT_EXPR_CODE_P (code2)
|| code1 == NON_LVALUE_EXPR;
code2 = TREE_CODE (t2))
t2 = TREE_OPERAND (t2, 0);
&& !memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
TREE_STRING_LENGTH (t1));
+ case FIXED_CST:
+ return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1),
+ TREE_FIXED_CST (t2));
+
case COMPLEX_CST:
return cp_tree_equal (TREE_REALPART (t1), TREE_REALPART (t2))
&& cp_tree_equal (TREE_IMAGPART (t1), TREE_IMAGPART (t2));
;
else if (real_lvalue_p (arg))
type = build_reference_type (lvalue_type (arg));
- else if (IS_AGGR_TYPE (type))
+ else if (MAYBE_CLASS_TYPE_P (type))
type = lvalue_type (arg);
return type;
/* Does FUNCTION use a variable-length argument list? */
int
-varargs_function_p (tree function)
+varargs_function_p (const_tree function)
{
- tree parm = TYPE_ARG_TYPES (TREE_TYPE (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;
/* Returns 1 if decl is a member of a class. */
int
-member_p (tree decl)
+member_p (const_tree decl)
{
- const tree ctx = DECL_CONTEXT (decl);
+ const_tree const ctx = DECL_CONTEXT (decl);
return (ctx && TYPE_P (ctx));
}
build_dummy_object (tree type)
{
tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
- return build_indirect_ref (decl, NULL);
+ return cp_build_indirect_ref (decl, NULL, tf_warning_or_error);
}
/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
/* Returns 1 if OB is a placeholder object, or a pointer to one. */
int
-is_dummy_object (tree ob)
+is_dummy_object (const_tree ob)
{
if (TREE_CODE (ob) == INDIRECT_REF)
ob = TREE_OPERAND (ob, 0);
/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
int
-pod_type_p (tree t)
+pod_type_p (const_tree t)
{
- t = strip_array_types (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;
/* Nonzero iff type T is a class template implicit specialization. */
bool
-class_tmpl_impl_spec_p (tree t)
+class_tmpl_impl_spec_p (const_tree t)
{
return CLASS_TYPE_P (t) && CLASSTYPE_TEMPLATE_INSTANTIATION (t);
}
zeros in it. */
int
-zero_init_p (tree t)
+zero_init_p (const_tree t)
{
- t = strip_array_types (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;
}
/* Build a variant of TYPE that has the indicated ATTRIBUTES. May
- return an existing type of an appropriate type already exists. */
+ return an existing type if an appropriate type already exists. */
tree
cp_build_type_attribute_variant (tree type, tree attributes)
return new_type;
}
+/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
+ Called only after doing all language independent checks. Only
+ to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
+ compared in type_hash_eq. */
+
+bool
+cxx_type_hash_eq (const_tree typea, const_tree typeb)
+{
+ gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE);
+
+ return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
+ TYPE_RAISES_EXCEPTIONS (typeb), 1);
+}
+
/* Apply FUNC to all language-specific sub-trees of TP in a pre-order
traversal. Called from walk_tree. */
#define WALK_SUBTREE(NODE) \
do \
{ \
- result = walk_tree (&(NODE), func, data, pset); \
+ result = cp_walk_tree (&(NODE), func, data, pset); \
if (result) goto out; \
} \
while (0)
*walk_subtrees_p = 0;
break;
- case TINST_LEVEL:
- WALK_SUBTREE (TINST_DECL (*tp));
- *walk_subtrees_p = 0;
- break;
-
case PTRMEM_CST:
WALK_SUBTREE (TREE_TYPE (*tp));
*walk_subtrees_p = 0;
*walk_subtrees_p = 0;
break;
+ case USING_DECL:
+ WALK_SUBTREE (DECL_NAME (*tp));
+ WALK_SUBTREE (USING_DECL_SCOPE (*tp));
+ WALK_SUBTREE (USING_DECL_DECLS (*tp));
+ *walk_subtrees_p = 0;
+ break;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (*tp))
WALK_SUBTREE (TYPE_PTRMEMFUNC_FN_TYPE (*tp));
#undef WALK_SUBTREE
}
-/* Decide whether there are language-specific reasons to not inline a
- function as a tree. */
-
-int
-cp_cannot_inline_tree_fn (tree* fnp)
-{
- tree fn = *fnp;
-
- /* We can inline a template instantiation only if it's fully
- instantiated. */
- if (DECL_TEMPLATE_INFO (fn)
- && TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
- {
- /* Don't instantiate functions that are not going to be
- inlined. */
- if (!DECL_INLINE (DECL_TEMPLATE_RESULT
- (template_for_substitution (fn))))
- return 1;
-
- fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
-
- if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
- return 1;
- }
-
- if (flag_really_no_inline
- && lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL)
- return 1;
-
- /* Don't auto-inline functions that might be replaced at link-time
- with an alternative definition. */
- if (!DECL_DECLARED_INLINE_P (fn) && DECL_REPLACEABLE_P (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- if (varargs_function_p (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- if (! function_attribute_inlinable_p (fn))
- {
- DECL_UNINLINABLE (fn) = 1;
- return 1;
- }
-
- return 0;
-}
-
-/* Determine whether VAR is a declaration of an automatic variable in
- function FN. */
-
-int
-cp_auto_var_in_fn_p (tree var, tree fn)
-{
- return (DECL_P (var) && DECL_CONTEXT (var) == fn
- && nonstatic_local_decl_p (var));
-}
-
/* Like save_expr, but for C++. */
tree
predicate to test whether or not DECL is a special function. */
special_function_kind
-special_function_p (tree decl)
+special_function_p (const_tree decl)
{
/* Rather than doing all this stuff with magic names, we should
probably have a field of type `special_function_kind' in
return (same_type_p (type, char_type_node)
|| same_type_p (type, unsigned_char_type_node)
|| same_type_p (type, signed_char_type_node)
+ || same_type_p (type, char16_type_node)
+ || same_type_p (type, char32_type_node)
|| same_type_p (type, wchar_type_node));
}
if (!DECL_NAME (decl))
return lk_none;
+ /* Fields have no linkage. */
+ if (TREE_CODE (decl) == FIELD_DECL)
+ return lk_none;
+
/* Things that are TREE_PUBLIC have external linkage. */
if (TREE_PUBLIC (decl))
return lk_external;
/* Members of the anonymous namespace also have TREE_PUBLIC unset, but
are considered to have external linkage for language purposes. DECLs
really meant to have internal linkage have DECL_THIS_STATIC set. */
- if (TREE_CODE (decl) == TYPE_DECL
- || ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
- && !DECL_THIS_STATIC (decl)))
+ if (TREE_CODE (decl) == TYPE_DECL)
return lk_external;
+ if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (!DECL_THIS_STATIC (decl))
+ return lk_external;
+
+ /* Static data members and static member functions from classes
+ in anonymous namespace also don't have TREE_PUBLIC set. */
+ if (DECL_CLASS_CONTEXT (decl))
+ return lk_external;
+ }
/* Everything else has internal linkage. */
return lk_internal;
}
else
{
- exp = build_unary_op (ADDR_EXPR, exp, 1);
+ exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error);
init_expr = get_target_expr (exp);
exp = TARGET_EXPR_SLOT (init_expr);
- exp = build_indirect_ref (exp, 0);
+ exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error);
}
*initp = init_expr;
return exp;
}
-/* Add NEW, an expression whose value we don't care about, after the
+/* Add NEW_EXPR, an expression whose value we don't care about, after the
similar expression ORIG. */
tree
-add_stmt_to_compound (tree orig, tree new)
+add_stmt_to_compound (tree orig, tree new_expr)
{
- if (!new || !TREE_SIDE_EFFECTS (new))
+ if (!new_expr || !TREE_SIDE_EFFECTS (new_expr))
return orig;
if (!orig || !TREE_SIDE_EFFECTS (orig))
- return new;
- return build2 (COMPOUND_EXPR, void_type_node, orig, new);
+ return new_expr;
+ return build2 (COMPOUND_EXPR, void_type_node, orig, new_expr);
}
/* Like stabilize_expr, but for a call whose arguments we want to
int i;
int nargs = call_expr_nargs (call);
- if (call == error_mark_node)
- return;
+ if (call == error_mark_node || processing_template_decl)
+ {
+ *initp = NULL_TREE;
+ return;
+ }
gcc_assert (TREE_CODE (call) == CALL_EXPR);
*initp = NULL_TREE;
- if (t == error_mark_node)
+ if (t == error_mark_node || processing_template_decl)
return true;
if (TREE_CODE (t) == INIT_EXPR
- && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR)
+ && TREE_CODE (TREE_OPERAND (t, 1)) != TARGET_EXPR
+ && TREE_CODE (TREE_OPERAND (t, 1)) != AGGR_INIT_EXPR)
{
TREE_OPERAND (t, 1) = stabilize_expr (TREE_OPERAND (t, 1), initp);
return true;