/* Language-independent 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, 2006, 2007, 2008, 2009
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
This file is part of GCC.
#include "tm.h"
#include "flags.h"
#include "tree.h"
-#include "real.h"
#include "tm_p.h"
#include "function.h"
#include "obstack.h"
#include "tree-flow.h"
#include "params.h"
#include "pointer-set.h"
-#include "fixed-value.h"
+#include "tree-pass.h"
+#include "langhooks-def.h"
+#include "diagnostic.h"
+#include "tree-diagnostic.h"
+#include "tree-pretty-print.h"
+#include "cgraph.h"
+#include "timevar.h"
+#include "except.h"
+#include "debug.h"
+#include "intl.h"
/* Tree code classes. */
static GTY(()) int next_decl_uid;
/* Unique id for next type created. */
static GTY(()) int next_type_uid = 1;
+/* Unique id for next debug decl created. Use negative numbers,
+ to catch erroneous uses. */
+static GTY(()) int next_debug_decl_uid;
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
/* General tree->tree mapping structure for use in hash tables. */
-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t debug_expr_for_decl;
-static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
+static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t value_expr_for_decl;
-static GTY ((if_marked ("tree_priority_map_marked_p"),
+static GTY ((if_marked ("tree_priority_map_marked_p"),
param_is (struct tree_priority_map)))
htab_t init_priority_for_decl;
tree_node_structure_for_code (enum tree_code code)
{
switch (TREE_CODE_CLASS (code))
- {
+ {
case tcc_declaration:
{
switch (code)
return TS_LABEL_DECL;
case RESULT_DECL:
return TS_RESULT_DECL;
+ case DEBUG_EXPR_DECL:
+ return TS_DECL_WRTL;
case CONST_DECL:
return TS_CONST_DECL;
case TYPE_DECL:
MARK_TS_COMMON (C); \
tree_contains_struct[C][TS_DECL_MINIMAL] = 1; \
} while (0)
-
+
#define MARK_TS_DECL_COMMON(C) \
do { \
MARK_TS_DECL_MINIMAL (C); \
int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
int_cst_hash_eq, NULL);
-
+
int_cst_node = make_node (INTEGER_CST);
cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
decl_str = IDENTIFIER_POINTER (decl_asmname);
asmname_str = IDENTIFIER_POINTER (asmname);
-
+
/* If the target assembler name was set by the user, things are trickier.
We have a leading '*' to begin with. After that, it's arguable what
return sizeof (struct tree_type_decl);
case FUNCTION_DECL:
return sizeof (struct tree_function_decl);
+ case DEBUG_EXPR_DECL:
+ return sizeof (struct tree_decl_with_rtl);
default:
return sizeof (struct tree_decl_non_common);
}
break;
}
break;
-
+
default:
gcc_unreachable ();
}
DECL_ALIGN (t) = 1;
}
DECL_SOURCE_LOCATION (t) = input_location;
- DECL_UID (t) = next_decl_uid++;
+ if (TREE_CODE (t) == DEBUG_EXPR_DECL)
+ DECL_UID (t) = --next_debug_decl_uid;
+ else
+ {
+ DECL_UID (t) = next_decl_uid++;
+ SET_DECL_PT_UID (t, -1);
+ }
if (TREE_CODE (t) == LABEL_DECL)
LABEL_DECL_UID (t) = -1;
TREE_CHAIN (t) = 0;
TREE_ASM_WRITTEN (t) = 0;
TREE_VISITED (t) = 0;
- t->base.ann = 0;
+ if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
+ *DECL_VAR_ANN_PTR (t) = 0;
if (TREE_CODE_CLASS (code) == tcc_declaration)
{
- DECL_UID (t) = next_decl_uid++;
+ if (code == DEBUG_EXPR_DECL)
+ DECL_UID (t) = --next_debug_decl_uid;
+ else
+ {
+ DECL_UID (t) = next_decl_uid++;
+ if (DECL_PT_UID_SET_P (node))
+ SET_DECL_PT_UID (t, DECL_PT_UID (node));
+ }
if ((TREE_CODE (node) == PARM_DECL || TREE_CODE (node) == VAR_DECL)
&& DECL_HAS_VALUE_EXPR_P (node))
{
but the optimizer should catch that. */
TYPE_SYMTAB_POINTER (t) = 0;
TYPE_SYMTAB_ADDRESS (t) = 0;
-
+
/* Do not copy the values cache. */
if (TYPE_CACHED_VALUES_P(t))
{
return build_int_cst_wide (type, low, low < 0 ? -1 : 0);
}
-/* Create an INT_CST node with a LOW value zero extended. */
-
-tree
-build_int_cstu (tree type, unsigned HOST_WIDE_INT low)
-{
- return build_int_cst_wide (type, low, 0);
-}
-
/* Create an INT_CST node with a LOW value in TYPE. The value is sign extended
if it is negative. This function is similar to build_int_cst, but
the extra bits outside of the type precision are cleared. Constants
return build_int_cst_wide (type, low1, hi);
}
-/* Create an INT_CST node of TYPE and value HI:LOW. The value is truncated
- and sign extended according to the value range of TYPE. */
+/* Constructs tree in type TYPE from with value given by CST. Signedness
+ of CST is assumed to be the same as the signedness of TYPE. */
tree
-build_int_cst_wide_type (tree type,
- unsigned HOST_WIDE_INT low, HOST_WIDE_INT high)
+double_int_to_tree (tree type, double_int cst)
{
- fit_double_type (low, high, &low, &high, type);
- return build_int_cst_wide (type, low, high);
+ /* Size types *are* sign extended. */
+ bool sign_extended_type = (!TYPE_UNSIGNED (type)
+ || (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)));
+
+ cst = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
+
+ return build_int_cst_wide (type, cst.low, cst.high);
+}
+
+/* Returns true if CST fits into range of TYPE. Signedness of CST is assumed
+ to be the same as the signedness of TYPE. */
+
+bool
+double_int_fits_to_tree_p (const_tree type, double_int cst)
+{
+ /* Size types *are* sign extended. */
+ bool sign_extended_type = (!TYPE_UNSIGNED (type)
+ || (TREE_CODE (type) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (type)));
+
+ double_int ext
+ = double_int_ext (cst, TYPE_PRECISION (type), !sign_extended_type);
+
+ return double_int_equal_p (cst, ext);
}
/* These are the hash table functions for the hash table of INTEGER_CST
TREE_INT_CST_LOW (t) = low;
TREE_INT_CST_HIGH (t) = hi;
TREE_TYPE (t) = type;
-
+
TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
}
}
tree
build_low_bits_mask (tree type, unsigned bits)
{
- unsigned HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0;
+ double_int mask;
gcc_assert (bits <= TYPE_PRECISION (type));
if (bits == TYPE_PRECISION (type)
&& !TYPE_UNSIGNED (type))
- {
- /* Sign extended all-ones mask. */
- low = all_ones;
- high = -1;
- }
- else if (bits <= HOST_BITS_PER_WIDE_INT)
- {
- low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
- high = 0;
- }
+ /* Sign extended all-ones mask. */
+ mask = double_int_minus_one;
else
- {
- bits -= HOST_BITS_PER_WIDE_INT;
- low = all_ones;
- high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
- }
+ mask = double_int_mask (bits);
- return build_int_cst_wide (type, low, high);
+ return build_int_cst_wide (type, mask.low, mask.high);
}
/* Checks that X is integer constant that can be expressed in (unsigned)
build_constructor (tree type, VEC(constructor_elt,gc) *vals)
{
tree c = make_node (CONSTRUCTOR);
+ unsigned int i;
+ constructor_elt *elt;
+ bool constant_p = true;
+
TREE_TYPE (c) = type;
CONSTRUCTOR_ELTS (c) = vals;
+
+ for (i = 0; VEC_iterate (constructor_elt, vals, i, elt); i++)
+ if (!TREE_CONSTANT (elt->value))
+ {
+ constant_p = false;
+ break;
+ }
+
+ TREE_CONSTANT (c) = constant_p;
+
return c;
}
{
VEC(constructor_elt,gc) *v;
constructor_elt *elt;
- tree t;
v = VEC_alloc (constructor_elt, gc, 1);
elt = VEC_quick_push (constructor_elt, v, NULL);
elt->index = index;
elt->value = value;
- t = build_constructor (type, v);
- TREE_CONSTANT (t) = TREE_CONSTANT (value);
- return t;
+ return build_constructor (type, v);
}
tree
build_constructor_from_list (tree type, tree vals)
{
- tree t, val;
+ tree t;
VEC(constructor_elt,gc) *v = NULL;
- bool constant_p = true;
if (vals)
{
v = VEC_alloc (constructor_elt, gc, list_length (vals));
for (t = vals; t; t = TREE_CHAIN (t))
- {
- constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
- val = TREE_VALUE (t);
- elt->index = TREE_PURPOSE (t);
- elt->value = val;
- if (!TREE_CONSTANT (val))
- constant_p = false;
- }
+ CONSTRUCTOR_APPEND_ELT (v, TREE_PURPOSE (t), TREE_VALUE (t));
}
- t = build_constructor (type, v);
- TREE_CONSTANT (t) = constant_p;
- return t;
+ return build_constructor (type, v);
}
/* Return a new FIXED_CST node whose type is TYPE and value is F. */
#ifdef GATHER_STATISTICS
tree_node_counts[(int) c_kind]++;
tree_node_sizes[(int) c_kind] += length;
-#endif
+#endif
s = ggc_alloc_tree (length);
if (TREE_CODE (expr) != INTEGER_CST)
return 0;
- prec = (POINTER_TYPE_P (TREE_TYPE (expr))
- ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
+ prec = TYPE_PRECISION (TREE_TYPE (expr));
high = TREE_INT_CST_HIGH (expr);
low = TREE_INT_CST_LOW (expr);
if (TREE_CODE (expr) == COMPLEX_CST)
return tree_log2 (TREE_REALPART (expr));
- prec = (POINTER_TYPE_P (TREE_TYPE (expr))
- ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+ prec = TYPE_PRECISION (TREE_TYPE (expr));
high = TREE_INT_CST_HIGH (expr);
low = TREE_INT_CST_LOW (expr);
if (TREE_CODE (expr) == COMPLEX_CST)
return tree_log2 (TREE_REALPART (expr));
- prec = (POINTER_TYPE_P (TREE_TYPE (expr))
- ? POINTER_SIZE : TYPE_PRECISION (TREE_TYPE (expr)));
-
+ prec = TYPE_PRECISION (TREE_TYPE (expr));
high = TREE_INT_CST_HIGH (expr);
low = TREE_INT_CST_LOW (expr);
return NULL_TREE;
}
+/* Returns element number IDX (zero-origin) of chain CHAIN, or
+ NULL_TREE. */
+
+tree
+chain_index (int idx, tree chain)
+{
+ for (; chain && idx > 0; --idx)
+ chain = TREE_CHAIN (chain);
+ return chain;
+}
+
/* Return nonzero if ELEM is part of the chain CHAIN. */
int
return count;
}
+/* Returns the first FIELD_DECL in the TYPE_FIELDS of the RECORD_TYPE or
+ UNION_TYPE TYPE, or NULL_TREE if none. */
+
+tree
+first_field (const_tree type)
+{
+ tree t = TYPE_FIELDS (type);
+ while (t && TREE_CODE (t) != FIELD_DECL)
+ t = TREE_CHAIN (t);
+ return t;
+}
+
/* Concatenate two chains of nodes (chained through TREE_CHAIN)
by modifying the last node in chain 1 to point to chain 2.
This is the Lisp primitive `nconc'. */
return chain;
}
-/* Return the node in a chain of nodes whose value is x, NULL if not found. */
-
-tree
-tree_find_value (tree chain, tree x)
-{
- tree list;
- for (list = chain; list; list = TREE_CHAIN (list))
- if (TREE_VALUE (list) == x)
- return list;
- return NULL;
-}
-
/* Reverse the order of elements in the chain T,
and return the new head of the chain (old last element). */
return node;
}
-/* Return the elements of a CONSTRUCTOR as a TREE_LIST. */
-
-tree
-ctor_to_list (tree ctor)
-{
- tree list = NULL_TREE;
- tree *p = &list;
- unsigned ix;
- tree purpose, val;
-
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), ix, purpose, val)
- {
- *p = build_tree_list (purpose, val);
- p = &TREE_CHAIN (*p);
- }
-
- return list;
-}
-
/* Return the values of the elements of a CONSTRUCTOR as a vector of
trees. */
return size;
}
+
+/* Returns a tree for the size of EXP in bytes. */
+
+tree
+tree_expr_size (const_tree exp)
+{
+ if (DECL_P (exp)
+ && DECL_SIZE_UNIT (exp) != 0)
+ return DECL_SIZE_UNIT (exp);
+ else
+ return size_in_bytes (TREE_TYPE (exp));
+}
\f
/* Return the bit position of FIELD, in bits from the start of the record.
This is a tree of type bitsizetype. */
side_effects = 1; \
if (!TREE_READONLY (arg##N) \
&& !CONSTANT_CLASS_P (arg##N)) \
- read_only = 0; \
+ (void) (read_only = 0); \
if (!TREE_CONSTANT (arg##N)) \
- constant = 0; \
+ (void) (constant = 0); \
} \
} while (0)
PROCESS_ARG(2);
PROCESS_ARG(3);
PROCESS_ARG(4);
+ if (code == TARGET_MEM_REF)
+ side_effects = 0;
PROCESS_ARG(5);
TREE_SIDE_EFFECTS (t) = side_effects;
- TREE_THIS_VOLATILE (t) = 0;
+ TREE_THIS_VOLATILE (t)
+ = (code == TARGET_MEM_REF
+ && arg5 && TREE_THIS_VOLATILE (arg5));
return t;
}
expand_location (source_location loc)
{
expanded_location xloc;
- if (loc == 0)
+ if (loc <= BUILTINS_LOCATION)
{
- xloc.file = NULL;
+ xloc.file = loc == UNKNOWN_LOCATION ? NULL : _("<built-in>");
xloc.line = 0;
xloc.column = 0;
xloc.sysp = 0;
}
/* Produce good hash value combining VAL and VAL2. */
-static inline hashval_t
+hashval_t
iterative_hash_host_wide_int (HOST_WIDE_INT val, hashval_t val2)
{
if (sizeof (HOST_WIDE_INT) == sizeof (hashval_t))
mix (a, b, val2);
if (sizeof (HOST_WIDE_INT) > 2 * sizeof (hashval_t))
{
- hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero));
- hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero));
- mix (a, b, val2);
+ hashval_t a = (hashval_t) (val >> (sizeof (hashval_t) * 16 + zero));
+ hashval_t b = (hashval_t) (val >> (sizeof (hashval_t) * 24 + zero));
+ mix (a, b, val2);
+ }
+ return val2;
+ }
+}
+
+/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
+ is ATTRIBUTE and its qualifiers are QUALS.
+
+ Record such modified types already made so we don't make duplicates. */
+
+tree
+build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
+{
+ if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
+ {
+ hashval_t hashcode = 0;
+ tree ntype;
+ enum tree_code code = TREE_CODE (ttype);
+
+ /* Building a distinct copy of a tagged type is inappropriate; it
+ causes breakage in code that expects there to be a one-to-one
+ relationship between a struct and its fields.
+ build_duplicate_type is another solution (as used in
+ handle_transparent_union_attribute), but that doesn't play well
+ with the stronger C++ type identity model. */
+ if (TREE_CODE (ttype) == RECORD_TYPE
+ || TREE_CODE (ttype) == UNION_TYPE
+ || TREE_CODE (ttype) == QUAL_UNION_TYPE
+ || TREE_CODE (ttype) == ENUMERAL_TYPE)
+ {
+ warning (OPT_Wattributes,
+ "ignoring attributes applied to %qT after definition",
+ TYPE_MAIN_VARIANT (ttype));
+ return build_qualified_type (ttype, quals);
+ }
+
+ ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
+ ntype = build_distinct_type_copy (ttype);
+
+ TYPE_ATTRIBUTES (ntype) = attribute;
+
+ hashcode = iterative_hash_object (code, hashcode);
+ if (TREE_TYPE (ntype))
+ hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)),
+ hashcode);
+ hashcode = attribute_hash_list (attribute, hashcode);
+
+ switch (TREE_CODE (ntype))
+ {
+ case FUNCTION_TYPE:
+ hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
+ break;
+ case ARRAY_TYPE:
+ if (TYPE_DOMAIN (ntype))
+ hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
+ hashcode);
+ break;
+ case INTEGER_TYPE:
+ hashcode = iterative_hash_object
+ (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode);
+ hashcode = iterative_hash_object
+ (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
+ break;
+ case REAL_TYPE:
+ case FIXED_POINT_TYPE:
+ {
+ unsigned int precision = TYPE_PRECISION (ntype);
+ hashcode = iterative_hash_object (precision, hashcode);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ntype = type_hash_canon (hashcode, ntype);
+
+ /* If the target-dependent attributes make NTYPE different from
+ its canonical type, we will need to use structural equality
+ checks for this type. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
+ || !targetm.comp_type_attributes (ntype, ttype))
+ SET_TYPE_STRUCTURAL_EQUALITY (ntype);
+ else if (TYPE_CANONICAL (ntype) == ntype)
+ TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
+
+ ttype = build_qualified_type (ntype, quals);
+ }
+ else if (TYPE_QUALS (ttype) != quals)
+ ttype = build_qualified_type (ttype, quals);
+
+ return ttype;
+}
+
+
+/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
+ is ATTRIBUTE.
+
+ Record such modified types already made so we don't make duplicates. */
+
+tree
+build_type_attribute_variant (tree ttype, tree attribute)
+{
+ return build_type_attribute_qual_variant (ttype, attribute,
+ TYPE_QUALS (ttype));
+}
+
+
+/* Reset the expression *EXPR_P, a size or position.
+
+ ??? We could reset all non-constant sizes or positions. But it's cheap
+ enough to not do so and refrain from adding workarounds to dwarf2out.c.
+
+ We need to reset self-referential sizes or positions because they cannot
+ be gimplified and thus can contain a CALL_EXPR after the gimplification
+ is finished, which will run afoul of LTO streaming. And they need to be
+ reset to something essentially dummy but not constant, so as to preserve
+ the properties of the object they are attached to. */
+
+static inline void
+free_lang_data_in_one_sizepos (tree *expr_p)
+{
+ tree expr = *expr_p;
+ if (CONTAINS_PLACEHOLDER_P (expr))
+ *expr_p = build0 (PLACEHOLDER_EXPR, TREE_TYPE (expr));
+}
+
+
+/* Reset all the fields in a binfo node BINFO. We only keep
+ BINFO_VIRTUALS, which is used by gimple_fold_obj_type_ref. */
+
+static void
+free_lang_data_in_binfo (tree binfo)
+{
+ unsigned i;
+ tree t;
+
+ gcc_assert (TREE_CODE (binfo) == TREE_BINFO);
+
+ BINFO_VTABLE (binfo) = NULL_TREE;
+ BINFO_BASE_ACCESSES (binfo) = NULL;
+ BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
+ BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
+
+ for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (binfo), i, t); i++)
+ free_lang_data_in_binfo (t);
+}
+
+
+/* Reset all language specific information still present in TYPE. */
+
+static void
+free_lang_data_in_type (tree type)
+{
+ gcc_assert (TYPE_P (type));
+
+ /* Give the FE a chance to remove its own data first. */
+ lang_hooks.free_lang_data (type);
+
+ TREE_LANG_FLAG_0 (type) = 0;
+ TREE_LANG_FLAG_1 (type) = 0;
+ TREE_LANG_FLAG_2 (type) = 0;
+ TREE_LANG_FLAG_3 (type) = 0;
+ TREE_LANG_FLAG_4 (type) = 0;
+ TREE_LANG_FLAG_5 (type) = 0;
+ TREE_LANG_FLAG_6 (type) = 0;
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ /* Remove the const and volatile qualifiers from arguments. The
+ C++ front end removes them, but the C front end does not,
+ leading to false ODR violation errors when merging two
+ instances of the same function signature compiled by
+ different front ends. */
+ tree p;
+
+ for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+ {
+ tree arg_type = TREE_VALUE (p);
+
+ if (TYPE_READONLY (arg_type) || TYPE_VOLATILE (arg_type))
+ {
+ int quals = TYPE_QUALS (arg_type)
+ & ~TYPE_QUAL_CONST
+ & ~TYPE_QUAL_VOLATILE;
+ TREE_VALUE (p) = build_qualified_type (arg_type, quals);
+ free_lang_data_in_type (TREE_VALUE (p));
+ }
+ }
+ }
+
+ /* Remove members that are not actually FIELD_DECLs from the field
+ list of an aggregate. These occur in C++. */
+ if (RECORD_OR_UNION_TYPE_P (type))
+ {
+ tree prev, member;
+
+ /* Note that TYPE_FIELDS can be shared across distinct
+ TREE_TYPEs. Therefore, if the first field of TYPE_FIELDS is
+ to be removed, we cannot set its TREE_CHAIN to NULL.
+ Otherwise, we would not be able to find all the other fields
+ in the other instances of this TREE_TYPE.
+
+ This was causing an ICE in testsuite/g++.dg/lto/20080915.C. */
+ prev = NULL_TREE;
+ member = TYPE_FIELDS (type);
+ while (member)
+ {
+ if (TREE_CODE (member) == FIELD_DECL)
+ {
+ if (prev)
+ TREE_CHAIN (prev) = member;
+ else
+ TYPE_FIELDS (type) = member;
+ prev = member;
+ }
+
+ member = TREE_CHAIN (member);
+ }
+
+ if (prev)
+ TREE_CHAIN (prev) = NULL_TREE;
+ else
+ TYPE_FIELDS (type) = NULL_TREE;
+
+ TYPE_METHODS (type) = NULL_TREE;
+ if (TYPE_BINFO (type))
+ free_lang_data_in_binfo (TYPE_BINFO (type));
+ }
+ else
+ {
+ /* For non-aggregate types, clear out the language slot (which
+ overloads TYPE_BINFO). */
+ TYPE_LANG_SLOT_1 (type) = NULL_TREE;
+
+ if (INTEGRAL_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type)
+ || FIXED_POINT_TYPE_P (type))
+ {
+ free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
+ free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
+ }
+ }
+
+ free_lang_data_in_one_sizepos (&TYPE_SIZE (type));
+ free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type));
+
+ if (debug_info_level < DINFO_LEVEL_TERSE
+ || (TYPE_CONTEXT (type)
+ && TREE_CODE (TYPE_CONTEXT (type)) != FUNCTION_DECL
+ && TREE_CODE (TYPE_CONTEXT (type)) != NAMESPACE_DECL))
+ TYPE_CONTEXT (type) = NULL_TREE;
+
+ if (debug_info_level < DINFO_LEVEL_TERSE)
+ TYPE_STUB_DECL (type) = NULL_TREE;
+}
+
+
+/* Return true if DECL may need an assembler name to be set. */
+
+static inline bool
+need_assembler_name_p (tree decl)
+{
+ /* Only FUNCTION_DECLs and VAR_DECLs are considered. */
+ if (TREE_CODE (decl) != FUNCTION_DECL
+ && TREE_CODE (decl) != VAR_DECL)
+ return false;
+
+ /* If DECL already has its assembler name set, it does not need a
+ new one. */
+ if (!HAS_DECL_ASSEMBLER_NAME_P (decl)
+ || DECL_ASSEMBLER_NAME_SET_P (decl))
+ return false;
+
+ /* Abstract decls do not need an assembler name. */
+ if (DECL_ABSTRACT (decl))
+ return false;
+
+ /* For VAR_DECLs, only static, public and external symbols need an
+ assembler name. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && !TREE_STATIC (decl)
+ && !TREE_PUBLIC (decl)
+ && !DECL_EXTERNAL (decl))
+ return false;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ /* Do not set assembler name on builtins. Allow RTL expansion to
+ decide whether to expand inline or via a regular call. */
+ if (DECL_BUILT_IN (decl)
+ && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
+ return false;
+
+ /* Functions represented in the callgraph need an assembler name. */
+ if (cgraph_get_node (decl) != NULL)
+ return true;
+
+ /* Unused and not public functions don't need an assembler name. */
+ if (!TREE_USED (decl) && !TREE_PUBLIC (decl))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Remove all the non-variable decls from BLOCK. LOCALS is the set of
+ variables in DECL_STRUCT_FUNCTION (FN)->local_decls. Every decl
+ in BLOCK that is not in LOCALS is removed. */
+
+static void
+free_lang_data_in_block (tree fn, tree block, struct pointer_set_t *locals)
+{
+ tree *tp, t;
+
+ tp = &BLOCK_VARS (block);
+ while (*tp)
+ {
+ if (!pointer_set_contains (locals, *tp))
+ *tp = TREE_CHAIN (*tp);
+ else
+ tp = &TREE_CHAIN (*tp);
+ }
+
+ for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+ free_lang_data_in_block (fn, t, locals);
+}
+
+
+/* Reset all language specific information still present in symbol
+ DECL. */
+
+static void
+free_lang_data_in_decl (tree decl)
+{
+ gcc_assert (DECL_P (decl));
+
+ /* Give the FE a chance to remove its own data first. */
+ lang_hooks.free_lang_data (decl);
+
+ TREE_LANG_FLAG_0 (decl) = 0;
+ TREE_LANG_FLAG_1 (decl) = 0;
+ TREE_LANG_FLAG_2 (decl) = 0;
+ TREE_LANG_FLAG_3 (decl) = 0;
+ TREE_LANG_FLAG_4 (decl) = 0;
+ TREE_LANG_FLAG_5 (decl) = 0;
+ TREE_LANG_FLAG_6 (decl) = 0;
+
+ /* Identifiers need not have a type. */
+ if (DECL_NAME (decl))
+ TREE_TYPE (DECL_NAME (decl)) = NULL_TREE;
+
+ /* Ignore any intervening types, because we are going to clear their
+ TYPE_CONTEXT fields. */
+ if (TREE_CODE (decl) != FIELD_DECL
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ DECL_CONTEXT (decl) = decl_function_context (decl);
+
+ if (DECL_CONTEXT (decl)
+ && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL)
+ DECL_CONTEXT (decl) = NULL_TREE;
+
+ if (TREE_CODE (decl) == VAR_DECL)
+ {
+ tree context = DECL_CONTEXT (decl);
+
+ if (context)
+ {
+ enum tree_code code = TREE_CODE (context);
+ if (code == FUNCTION_DECL && DECL_ABSTRACT (context))
+ {
+ /* Do not clear the decl context here, that will promote
+ all vars to global ones. */
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+
+ if (TREE_STATIC (decl))
+ DECL_CONTEXT (decl) = NULL_TREE;
+ }
+ }
+
+ free_lang_data_in_one_sizepos (&DECL_SIZE (decl));
+ free_lang_data_in_one_sizepos (&DECL_SIZE_UNIT (decl));
+ if (TREE_CODE (decl) == FIELD_DECL)
+ free_lang_data_in_one_sizepos (&DECL_FIELD_OFFSET (decl));
+
+ /* DECL_FCONTEXT is only used for debug info generation. */
+ if (TREE_CODE (decl) == FIELD_DECL
+ && debug_info_level < DINFO_LEVEL_TERSE)
+ DECL_FCONTEXT (decl) = NULL_TREE;
+
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ if (gimple_has_body_p (decl))
+ {
+ tree t;
+ struct pointer_set_t *locals;
+
+ /* If DECL has a gimple body, then the context for its
+ arguments must be DECL. Otherwise, it doesn't really
+ matter, as we will not be emitting any code for DECL. In
+ general, there may be other instances of DECL created by
+ the front end and since PARM_DECLs are generally shared,
+ their DECL_CONTEXT changes as the replicas of DECL are
+ created. The only time where DECL_CONTEXT is important
+ is for the FUNCTION_DECLs that have a gimple body (since
+ the PARM_DECL will be used in the function's body). */
+ for (t = DECL_ARGUMENTS (decl); t; t = TREE_CHAIN (t))
+ DECL_CONTEXT (t) = decl;
+
+ /* Collect all the symbols declared in DECL. */
+ locals = pointer_set_create ();
+ t = DECL_STRUCT_FUNCTION (decl)->local_decls;
+ for (; t; t = TREE_CHAIN (t))
+ {
+ pointer_set_insert (locals, TREE_VALUE (t));
+
+ /* All the local symbols should have DECL as their
+ context. */
+ DECL_CONTEXT (TREE_VALUE (t)) = decl;
+ }
+
+ /* Get rid of any decl not in local_decls. */
+ free_lang_data_in_block (decl, DECL_INITIAL (decl), locals);
+
+ pointer_set_destroy (locals);
+ }
+
+ /* DECL_SAVED_TREE holds the GENERIC representation for DECL.
+ At this point, it is not needed anymore. */
+ DECL_SAVED_TREE (decl) = NULL_TREE;
+ }
+ else if (TREE_CODE (decl) == VAR_DECL)
+ {
+ tree expr = DECL_DEBUG_EXPR (decl);
+ if (expr
+ && TREE_CODE (expr) == VAR_DECL
+ && !TREE_STATIC (expr) && !DECL_EXTERNAL (expr))
+ SET_DECL_DEBUG_EXPR (decl, NULL_TREE);
+
+ if (DECL_EXTERNAL (decl)
+ && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
+ DECL_INITIAL (decl) = NULL_TREE;
+ }
+ else if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ DECL_INITIAL (decl) = NULL_TREE;
+
+ /* DECL_CONTEXT is overloaded as DECL_FIELD_CONTEXT for
+ FIELD_DECLs, which should be preserved. Otherwise,
+ we shouldn't be concerned with source-level lexical
+ nesting beyond this point. */
+ DECL_CONTEXT (decl) = NULL_TREE;
+ }
+}
+
+
+/* Data used when collecting DECLs and TYPEs for language data removal. */
+
+struct free_lang_data_d
+{
+ /* Worklist to avoid excessive recursion. */
+ VEC(tree,heap) *worklist;
+
+ /* Set of traversed objects. Used to avoid duplicate visits. */
+ struct pointer_set_t *pset;
+
+ /* Array of symbols to process with free_lang_data_in_decl. */
+ VEC(tree,heap) *decls;
+
+ /* Array of types to process with free_lang_data_in_type. */
+ VEC(tree,heap) *types;
+};
+
+
+/* Save all language fields needed to generate proper debug information
+ for DECL. This saves most fields cleared out by free_lang_data_in_decl. */
+
+static void
+save_debug_info_for_decl (tree t)
+{
+ /*struct saved_debug_info_d *sdi;*/
+
+ gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && DECL_P (t));
+
+ /* FIXME. Partial implementation for saving debug info removed. */
+}
+
+
+/* Save all language fields needed to generate proper debug information
+ for TYPE. This saves most fields cleared out by free_lang_data_in_type. */
+
+static void
+save_debug_info_for_type (tree t)
+{
+ /*struct saved_debug_info_d *sdi;*/
+
+ gcc_assert (debug_info_level > DINFO_LEVEL_TERSE && t && TYPE_P (t));
+
+ /* FIXME. Partial implementation for saving debug info removed. */
+}
+
+
+/* Add type or decl T to one of the list of tree nodes that need their
+ language data removed. The lists are held inside FLD. */
+
+static void
+add_tree_to_fld_list (tree t, struct free_lang_data_d *fld)
+{
+ if (DECL_P (t))
+ {
+ VEC_safe_push (tree, heap, fld->decls, t);
+ if (debug_info_level > DINFO_LEVEL_TERSE)
+ save_debug_info_for_decl (t);
+ }
+ else if (TYPE_P (t))
+ {
+ VEC_safe_push (tree, heap, fld->types, t);
+ if (debug_info_level > DINFO_LEVEL_TERSE)
+ save_debug_info_for_type (t);
+ }
+ else
+ gcc_unreachable ();
+}
+
+/* Push tree node T into FLD->WORKLIST. */
+
+static inline void
+fld_worklist_push (tree t, struct free_lang_data_d *fld)
+{
+ if (t && !is_lang_specific (t) && !pointer_set_contains (fld->pset, t))
+ VEC_safe_push (tree, heap, fld->worklist, (t));
+}
+
+
+/* Operand callback helper for free_lang_data_in_node. *TP is the
+ subtree operand being considered. */
+
+static tree
+find_decls_types_r (tree *tp, int *ws, void *data)
+{
+ tree t = *tp;
+ struct free_lang_data_d *fld = (struct free_lang_data_d *) data;
+
+ if (TREE_CODE (t) == TREE_LIST)
+ return NULL_TREE;
+
+ /* Language specific nodes will be removed, so there is no need
+ to gather anything under them. */
+ if (is_lang_specific (t))
+ {
+ *ws = 0;
+ return NULL_TREE;
+ }
+
+ if (DECL_P (t))
+ {
+ /* Note that walk_tree does not traverse every possible field in
+ decls, so we have to do our own traversals here. */
+ add_tree_to_fld_list (t, fld);
+
+ fld_worklist_push (DECL_NAME (t), fld);
+ fld_worklist_push (DECL_CONTEXT (t), fld);
+ fld_worklist_push (DECL_SIZE (t), fld);
+ fld_worklist_push (DECL_SIZE_UNIT (t), fld);
+
+ /* We are going to remove everything under DECL_INITIAL for
+ TYPE_DECLs. No point walking them. */
+ if (TREE_CODE (t) != TYPE_DECL)
+ fld_worklist_push (DECL_INITIAL (t), fld);
+
+ fld_worklist_push (DECL_ATTRIBUTES (t), fld);
+ fld_worklist_push (DECL_ABSTRACT_ORIGIN (t), fld);
+
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ {
+ fld_worklist_push (DECL_ARGUMENTS (t), fld);
+ fld_worklist_push (DECL_RESULT (t), fld);
+ }
+ else if (TREE_CODE (t) == TYPE_DECL)
+ {
+ fld_worklist_push (DECL_ARGUMENT_FLD (t), fld);
+ fld_worklist_push (DECL_VINDEX (t), fld);
+ }
+ else if (TREE_CODE (t) == FIELD_DECL)
+ {
+ fld_worklist_push (DECL_FIELD_OFFSET (t), fld);
+ fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld);
+ fld_worklist_push (DECL_QUALIFIER (t), fld);
+ fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
+ fld_worklist_push (DECL_FCONTEXT (t), fld);
+ }
+ else if (TREE_CODE (t) == VAR_DECL)
+ {
+ fld_worklist_push (DECL_SECTION_NAME (t), fld);
+ fld_worklist_push (DECL_COMDAT_GROUP (t), fld);
+ }
+
+ if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == PARM_DECL)
+ && DECL_HAS_VALUE_EXPR_P (t))
+ fld_worklist_push (DECL_VALUE_EXPR (t), fld);
+
+ if (TREE_CODE (t) != FIELD_DECL)
+ fld_worklist_push (TREE_CHAIN (t), fld);
+ *ws = 0;
+ }
+ else if (TYPE_P (t))
+ {
+ /* Note that walk_tree does not traverse every possible field in
+ types, so we have to do our own traversals here. */
+ add_tree_to_fld_list (t, fld);
+
+ if (!RECORD_OR_UNION_TYPE_P (t))
+ fld_worklist_push (TYPE_CACHED_VALUES (t), fld);
+ fld_worklist_push (TYPE_SIZE (t), fld);
+ fld_worklist_push (TYPE_SIZE_UNIT (t), fld);
+ fld_worklist_push (TYPE_ATTRIBUTES (t), fld);
+ fld_worklist_push (TYPE_POINTER_TO (t), fld);
+ fld_worklist_push (TYPE_REFERENCE_TO (t), fld);
+ fld_worklist_push (TYPE_NAME (t), fld);
+ fld_worklist_push (TYPE_MINVAL (t), fld);
+ if (!RECORD_OR_UNION_TYPE_P (t))
+ fld_worklist_push (TYPE_MAXVAL (t), fld);
+ fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
+ fld_worklist_push (TYPE_NEXT_VARIANT (t), fld);
+ fld_worklist_push (TYPE_CONTEXT (t), fld);
+ fld_worklist_push (TYPE_CANONICAL (t), fld);
+
+ if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
+ {
+ unsigned i;
+ tree tem;
+ for (i = 0; VEC_iterate (tree, BINFO_BASE_BINFOS (TYPE_BINFO (t)),
+ i, tem); ++i)
+ fld_worklist_push (TREE_TYPE (tem), fld);
+ tem = BINFO_VIRTUALS (TYPE_BINFO (t));
+ if (tem
+ /* The Java FE overloads BINFO_VIRTUALS for its own purpose. */
+ && TREE_CODE (tem) == TREE_LIST)
+ do
+ {
+ fld_worklist_push (TREE_VALUE (tem), fld);
+ tem = TREE_CHAIN (tem);
+ }
+ while (tem);
+ }
+ if (RECORD_OR_UNION_TYPE_P (t))
+ {
+ tree tem;
+ /* Push all TYPE_FIELDS - there can be interleaving interesting
+ and non-interesting things. */
+ tem = TYPE_FIELDS (t);
+ while (tem)
+ {
+ if (TREE_CODE (tem) == FIELD_DECL)
+ fld_worklist_push (tem, fld);
+ tem = TREE_CHAIN (tem);
+ }
+ }
+
+ fld_worklist_push (TREE_CHAIN (t), fld);
+ *ws = 0;
+ }
+ else if (TREE_CODE (t) == BLOCK)
+ {
+ tree tem;
+ for (tem = BLOCK_VARS (t); tem; tem = TREE_CHAIN (tem))
+ fld_worklist_push (tem, fld);
+ for (tem = BLOCK_SUBBLOCKS (t); tem; tem = BLOCK_CHAIN (tem))
+ fld_worklist_push (tem, fld);
+ fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld);
+ }
+
+ fld_worklist_push (TREE_TYPE (t), fld);
+
+ return NULL_TREE;
+}
+
+
+/* Find decls and types in T. */
+
+static void
+find_decls_types (tree t, struct free_lang_data_d *fld)
+{
+ while (1)
+ {
+ if (!pointer_set_contains (fld->pset, t))
+ walk_tree (&t, find_decls_types_r, fld, fld->pset);
+ if (VEC_empty (tree, fld->worklist))
+ break;
+ t = VEC_pop (tree, fld->worklist);
+ }
+}
+
+/* Translate all the types in LIST with the corresponding runtime
+ types. */
+
+static tree
+get_eh_types_for_runtime (tree list)
+{
+ tree head, prev;
+
+ if (list == NULL_TREE)
+ return NULL_TREE;
+
+ head = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+ prev = head;
+ list = TREE_CHAIN (list);
+ while (list)
+ {
+ tree n = build_tree_list (0, lookup_type_for_runtime (TREE_VALUE (list)));
+ TREE_CHAIN (prev) = n;
+ prev = TREE_CHAIN (prev);
+ list = TREE_CHAIN (list);
+ }
+
+ return head;
+}
+
+
+/* Find decls and types referenced in EH region R and store them in
+ FLD->DECLS and FLD->TYPES. */
+
+static void
+find_decls_types_in_eh_region (eh_region r, struct free_lang_data_d *fld)
+{
+ switch (r->type)
+ {
+ case ERT_CLEANUP:
+ break;
+
+ case ERT_TRY:
+ {
+ eh_catch c;
+
+ /* The types referenced in each catch must first be changed to the
+ EH types used at runtime. This removes references to FE types
+ in the region. */
+ for (c = r->u.eh_try.first_catch; c ; c = c->next_catch)
+ {
+ c->type_list = get_eh_types_for_runtime (c->type_list);
+ walk_tree (&c->type_list, find_decls_types_r, fld, fld->pset);
+ }
+ }
+ break;
+
+ case ERT_ALLOWED_EXCEPTIONS:
+ r->u.allowed.type_list
+ = get_eh_types_for_runtime (r->u.allowed.type_list);
+ walk_tree (&r->u.allowed.type_list, find_decls_types_r, fld, fld->pset);
+ break;
+
+ case ERT_MUST_NOT_THROW:
+ walk_tree (&r->u.must_not_throw.failure_decl,
+ find_decls_types_r, fld, fld->pset);
+ break;
+ }
+}
+
+
+/* Find decls and types referenced in cgraph node N and store them in
+ FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
+ look for *every* kind of DECL and TYPE node reachable from N,
+ including those embedded inside types and decls (i.e,, TYPE_DECLs,
+ NAMESPACE_DECLs, etc). */
+
+static void
+find_decls_types_in_node (struct cgraph_node *n, struct free_lang_data_d *fld)
+{
+ basic_block bb;
+ struct function *fn;
+ tree t;
+
+ find_decls_types (n->decl, fld);
+
+ if (!gimple_has_body_p (n->decl))
+ return;
+
+ gcc_assert (current_function_decl == NULL_TREE && cfun == NULL);
+
+ fn = DECL_STRUCT_FUNCTION (n->decl);
+
+ /* Traverse locals. */
+ for (t = fn->local_decls; t; t = TREE_CHAIN (t))
+ find_decls_types (TREE_VALUE (t), fld);
+
+ /* Traverse EH regions in FN. */
+ {
+ eh_region r;
+ FOR_ALL_EH_REGION_FN (r, fn)
+ find_decls_types_in_eh_region (r, fld);
+ }
+
+ /* Traverse every statement in FN. */
+ FOR_EACH_BB_FN (bb, fn)
+ {
+ gimple_stmt_iterator si;
+ unsigned i;
+
+ for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple phi = gsi_stmt (si);
+
+ for (i = 0; i < gimple_phi_num_args (phi); i++)
+ {
+ tree *arg_p = gimple_phi_arg_def_ptr (phi, i);
+ find_decls_types (*arg_p, fld);
+ }
+ }
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple stmt = gsi_stmt (si);
+
+ for (i = 0; i < gimple_num_ops (stmt); i++)
+ {
+ tree arg = gimple_op (stmt, i);
+ find_decls_types (arg, fld);
+ }
}
- return val2;
}
}
-/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
- is ATTRIBUTE and its qualifiers are QUALS.
- Record such modified types already made so we don't make duplicates. */
+/* Find decls and types referenced in varpool node N and store them in
+ FLD->DECLS and FLD->TYPES. Unlike pass_referenced_vars, this will
+ look for *every* kind of DECL and TYPE node reachable from N,
+ including those embedded inside types and decls (i.e,, TYPE_DECLs,
+ NAMESPACE_DECLs, etc). */
-static tree
-build_type_attribute_qual_variant (tree ttype, tree attribute, int quals)
+static void
+find_decls_types_in_var (struct varpool_node *v, struct free_lang_data_d *fld)
{
- if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
+ find_decls_types (v->decl, fld);
+}
+
+/* If T needs an assembler name, have one created for it. */
+
+void
+assign_assembler_name_if_neeeded (tree t)
+{
+ if (need_assembler_name_p (t))
{
- hashval_t hashcode = 0;
- tree ntype;
- enum tree_code code = TREE_CODE (ttype);
+ /* When setting DECL_ASSEMBLER_NAME, the C++ mangler may emit
+ diagnostics that use input_location to show locus
+ information. The problem here is that, at this point,
+ input_location is generally anchored to the end of the file
+ (since the parser is long gone), so we don't have a good
+ position to pin it to.
- /* Building a distinct copy of a tagged type is inappropriate; it
- causes breakage in code that expects there to be a one-to-one
- relationship between a struct and its fields.
- build_duplicate_type is another solution (as used in
- handle_transparent_union_attribute), but that doesn't play well
- with the stronger C++ type identity model. */
- if (TREE_CODE (ttype) == RECORD_TYPE
- || TREE_CODE (ttype) == UNION_TYPE
- || TREE_CODE (ttype) == QUAL_UNION_TYPE
- || TREE_CODE (ttype) == ENUMERAL_TYPE)
- {
- warning (OPT_Wattributes,
- "ignoring attributes applied to %qT after definition",
- TYPE_MAIN_VARIANT (ttype));
- return build_qualified_type (ttype, quals);
- }
+ To alleviate this problem, this uses the location of T's
+ declaration. Examples of this are
+ testsuite/g++.dg/template/cond2.C and
+ testsuite/g++.dg/template/pr35240.C. */
+ location_t saved_location = input_location;
+ input_location = DECL_SOURCE_LOCATION (t);
- ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
- ntype = build_distinct_type_copy (ttype);
+ decl_assembler_name (t);
- TYPE_ATTRIBUTES (ntype) = attribute;
+ input_location = saved_location;
+ }
+}
- hashcode = iterative_hash_object (code, hashcode);
- if (TREE_TYPE (ntype))
- hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (ntype)),
- hashcode);
- hashcode = attribute_hash_list (attribute, hashcode);
- switch (TREE_CODE (ntype))
- {
- case FUNCTION_TYPE:
- hashcode = type_hash_list (TYPE_ARG_TYPES (ntype), hashcode);
- break;
- case ARRAY_TYPE:
- if (TYPE_DOMAIN (ntype))
- hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (ntype)),
- hashcode);
- break;
- case INTEGER_TYPE:
- hashcode = iterative_hash_object
- (TREE_INT_CST_LOW (TYPE_MAX_VALUE (ntype)), hashcode);
- hashcode = iterative_hash_object
- (TREE_INT_CST_HIGH (TYPE_MAX_VALUE (ntype)), hashcode);
- break;
- case REAL_TYPE:
- case FIXED_POINT_TYPE:
- {
- unsigned int precision = TYPE_PRECISION (ntype);
- hashcode = iterative_hash_object (precision, hashcode);
- }
- break;
- default:
- break;
- }
+/* Free language specific information for every operand and expression
+ in every node of the call graph. This process operates in three stages:
- ntype = type_hash_canon (hashcode, ntype);
+ 1- Every callgraph node and varpool node is traversed looking for
+ decls and types embedded in them. This is a more exhaustive
+ search than that done by find_referenced_vars, because it will
+ also collect individual fields, decls embedded in types, etc.
- /* If the target-dependent attributes make NTYPE different from
- its canonical type, we will need to use structural equality
- checks for this type. */
- if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
- || !targetm.comp_type_attributes (ntype, ttype))
- SET_TYPE_STRUCTURAL_EQUALITY (ntype);
- else if (TYPE_CANONICAL (ntype) == ntype)
- TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
+ 2- All the decls found are sent to free_lang_data_in_decl.
- ttype = build_qualified_type (ntype, quals);
- }
- else if (TYPE_QUALS (ttype) != quals)
- ttype = build_qualified_type (ttype, quals);
+ 3- All the types found are sent to free_lang_data_in_type.
- return ttype;
-}
+ The ordering between decls and types is important because
+ free_lang_data_in_decl sets assembler names, which includes
+ mangling. So types cannot be freed up until assembler names have
+ been set up. */
+static void
+free_lang_data_in_cgraph (void)
+{
+ struct cgraph_node *n;
+ struct varpool_node *v;
+ struct free_lang_data_d fld;
+ tree t;
+ unsigned i;
+ alias_pair *p;
-/* Return a type like TTYPE except that its TYPE_ATTRIBUTE
- is ATTRIBUTE.
+ /* Initialize sets and arrays to store referenced decls and types. */
+ fld.pset = pointer_set_create ();
+ fld.worklist = NULL;
+ fld.decls = VEC_alloc (tree, heap, 100);
+ fld.types = VEC_alloc (tree, heap, 100);
- Record such modified types already made so we don't make duplicates. */
+ /* Find decls and types in the body of every function in the callgraph. */
+ for (n = cgraph_nodes; n; n = n->next)
+ find_decls_types_in_node (n, &fld);
-tree
-build_type_attribute_variant (tree ttype, tree attribute)
+ for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+ find_decls_types (p->decl, &fld);
+
+ /* Find decls and types in every varpool symbol. */
+ for (v = varpool_nodes_queue; v; v = v->next_needed)
+ find_decls_types_in_var (v, &fld);
+
+ /* Set the assembler name on every decl found. We need to do this
+ now because free_lang_data_in_decl will invalidate data needed
+ for mangling. This breaks mangling on interdependent decls. */
+ for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ assign_assembler_name_if_neeeded (t);
+
+ /* Traverse every decl found freeing its language data. */
+ for (i = 0; VEC_iterate (tree, fld.decls, i, t); i++)
+ free_lang_data_in_decl (t);
+
+ /* Traverse every type found freeing its language data. */
+ for (i = 0; VEC_iterate (tree, fld.types, i, t); i++)
+ free_lang_data_in_type (t);
+
+ pointer_set_destroy (fld.pset);
+ VEC_free (tree, heap, fld.worklist);
+ VEC_free (tree, heap, fld.decls);
+ VEC_free (tree, heap, fld.types);
+}
+
+
+/* Free resources that are used by FE but are not needed once they are done. */
+
+static unsigned
+free_lang_data (void)
{
- return build_type_attribute_qual_variant (ttype, attribute,
- TYPE_QUALS (ttype));
+ unsigned i;
+
+ /* If we are the LTO frontend we have freed lang-specific data already. */
+ if (in_lto_p
+ || !flag_generate_lto)
+ return 0;
+
+ /* Allocate and assign alias sets to the standard integer types
+ while the slots are still in the way the frontends generated them. */
+ for (i = 0; i < itk_none; ++i)
+ if (integer_types[i])
+ TYPE_ALIAS_SET (integer_types[i]) = get_alias_set (integer_types[i]);
+
+ /* Traverse the IL resetting language specific information for
+ operands, expressions, etc. */
+ free_lang_data_in_cgraph ();
+
+ /* Create gimple variants for common types. */
+ ptrdiff_type_node = integer_type_node;
+ fileptr_type_node = ptr_type_node;
+ if (TREE_CODE (boolean_type_node) != BOOLEAN_TYPE
+ || (TYPE_MODE (boolean_type_node)
+ != mode_for_size (BOOL_TYPE_SIZE, MODE_INT, 0))
+ || TYPE_PRECISION (boolean_type_node) != 1
+ || !TYPE_UNSIGNED (boolean_type_node))
+ {
+ boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
+ TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
+ TYPE_MAX_VALUE (boolean_type_node) = build_int_cst (boolean_type_node, 1);
+ TYPE_PRECISION (boolean_type_node) = 1;
+ boolean_false_node = TYPE_MIN_VALUE (boolean_type_node);
+ boolean_true_node = TYPE_MAX_VALUE (boolean_type_node);
+ }
+
+ /* Unify char_type_node with its properly signed variant. */
+ if (TYPE_UNSIGNED (char_type_node))
+ unsigned_char_type_node = char_type_node;
+ else
+ signed_char_type_node = char_type_node;
+
+ /* Reset some langhooks. Do not reset types_compatible_p, it may
+ still be used indirectly via the get_alias_set langhook. */
+ lang_hooks.callgraph.analyze_expr = NULL;
+ lang_hooks.dwarf_name = lhd_dwarf_name;
+ lang_hooks.decl_printable_name = gimple_decl_printable_name;
+ lang_hooks.set_decl_assembler_name = lhd_set_decl_assembler_name;
+
+ /* Reset diagnostic machinery. */
+ diagnostic_starter (global_dc) = default_tree_diagnostic_starter;
+ diagnostic_finalizer (global_dc) = default_diagnostic_finalizer;
+ diagnostic_format_decoder (global_dc) = default_tree_printer;
+
+ return 0;
}
+
+struct simple_ipa_opt_pass pass_ipa_free_lang_data =
+{
+ {
+ SIMPLE_IPA_PASS,
+ "*free_lang_data", /* name */
+ NULL, /* gate */
+ free_lang_data, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_IPA_FREE_LANG_DATA, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_ggc_collect /* todo_flags_finish */
+ }
+};
+
/* Return nonzero if IDENT is a valid name for attribute ATTR,
or zero if not.
if (TREE_CODE (ident) != IDENTIFIER_NODE)
return 0;
-
+
p = IDENTIFIER_POINTER (ident);
ident_len = IDENTIFIER_LENGTH (ident);
-
+
if (ident_len == attr_len
&& strcmp (attr, p) == 0)
return 1;
marked dllimport and a definition appears later, then the object
is not dllimport'd. We also remove a `new' dllimport if the old list
contains dllexport: dllexport always overrides dllimport, regardless
- of the order of declaration. */
+ of the order of declaration. */
if (!VAR_OR_FUNCTION_DECL_P (new_tree))
delete_dllimport_p = 0;
else if (DECL_DLLIMPORT_P (new_tree)
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
- {
+ {
DECL_DLLIMPORT_P (new_tree) = 0;
warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: "
"dllimport ignored", new_tree);
}
/* Let an inline definition silently override the external reference,
- but otherwise warn about attribute inconsistency. */
+ but otherwise warn about attribute inconsistency. */
else if (TREE_CODE (new_tree) == VAR_DECL
|| !DECL_DECLARED_INLINE_P (new_tree))
warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
- if (delete_dllimport_p)
+ if (delete_dllimport_p)
{
tree prev, t;
- const size_t attr_len = strlen ("dllimport");
-
+ const size_t attr_len = strlen ("dllimport");
+
/* Scan the list for dllimport and delete it. */
for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
{
any damage. */
if (is_dllimport)
{
- /* Honor any target-specific overrides. */
+ /* Honor any target-specific overrides. */
if (!targetm.valid_dllimport_attribute_p (node))
*no_add_attrs = true;
&& DECL_DECLARED_INLINE_P (node))
{
warning (OPT_Wattributes, "inline function %q+D declared as "
- " dllimport: attribute ignored", node);
+ " dllimport: attribute ignored", node);
*no_add_attrs = true;
}
/* Like MS, treat definition of dllimported variables and
if (DECL_VISIBILITY_SPECIFIED (node)
&& DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
error ("%qE implies default visibility, but %qD has already "
- "been declared with a different visibility",
+ "been declared with a different visibility",
name, node);
DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
DECL_VISIBILITY_SPECIFIED (node) = 1;
TYPE_READONLY (type) = (type_quals & TYPE_QUAL_CONST) != 0;
TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
+ TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
/* Returns true iff CAND is equivalent to BASE with TYPE_QUALS. */
else
/* T is its own canonical type. */
TYPE_CANONICAL (t) = t;
-
+
}
return t;
build_distinct_type_copy (tree type)
{
tree t = copy_node (type);
-
+
TYPE_POINTER_TO (t) = 0;
TYPE_REFERENCE_TO (t) = 0;
/* Since we're building a variant, assume that it is a non-semantic
variant. This also propagates TYPE_STRUCTURAL_EQUALITY_P. */
TYPE_CANONICAL (t) = TYPE_CANONICAL (type);
-
+
/* Add the new type to the chain of variants of TYPE. */
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (m);
TYPE_NEXT_VARIANT (m) = t;
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
h = decl_priority_info (decl);
h->init = priority;
-}
+}
/* Set the finalization priority for DECL to PRIORITY. */
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
h = decl_priority_info (decl);
h->fini = priority;
-}
+}
/* Print out the statistics for the DECL_DEBUG_EXPR hash table. */
/* Lookup a debug expression for FROM, and return it if we find one. */
-tree
+tree
decl_debug_expr_lookup (tree from)
{
struct tree_map *h, in;
h->to = to;
loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
-}
+}
/* Lookup a value expression for FROM, and return it if we find one. */
-tree
+tree
decl_value_expr_lookup (tree from)
{
struct tree_map *h, in;
TYPE_ATTRIBUTES (b->type))
|| TYPE_ALIGN (a->type) != TYPE_ALIGN (b->type)
|| TYPE_MODE (a->type) != TYPE_MODE (b->type)
- || (TREE_CODE (a->type) != COMPLEX_TYPE
+ || (TREE_CODE (a->type) != COMPLEX_TYPE
&& TYPE_NAME (a->type) != TYPE_NAME (b->type)))
return 0;
int
host_integerp (const_tree t, int pos)
{
+ if (t == NULL_TREE)
+ return 0;
+
return (TREE_CODE (t) == INTEGER_CST
&& ((TREE_INT_CST_HIGH (t) == 0
&& (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
return iterative_hash_expr (TREE_IMAGPART (t), val);
case VECTOR_CST:
return iterative_hash_expr (TREE_VECTOR_CST_ELTS (t), val);
-
case SSA_NAME:
- /* we can just compare by pointer. */
+ /* We can just compare by pointer. */
return iterative_hash_host_wide_int (SSA_NAME_VERSION (t), val);
-
+ case PLACEHOLDER_EXPR:
+ /* The node itself doesn't matter. */
+ return val;
case TREE_LIST:
/* A list of expressions, for a CALL_EXPR or as the elements of a
VECTOR_CST. */
else
{
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
-
+
val = iterative_hash_object (code, val);
/* Don't hash the type, that can lead to having nodes which
tree
build_pointer_type (tree to_type)
{
- return build_pointer_type_for_mode (to_type, ptr_mode, false);
+ addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+ : TYPE_ADDR_SPACE (to_type);
+ enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+ return build_pointer_type_for_mode (to_type, pointer_mode, false);
}
/* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (to_type) != to_type)
- TYPE_CANONICAL (t)
+ TYPE_CANONICAL (t)
= build_reference_type_for_mode (TYPE_CANONICAL (to_type),
mode, can_alias_all);
tree
build_reference_type (tree to_type)
{
- return build_reference_type_for_mode (to_type, ptr_mode, false);
+ addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+ : TYPE_ADDR_SPACE (to_type);
+ enum machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
+ return build_reference_type_for_mode (to_type, pointer_mode, false);
}
/* Build a type that is compatible with t but has no cv quals anywhere
}
}
+#define MAX_INT_CACHED_PREC \
+ (HOST_BITS_PER_WIDE_INT > 64 ? HOST_BITS_PER_WIDE_INT : 64)
+static GTY(()) tree nonstandard_integer_type_cache[2 * MAX_INT_CACHED_PREC + 2];
+
/* Builds a signed or unsigned integer type of precision PRECISION.
Used for C bitfields whose precision does not match that of
built-in target types. */
build_nonstandard_integer_type (unsigned HOST_WIDE_INT precision,
int unsignedp)
{
- tree itype = make_node (INTEGER_TYPE);
+ tree itype, ret;
+
+ if (unsignedp)
+ unsignedp = MAX_INT_CACHED_PREC + 1;
+
+ if (precision <= MAX_INT_CACHED_PREC)
+ {
+ itype = nonstandard_integer_type_cache[precision + unsignedp];
+ if (itype)
+ return itype;
+ }
+ itype = make_node (INTEGER_TYPE);
TYPE_PRECISION (itype) = precision;
if (unsignedp)
else
fixup_signed_type (itype);
+ ret = itype;
if (host_integerp (TYPE_MAX_VALUE (itype), 1))
- return type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
+ ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype);
+ if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types)
+ nonstandard_integer_type_cache[precision + unsignedp] = ret;
- return itype;
+ return ret;
}
/* Create a range of some discrete type TYPE (an INTEGER_TYPE,
t = make_node (ARRAY_TYPE);
TREE_TYPE (t) = elt_type;
TYPE_DOMAIN (t) = index_type;
-
- if (index_type == 0)
- {
- tree save = t;
- hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
- t = type_hash_canon (hashcode, t);
- if (save == t)
- layout_type (t);
-
- if (TYPE_CANONICAL (t) == t)
- {
- if (TYPE_STRUCTURAL_EQUALITY_P (elt_type))
- SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (elt_type) != elt_type)
- TYPE_CANONICAL (t)
- = build_array_type (TYPE_CANONICAL (elt_type), index_type);
- }
+ TYPE_ADDR_SPACE (t) = TYPE_ADDR_SPACE (elt_type);
+ layout_type (t);
- return t;
- }
+ /* If the element type is incomplete at this point we get marked for
+ structural equality. Do not record these types in the canonical
+ type hashtable. */
+ if (TYPE_STRUCTURAL_EQUALITY_P (t))
+ return t;
hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode);
- hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
+ if (index_type)
+ hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode);
t = type_hash_canon (hashcode, t);
- if (!COMPLETE_TYPE_P (t))
- layout_type (t);
-
if (TYPE_CANONICAL (t) == t)
{
if (TYPE_STRUCTURAL_EQUALITY_P (elt_type)
- || TYPE_STRUCTURAL_EQUALITY_P (index_type))
+ || (index_type && TYPE_STRUCTURAL_EQUALITY_P (index_type)))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (elt_type) != elt_type
- || TYPE_CANONICAL (index_type) != index_type)
- TYPE_CANONICAL (t)
+ || (index_type && TYPE_CANONICAL (index_type) != index_type))
+ TYPE_CANONICAL (t)
= build_array_type (TYPE_CANONICAL (elt_type),
- TYPE_CANONICAL (index_type));
+ index_type ? TYPE_CANONICAL (index_type) : NULL);
}
return t;
}
/* Computes the canonical argument types from the argument type list
- ARGTYPES.
+ ARGTYPES.
Upon return, *ANY_STRUCTURAL_P will be true iff either it was true
on entry to this function, or if any of the ARGTYPES are
canonical argument list is unneeded (i.e., *ANY_STRUCTURAL_P is
true) or would not differ from ARGTYPES. */
-static tree
-maybe_canonicalize_argtypes(tree argtypes,
+static tree
+maybe_canonicalize_argtypes(tree argtypes,
bool *any_structural_p,
bool *any_noncanonical_p)
{
tree arg;
bool any_noncanonical_argtypes_p = false;
-
+
for (arg = argtypes; arg && !(*any_structural_p); arg = TREE_CHAIN (arg))
{
if (!TREE_VALUE (arg) || TREE_VALUE (arg) == error_mark_node)
/* Set up the canonical type. */
any_structural_p = TYPE_STRUCTURAL_EQUALITY_P (value_type);
any_noncanonical_p = TYPE_CANONICAL (value_type) != value_type;
- canon_argtypes = maybe_canonicalize_argtypes (arg_types,
+ canon_argtypes = maybe_canonicalize_argtypes (arg_types,
&any_structural_p,
&any_noncanonical_p);
if (any_structural_p)
else if (any_noncanonical_p)
TYPE_CANONICAL (t) = build_function_type (TYPE_CANONICAL (value_type),
canon_argtypes);
-
+
if (!COMPLETE_TYPE_P (t))
layout_type (t);
return t;
else
new_reversed = void_list_node;
}
- gcc_assert (new_reversed);
/* Use copy_node to preserve as much as possible from original type
(debug info, attribute lists etc.)
return new_type;
}
-/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.
-
+/* Build variant of function type ORIG_TYPE skipping ARGS_TO_SKIP.
+
Arguments from DECL_ARGUMENTS list can't be removed now, since they are
- linked by TREE_CHAIN directly. It is caller responsibility to eliminate
+ linked by TREE_CHAIN directly. The caller is responsible for eliminating
them when they are being duplicated (i.e. copy_arguments_for_versioning). */
tree
}
/* Build a function type. The RETURN_TYPE is the type returned by the
- function. If VAARGS is set, no void_type_node is appended to the
- the list. ARGP muse be alway be terminated be a NULL_TREE. */
+ function. If VAARGS is set, no void_type_node is appended to the
+ the list. ARGP must be always be terminated be a NULL_TREE. */
static tree
build_function_type_list_1 (bool vaargs, tree return_type, va_list argp)
last = args;
if (args != NULL_TREE)
args = nreverse (args);
- gcc_assert (args != NULL_TREE && last != void_list_node);
+ gcc_assert (last != void_list_node);
}
else if (args == NULL_TREE)
args = void_list_node;
if (any_structural_p)
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (any_noncanonical_p)
- TYPE_CANONICAL (t)
+ TYPE_CANONICAL (t)
= build_method_type_directly (TYPE_CANONICAL (basetype),
TYPE_CANONICAL (rettype),
canon_argtypes);
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)) != basetype
|| TYPE_CANONICAL (type) != type)
- TYPE_CANONICAL (t)
+ TYPE_CANONICAL (t)
= build_offset_type (TYPE_CANONICAL (TYPE_MAIN_VARIANT (basetype)),
TYPE_CANONICAL (type));
}
if (TYPE_STRUCTURAL_EQUALITY_P (component_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (component_type) != component_type)
- TYPE_CANONICAL (t)
+ TYPE_CANONICAL (t)
= build_complex_type (TYPE_CANONICAL (component_type));
}
}
}
+ /* If we finally reach a constant see if it fits in for_type and
+ in that case convert it. */
+ if (for_type
+ && TREE_CODE (win) == INTEGER_CST
+ && TREE_TYPE (win) != for_type
+ && int_fits_type_p (win, for_type))
+ win = fold_convert (for_type, win);
+
return win;
}
\f
}
}
- if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type)
+ if (!POINTER_TYPE_P (type) && TYPE_MAX_VALUE (type)
&& TREE_CODE (TYPE_MAX_VALUE (type)) == INTEGER_CST)
mpz_set_double_int (max, tree_to_double_int (TYPE_MAX_VALUE (type)),
TYPE_UNSIGNED (type));
auto_var_in_fn_p (const_tree var, const_tree fn)
{
return (DECL_P (var) && DECL_CONTEXT (var) == fn
- && (((TREE_CODE (var) == VAR_DECL || TREE_CODE (var) == PARM_DECL)
+ && ((((TREE_CODE (var) == VAR_DECL && ! DECL_EXTERNAL (var))
+ || TREE_CODE (var) == PARM_DECL)
&& ! TREE_STATIC (var))
|| TREE_CODE (var) == LABEL_DECL
|| TREE_CODE (var) == RESULT_DECL));
while ((code = va_arg (args, int)))
{
const char *prefix = length ? " or " : "expected ";
-
+
strcpy (tmp + length, prefix);
length += strlen (prefix);
strcpy (tmp + length, tree_code_name[code]);
whether CODE contains the tree structure identified by EN. */
void
-tree_contains_struct_check_failed (const_tree node,
+tree_contains_struct_check_failed (const_tree node,
const enum tree_node_structure_enum en,
- const char *file, int line,
+ const char *file, int line,
const char *function)
{
internal_error
tree t;
hashval_t hashcode = 0;
- /* Build a main variant, based on the main variant of the inner type, then
- use it to build the variant we return. */
- if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype))
- && TYPE_MAIN_VARIANT (innertype) != innertype)
- return build_type_attribute_qual_variant (
- make_vector_type (TYPE_MAIN_VARIANT (innertype), nunits, mode),
- TYPE_ATTRIBUTES (innertype),
- TYPE_QUALS (innertype));
-
t = make_node (VECTOR_TYPE);
TREE_TYPE (t) = TYPE_MAIN_VARIANT (innertype);
SET_TYPE_VECTOR_SUBPARTS (t, nunits);
SET_TYPE_MODE (t, mode);
- TYPE_READONLY (t) = TYPE_READONLY (innertype);
- TYPE_VOLATILE (t) = TYPE_VOLATILE (innertype);
if (TYPE_STRUCTURAL_EQUALITY_P (innertype))
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (innertype) != innertype
|| mode != VOIDmode)
- TYPE_CANONICAL (t)
+ TYPE_CANONICAL (t)
= make_vector_type (TYPE_CANONICAL (innertype), nunits, VOIDmode);
layout_type (t);
}
hashcode = iterative_hash_host_wide_int (VECTOR_TYPE, hashcode);
+ hashcode = iterative_hash_host_wide_int (nunits, hashcode);
hashcode = iterative_hash_host_wide_int (mode, hashcode);
- hashcode = iterative_hash_object (TYPE_HASH (innertype), hashcode);
- return type_hash_canon (hashcode, t);
+ hashcode = iterative_hash_object (TYPE_HASH (TREE_TYPE (t)), hashcode);
+ t = type_hash_canon (hashcode, t);
+
+ /* We have built a main variant, based on the main variant of the
+ inner type. Use it to build the variant we return. */
+ if ((TYPE_ATTRIBUTES (innertype) || TYPE_QUALS (innertype))
+ && TREE_TYPE (t) != innertype)
+ return build_type_attribute_qual_variant (t,
+ TYPE_ATTRIBUTES (innertype),
+ TYPE_QUALS (innertype));
+
+ return t;
}
static tree
this function to select one of the types as sizetype. */
void
-build_common_tree_nodes (bool signed_char, bool signed_sizetype)
+build_common_tree_nodes (bool signed_char)
{
error_mark_node = make_node (ERROR_MARK);
TREE_TYPE (error_mark_node) = error_mark_node;
- initialize_sizetypes (signed_sizetype);
+ initialize_sizetypes ();
/* Define both `signed char' and `unsigned char'. */
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
/* Decimal float types. */
dfloat32_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
+ TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
layout_type (dfloat32_type_node);
SET_TYPE_MODE (dfloat32_type_node, SDmode);
dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
dfloat128_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
+ TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
layout_type (dfloat128_type_node);
SET_TYPE_MODE (dfloat128_type_node, TDmode);
dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
declare the type to be __builtin_va_list. */
if (TREE_CODE (t) != RECORD_TYPE)
t = build_variant_type_copy (t);
-
+
va_list_type_node = t;
}
}
void
build_common_builtin_nodes (void)
{
- tree tmp, ftype;
+ tree tmp, tmp2, ftype;
if (built_in_decls[BUILT_IN_MEMCPY] == NULL
|| built_in_decls[BUILT_IN_MEMMOVE] == NULL)
tmp = tree_cons (NULL_TREE, size_type_node, void_list_node);
ftype = build_function_type (ptr_type_node, tmp);
local_define_builtin ("__builtin_alloca", ftype, BUILT_IN_ALLOCA,
- "alloca", ECF_NOTHROW | ECF_MALLOC);
+ "alloca", ECF_MALLOC | ECF_NOTHROW);
}
+ /* If we're checking the stack, `alloca' can throw. */
+ if (flag_stack_check)
+ TREE_NOTHROW (built_in_decls[BUILT_IN_ALLOCA]) = 0;
+
tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
local_define_builtin ("__builtin_profile_func_exit", ftype,
BUILT_IN_PROFILE_FUNC_EXIT, "profile_func_exit", 0);
+ /* If there's a possibility that we might use the ARM EABI, build the
+ alternate __cxa_end_cleanup node used to resume from C++ and Java. */
+ if (targetm.arm_eabi_unwinder)
+ {
+ ftype = build_function_type (void_type_node, void_list_node);
+ local_define_builtin ("__builtin_cxa_end_cleanup", ftype,
+ BUILT_IN_CXA_END_CLEANUP,
+ "__cxa_end_cleanup", ECF_NORETURN);
+ }
+
+ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
+ ftype = build_function_type (void_type_node, tmp);
+ local_define_builtin ("__builtin_unwind_resume", ftype,
+ BUILT_IN_UNWIND_RESUME,
+ (USING_SJLJ_EXCEPTIONS
+ ? "_Unwind_SjLj_Resume" : "_Unwind_Resume"),
+ ECF_NORETURN);
+
+ /* The exception object and filter values from the runtime. The argument
+ must be zero before exception lowering, i.e. from the front end. After
+ exception lowering, it will be the region number for the exception
+ landing pad. These functions are PURE instead of CONST to prevent
+ them from being hoisted past the exception edge that will initialize
+ its value in the landing pad. */
+ tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
+ ftype = build_function_type (ptr_type_node, tmp);
+ local_define_builtin ("__builtin_eh_pointer", ftype, BUILT_IN_EH_POINTER,
+ "__builtin_eh_pointer", ECF_PURE | ECF_NOTHROW);
+
+ tmp2 = lang_hooks.types.type_for_mode (targetm.eh_return_filter_mode (), 0);
+ ftype = build_function_type (tmp2, tmp);
+ local_define_builtin ("__builtin_eh_filter", ftype, BUILT_IN_EH_FILTER,
+ "__builtin_eh_filter", ECF_PURE | ECF_NOTHROW);
+
+ tmp = tree_cons (NULL_TREE, integer_type_node, void_list_node);
+ tmp = tree_cons (NULL_TREE, integer_type_node, tmp);
+ ftype = build_function_type (void_type_node, tmp);
+ local_define_builtin ("__builtin_eh_copy_values", ftype,
+ BUILT_IN_EH_COPY_VALUES,
+ "__builtin_eh_copy_values", ECF_NOTHROW);
+
/* Complex multiplication and division. These are handled as builtins
rather than optabs because emit_library_call_value doesn't support
- complex. Further, we can do slightly better with folding these
+ complex. Further, we can do slightly better with folding these
beasties if the real and complex parts of the arguments are separate. */
{
int mode;
reconstruct_complex_type (tree type, tree bottom)
{
tree inner, outer;
-
+
if (TREE_CODE (type) == POINTER_TYPE)
{
inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
inner = reconstruct_complex_type (TREE_TYPE (type), bottom);
/* The build_method_type_directly() routine prepends 'this' to argument list,
so we must compensate by getting rid of it. */
- outer
- = build_method_type_directly
+ outer
+ = build_method_type_directly
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type))),
inner,
TREE_CHAIN (TYPE_ARG_TYPES (type)));
else
return bottom;
- return build_qualified_type (outer, TYPE_QUALS (type));
+ return build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type),
+ TYPE_QUALS (type));
}
/* Returns a vector tree node given a mode (integer, vector, or BLKmode) and
}
-/* Build RESX_EXPR with given REGION_NUMBER. */
-tree
-build_resx (int region_number)
-{
- tree t;
- t = build1 (RESX_EXPR, void_type_node,
- build_int_cst (NULL_TREE, region_number));
- return t;
-}
-
/* Given an initializer INIT, return TRUE if INIT is zero or some
aggregate of zeros. Otherwise return FALSE. */
bool
return true;
}
+ case STRING_CST:
+ {
+ int i;
+
+ /* We need to loop through all elements to handle cases like
+ "\0" and "\0foobar". */
+ for (i = 0; i < TREE_STRING_LENGTH (init); ++i)
+ if (TREE_STRING_POINTER (init)[i] != '\0')
+ return false;
+
+ return true;
+ }
+
default:
return false;
}
tree_node_counts[(int) omp_clause_kind]++;
tree_node_sizes[(int) omp_clause_kind] += size;
#endif
-
+
return t;
}
{
tree t = type;
if (POINTER_TYPE_P (type))
- t = size_type_node;
+ {
+ /* If the pointer points to the normal address space, use the
+ size_type_node. Otherwise use an appropriate size for the pointer
+ based on the named address space it points to. */
+ if (!TYPE_ADDR_SPACE (TREE_TYPE (t)))
+ t = size_type_node;
+ else
+ return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
+ }
if (!INTEGRAL_TYPE_P (t) || TYPE_UNSIGNED (t) == unsignedp)
return t;
-
+
return lang_hooks.types.type_for_size (TYPE_PRECISION (t), unsignedp);
}
}
/* Returns number of zeros at the end of binary representation of X.
-
+
??? Use ffs if available? */
tree
that are directly gimplified in gimplify_type_sizes in order for the
mark/copy-if-shared/unmark machinery of the gimplifier to work with
variable-sized types.
-
+
Note that DECLs get walked as part of processing the BIND_EXPR. */
if (TREE_CODE (DECL_EXPR_DECL (*tp)) == TYPE_DECL)
{
return result;
/* If this is a record type, also walk the fields. */
- if (TREE_CODE (*type_p) == RECORD_TYPE
- || TREE_CODE (*type_p) == UNION_TYPE
- || TREE_CODE (*type_p) == QUAL_UNION_TYPE)
+ if (RECORD_OR_UNION_TYPE_P (*type_p))
{
tree field;
return NULL;
}
-/* Build and return a TREE_LIST of arguments in the CALL_EXPR exp.
- FIXME: don't use this function. It exists for compatibility with
- the old representation of CALL_EXPRs where a list was used to hold the
- arguments. Places that currently extract the arglist from a CALL_EXPR
- ought to be rewritten to use the CALL_EXPR itself. */
-tree
-call_expr_arglist (tree exp)
-{
- tree arglist = NULL_TREE;
- int i;
- for (i = call_expr_nargs (exp) - 1; i >= 0; i--)
- arglist = tree_cons (NULL_TREE, CALL_EXPR_ARG (exp, i), arglist);
- return arglist;
-}
-
-
/* Create a nameless artificial label and put it in the current
function context. The label has a location of LOC. Returns the
newly created label. */
outer_type = TREE_TYPE (exp);
inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
+ if (!inner_type)
+ return false;
+
/* Use precision rather then machine mode when we can, which gives
the correct answer even for submode (bit-field) types. */
if ((INTEGRAL_TYPE_P (outer_type)
return exp;
}
+static GTY(()) tree gcc_eh_personality_decl;
+
+/* Return the GCC personality function decl. */
+
+tree
+lhd_gcc_personality (void)
+{
+ if (!gcc_eh_personality_decl)
+ gcc_eh_personality_decl
+ = build_personality_function (USING_SJLJ_EXCEPTIONS
+ ? "__gcc_personality_sj0"
+ : "__gcc_personality_v0");
+
+ return gcc_eh_personality_decl;
+}
+
+/* Try to find a base info of BINFO that would have its field decl at offset
+ OFFSET within the BINFO type and which is of EXPECTED_TYPE. If it can be
+ found, return, otherwise return NULL_TREE. */
+
+tree
+get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
+{
+ tree type;
+
+ if (offset == 0)
+ return binfo;
+
+ type = TREE_TYPE (binfo);
+ while (offset > 0)
+ {
+ tree base_binfo, found_binfo;
+ HOST_WIDE_INT pos, size;
+ tree fld;
+ int i;
+
+ if (TREE_CODE (type) != RECORD_TYPE)
+ return NULL_TREE;
+
+ for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+ {
+ if (TREE_CODE (fld) != FIELD_DECL)
+ continue;
+
+ pos = int_bit_position (fld);
+ size = tree_low_cst (DECL_SIZE (fld), 1);
+ if (pos <= offset && (pos + size) > offset)
+ break;
+ }
+ if (!fld)
+ return NULL_TREE;
+
+ found_binfo = NULL_TREE;
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (TREE_TYPE (base_binfo) == TREE_TYPE (fld))
+ {
+ found_binfo = base_binfo;
+ break;
+ }
+
+ if (!found_binfo)
+ return NULL_TREE;
+
+ type = TREE_TYPE (fld);
+ binfo = found_binfo;
+ offset -= pos;
+ }
+ if (type != expected_type)
+ return NULL_TREE;
+ return binfo;
+}
#include "gt-tree.h"