/* Language-independent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987-2014 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
tables index by tree code that describe how to take apart
nodes of that code.
- It is intended to be language-independent, but occasionally
- calls language-dependent routines defined (for C) in typecheck.c. */
+ It is intended to be language-independent but can occasionally
+ calls language-dependent routines. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "flags.h"
+#include "alias.h"
+#include "symtab.h"
#include "tree.h"
+#include "fold-const.h"
#include "stor-layout.h"
#include "calls.h"
#include "attribs.h"
#include "varasm.h"
#include "tm_p.h"
-#include "hashtab.h"
-#include "hash-set.h"
-#include "vec.h"
-#include "machmode.h"
#include "hard-reg-set.h"
-#include "input.h"
#include "function.h"
#include "obstack.h"
#include "toplev.h" /* get_random_seed */
-#include "inchash.h"
#include "filenames.h"
#include "output.h"
#include "target.h"
#include "tree-ssa-alias.h"
#include "internal-fn.h"
#include "gimple-expr.h"
-#include "is-a.h"
#include "gimple.h"
#include "gimple-iterator.h"
#include "gimplify.h"
#include "gimple-ssa.h"
-#include "hash-map.h"
-#include "plugin-api.h"
-#include "ipa-ref.h"
#include "cgraph.h"
#include "tree-phinodes.h"
#include "stringpool.h"
#include "tree-ssanames.h"
+#include "rtl.h"
+#include "insn-config.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "stmt.h"
#include "expr.h"
#include "tree-dfa.h"
#include "params.h"
#include "except.h"
#include "debug.h"
#include "intl.h"
-#include "wide-int.h"
#include "builtins.h"
+#include "print-tree.h"
+#include "ipa-utils.h"
/* Tree code classes. */
/* Since we cannot rehash a type after it is in the table, we have to
keep the hash code. */
-struct GTY(()) type_hash {
+struct GTY((for_user)) type_hash {
unsigned long hash;
tree type;
};
/* Initial size of the hash table (rounded to next prime). */
#define TYPE_HASH_INITIAL_SIZE 1000
+struct type_cache_hasher : ggc_cache_ptr_hash<type_hash>
+{
+ static hashval_t hash (type_hash *t) { return t->hash; }
+ static bool equal (type_hash *a, type_hash *b);
+
+ static int
+ keep_cache_entry (type_hash *&t)
+ {
+ return ggc_marked_p (t->type);
+ }
+};
+
/* Now here is the hash table. When recording a type, it is added to
the slot whose index is the hash code. Note that the hash table is
used for several kinds of types (function types, array types and
same table, they are completely independent, and the hash code is
computed differently for each of these. */
-static GTY ((if_marked ("type_hash_marked_p"), param_is (struct type_hash)))
- htab_t type_hash_table;
+static GTY ((cache)) hash_table<type_cache_hasher> *type_hash_table;
/* Hash table and temporary node for larger integer const values. */
static GTY (()) tree int_cst_node;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t int_cst_hash_table;
+
+struct int_cst_hasher : ggc_cache_ptr_hash<tree_node>
+{
+ static hashval_t hash (tree t);
+ static bool equal (tree x, tree y);
+};
+
+static GTY ((cache)) hash_table<int_cst_hasher> *int_cst_hash_table;
/* Hash table for optimization flags and target option flags. Use the same
hash table for both sets of options. Nodes for building the current
allocating and freeing up a node repeatably. */
static GTY (()) tree cl_optimization_node;
static GTY (()) tree cl_target_option_node;
-static GTY ((if_marked ("ggc_marked_p"), param_is (union tree_node)))
- htab_t cl_option_hash_table;
+
+struct cl_option_hasher : ggc_cache_ptr_hash<tree_node>
+{
+ static hashval_t hash (tree t);
+ static bool equal (tree x, tree y);
+};
+
+static GTY ((cache)) hash_table<cl_option_hasher> *cl_option_hash_table;
/* General tree->tree mapping structure for use in hash tables. */
-static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
- htab_t debug_expr_for_decl;
+static GTY ((cache))
+ hash_table<tree_decl_map_cache_hasher> *debug_expr_for_decl;
-static GTY ((if_marked ("tree_decl_map_marked_p"), param_is (struct tree_decl_map)))
- htab_t value_expr_for_decl;
+static GTY ((cache))
+ hash_table<tree_decl_map_cache_hasher> *value_expr_for_decl;
-static GTY ((if_marked ("tree_vec_map_marked_p"), param_is (struct tree_vec_map)))
- htab_t debug_args_for_decl;
+struct tree_vec_map_cache_hasher : ggc_cache_ptr_hash<tree_vec_map>
+{
+ static hashval_t hash (tree_vec_map *m) { return DECL_UID (m->base.from); }
+
+ static bool
+ equal (tree_vec_map *a, tree_vec_map *b)
+ {
+ return a->base.from == b->base.from;
+ }
+
+ static int
+ keep_cache_entry (tree_vec_map *&m)
+ {
+ return ggc_marked_p (m->base.from);
+ }
+};
+
+static GTY ((cache))
+ hash_table<tree_vec_map_cache_hasher> *debug_args_for_decl;
static void set_type_quals (tree, int);
-static int type_hash_eq (const void *, const void *);
-static hashval_t type_hash_hash (const void *);
-static hashval_t int_cst_hash_hash (const void *);
-static int int_cst_hash_eq (const void *, const void *);
-static hashval_t cl_option_hash_hash (const void *);
-static int cl_option_hash_eq (const void *, const void *);
static void print_type_hash_statistics (void);
static void print_debug_expr_statistics (void);
static void print_value_expr_statistics (void);
-static int type_hash_marked_p (const void *);
static void type_hash_list (const_tree, inchash::hash &);
static void attribute_hash_list (const_tree, inchash::hash &);
2, /* OMP_CLAUSE_FROM */
2, /* OMP_CLAUSE_TO */
2, /* OMP_CLAUSE_MAP */
+ 2, /* OMP_CLAUSE__CACHE_ */
+ 1, /* OMP_CLAUSE_DEVICE_RESIDENT */
+ 1, /* OMP_CLAUSE_USE_DEVICE */
+ 2, /* OMP_CLAUSE_GANG */
+ 1, /* OMP_CLAUSE_ASYNC */
+ 1, /* OMP_CLAUSE_WAIT */
+ 0, /* OMP_CLAUSE_AUTO */
+ 0, /* OMP_CLAUSE_SEQ */
1, /* OMP_CLAUSE__LOOPTEMP_ */
1, /* OMP_CLAUSE_IF */
1, /* OMP_CLAUSE_NUM_THREADS */
0, /* OMP_CLAUSE_TASKGROUP */
1, /* OMP_CLAUSE__SIMDUID_ */
1, /* OMP_CLAUSE__CILK_FOR_COUNT_ */
+ 0, /* OMP_CLAUSE_INDEPENDENT */
+ 1, /* OMP_CLAUSE_WORKER */
+ 1, /* OMP_CLAUSE_VECTOR */
+ 1, /* OMP_CLAUSE_NUM_GANGS */
+ 1, /* OMP_CLAUSE_NUM_WORKERS */
+ 1, /* OMP_CLAUSE_VECTOR_LENGTH */
};
const char * const omp_clause_code_name[] =
"from",
"to",
"map",
+ "_cache_",
+ "device_resident",
+ "use_device",
+ "gang",
+ "async",
+ "wait",
+ "auto",
+ "seq",
"_looptemp_",
"if",
"num_threads",
"sections",
"taskgroup",
"_simduid_",
- "_Cilk_for_count_"
+ "_Cilk_for_count_",
+ "independent",
+ "worker",
+ "vector",
+ "num_gangs",
+ "num_workers",
+ "vector_length"
};
init_ttree (void)
{
/* Initialize the hash table of types. */
- type_hash_table = htab_create_ggc (TYPE_HASH_INITIAL_SIZE, type_hash_hash,
- type_hash_eq, 0);
+ type_hash_table
+ = hash_table<type_cache_hasher>::create_ggc (TYPE_HASH_INITIAL_SIZE);
- debug_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
- tree_decl_map_eq, 0);
+ debug_expr_for_decl
+ = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
- value_expr_for_decl = htab_create_ggc (512, tree_decl_map_hash,
- tree_decl_map_eq, 0);
+ value_expr_for_decl
+ = hash_table<tree_decl_map_cache_hasher>::create_ggc (512);
- int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
- int_cst_hash_eq, NULL);
+ int_cst_hash_table = hash_table<int_cst_hasher>::create_ggc (1024);
int_cst_node = make_int_cst (1, 1);
- cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
- cl_option_hash_eq, NULL);
+ cl_option_hash_table = hash_table<cl_option_hasher>::create_ggc (64);
cl_optimization_node = make_node (OPTIMIZATION_NODE);
cl_target_option_node = make_node (TARGET_OPTION_NODE);
}
break;
+ case tcc_exceptional:
+ switch (code)
+ {
+ case TARGET_OPTION_NODE:
+ TREE_TARGET_OPTION(t)
+ = ggc_cleared_alloc<struct cl_target_option> ();
+ break;
+
+ case OPTIMIZATION_NODE:
+ TREE_OPTIMIZATION (t)
+ = ggc_cleared_alloc<struct cl_optimization> ();
+ break;
+
+ default:
+ break;
+ }
+ break;
+
default:
/* Other classes need no special treatment. */
break;
TYPE_CACHED_VALUES (t) = NULL_TREE;
}
}
+ else if (code == TARGET_OPTION_NODE)
+ {
+ TREE_TARGET_OPTION (t) = ggc_alloc<struct cl_target_option>();
+ memcpy (TREE_TARGET_OPTION (t), TREE_TARGET_OPTION (node),
+ sizeof (struct cl_target_option));
+ }
+ else if (code == OPTIMIZATION_NODE)
+ {
+ TREE_OPTIMIZATION (t) = ggc_alloc<struct cl_optimization>();
+ memcpy (TREE_OPTIMIZATION (t), TREE_OPTIMIZATION (node),
+ sizeof (struct cl_optimization));
+ }
return t;
}
/* Return the hash code code X, an INTEGER_CST. */
-static hashval_t
-int_cst_hash_hash (const void *x)
+hashval_t
+int_cst_hasher::hash (tree x)
{
- const_tree const t = (const_tree) x;
- hashval_t code = htab_hash_pointer (TREE_TYPE (t));
+ const_tree const t = x;
+ hashval_t code = TYPE_UID (TREE_TYPE (t));
int i;
for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
/* Return nonzero if the value represented by *X (an INTEGER_CST tree node)
is the same as that given by *Y, which is the same. */
-static int
-int_cst_hash_eq (const void *x, const void *y)
+bool
+int_cst_hasher::equal (tree x, tree y)
{
- const_tree const xt = (const_tree) x;
- const_tree const yt = (const_tree) y;
+ const_tree const xt = x;
+ const_tree const yt = y;
if (TREE_TYPE (xt) != TREE_TYPE (yt)
|| TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
case POINTER_TYPE:
case REFERENCE_TYPE:
- /* Cache NULL pointer. */
+ case POINTER_BOUNDS_TYPE:
+ /* Cache NULL pointer and zero bounds. */
if (hwi == 0)
{
limit = 1;
{
/* Use the cache of larger shared ints, using int_cst_node as
a temporary. */
- void **slot;
TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
TREE_TYPE (int_cst_node) = type;
- slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
- t = (tree) *slot;
+ tree *slot = int_cst_hash_table->find_slot (int_cst_node, INSERT);
+ t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
/* The value either hashes properly or we drop it on the floor
for the gc to take care of. There will not be enough of them
to worry about. */
- void **slot;
tree nt = build_new_int_cst (type, cst);
- slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
- t = (tree) *slot;
+ tree *slot = int_cst_hash_table->find_slot (nt, INSERT);
+ t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
else
{
/* Use the cache of larger shared ints. */
- void **slot;
-
- slot = htab_find_slot (int_cst_hash_table, t, INSERT);
+ tree *slot = int_cst_hash_table->find_slot (t, INSERT);
/* If there is already an entry for the number verify it's the
same. */
if (*slot)
return TREE_INT_CST_NUNITS (x) == 1;
}
-/* Build a newly constructed TREE_VEC node of length LEN. */
+/* Build a newly constructed VECTOR_CST node of length LEN. */
tree
make_vector_stat (unsigned len MEM_STAT_DECL)
|| integer_nonzerop (TREE_IMAGPART (expr)))));
}
+/* Return 1 if EXPR is the integer constant one. For vector,
+ return 1 if every piece is the integer constant minus one
+ (representing the value TRUE). */
+
+int
+integer_truep (const_tree expr)
+{
+ STRIP_NOPS (expr);
+
+ if (TREE_CODE (expr) == VECTOR_CST)
+ return integer_all_onesp (expr);
+ return integer_onep (expr);
+}
+
/* Return 1 if EXPR is the fixed-point constant zero. */
int
switch (TREE_CODE (type))
{
case VOID_TYPE:
+ case POINTER_BOUNDS_TYPE:
case COMPLEX_TYPE:
case ENUMERAL_TYPE:
case BOOLEAN_TYPE:
PROCESS_ARG (0);
PROCESS_ARG (1);
- TREE_READONLY (t) = read_only;
- TREE_CONSTANT (t) = constant;
TREE_SIDE_EFFECTS (t) = side_effects;
- TREE_THIS_VOLATILE (t)
- = (TREE_CODE_CLASS (code) == tcc_reference
- && arg0 && TREE_THIS_VOLATILE (arg0));
+ if (code == MEM_REF)
+ {
+ if (arg0 && TREE_CODE (arg0) == ADDR_EXPR)
+ {
+ tree o = TREE_OPERAND (arg0, 0);
+ TREE_READONLY (t) = TREE_READONLY (o);
+ TREE_THIS_VOLATILE (t) = TREE_THIS_VOLATILE (o);
+ }
+ }
+ else
+ {
+ TREE_READONLY (t) = read_only;
+ TREE_CONSTANT (t) = constant;
+ TREE_THIS_VOLATILE (t)
+ = (TREE_CODE_CLASS (code) == tcc_reference
+ && arg0 && TREE_THIS_VOLATILE (arg0));
+ }
return t;
}
PROCESS_ARG (4);
TREE_SIDE_EFFECTS (t) = side_effects;
- TREE_THIS_VOLATILE (t)
- = (TREE_CODE_CLASS (code) == tcc_reference
- && arg0 && TREE_THIS_VOLATILE (arg0));
+ if (code == TARGET_MEM_REF)
+ {
+ if (arg0 && TREE_CODE (arg0) == ADDR_EXPR)
+ {
+ tree o = TREE_OPERAND (arg0, 0);
+ TREE_READONLY (t) = TREE_READONLY (o);
+ TREE_THIS_VOLATILE (t) = TREE_THIS_VOLATILE (o);
+ }
+ }
+ else
+ TREE_THIS_VOLATILE (t)
+ = (TREE_CODE_CLASS (code) == tcc_reference
+ && arg0 && TREE_THIS_VOLATILE (arg0));
return t;
}
return l1 == l2;
}
-/* Compare two attributes for their value identity. Return true if the
- attribute values are known to be equal; otherwise return false.
-*/
+/* Compare two identifier nodes representing attributes. Either one may
+ be in wrapped __ATTR__ form. Return true if they are the same, false
+ otherwise. */
static bool
+cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
+{
+ /* Make sure we're dealing with IDENTIFIER_NODEs. */
+ gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
+ && TREE_CODE (attr2) == IDENTIFIER_NODE);
+
+ /* Identifiers can be compared directly for equality. */
+ if (attr1 == attr2)
+ return true;
+
+ /* If they are not equal, they may still be one in the form
+ 'text' while the other one is in the form '__text__'. TODO:
+ If we were storing attributes in normalized 'text' form, then
+ this could all go away and we could take full advantage of
+ the fact that we're comparing identifiers. :-) */
+ const size_t attr1_len = IDENTIFIER_LENGTH (attr1);
+ const size_t attr2_len = IDENTIFIER_LENGTH (attr2);
+
+ if (attr2_len == attr1_len + 4)
+ {
+ const char *p = IDENTIFIER_POINTER (attr2);
+ const char *q = IDENTIFIER_POINTER (attr1);
+ if (p[0] == '_' && p[1] == '_'
+ && p[attr2_len - 2] == '_' && p[attr2_len - 1] == '_'
+ && strncmp (q, p + 2, attr1_len) == 0)
+ return true;;
+ }
+ else if (attr2_len + 4 == attr1_len)
+ {
+ const char *p = IDENTIFIER_POINTER (attr2);
+ const char *q = IDENTIFIER_POINTER (attr1);
+ if (q[0] == '_' && q[1] == '_'
+ && q[attr1_len - 2] == '_' && q[attr1_len - 1] == '_'
+ && strncmp (q + 2, p, attr2_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+/* Compare two attributes for their value identity. Return true if the
+ attribute values are known to be equal; otherwise return false. */
+
+bool
attribute_value_equal (const_tree attr1, const_tree attr2)
{
if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
if (TREE_VALUE (attr1) != NULL_TREE
&& TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
- && TREE_VALUE (attr2) != NULL
+ && TREE_VALUE (attr2) != NULL_TREE
&& TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
- return (simple_cst_list_equal (TREE_VALUE (attr1),
- TREE_VALUE (attr2)) == 1);
+ {
+ /* Handle attribute format. */
+ if (is_attribute_p ("format", TREE_PURPOSE (attr1)))
+ {
+ attr1 = TREE_VALUE (attr1);
+ attr2 = TREE_VALUE (attr2);
+ /* Compare the archetypes (printf/scanf/strftime/...). */
+ if (!cmp_attrib_identifiers (TREE_VALUE (attr1),
+ TREE_VALUE (attr2)))
+ return false;
+ /* Archetypes are the same. Compare the rest. */
+ return (simple_cst_list_equal (TREE_CHAIN (attr1),
+ TREE_CHAIN (attr2)) == 1);
+ }
+ return (simple_cst_list_equal (TREE_VALUE (attr1),
+ TREE_VALUE (attr2)) == 1);
+ }
if ((flag_openmp || flag_openmp_simd)
&& TREE_VALUE (attr1) && TREE_VALUE (attr2)
TREE_VALUE (p) = build_qualified_type (arg_type, quals);
free_lang_data_in_type (TREE_VALUE (p));
}
+ /* C++ FE uses TREE_PURPOSE to store initial values. */
+ TREE_PURPOSE (p) = NULL;
+ }
+ /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
+ TYPE_MINVAL (type) = NULL;
+ }
+ if (TREE_CODE (type) == METHOD_TYPE)
+ {
+ tree p;
+
+ for (p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
+ {
+ /* C++ FE uses TREE_PURPOSE to store initial values. */
+ TREE_PURPOSE (p) = NULL;
}
+ /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
+ TYPE_MINVAL (type) = NULL;
}
/* Remove members that are not actually FIELD_DECLs from the field
else
TYPE_FIELDS (type) = NULL_TREE;
- TYPE_METHODS (type) = NULL_TREE;
+ /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
+ and danagle the pointer from time to time. */
+ if (TYPE_VFIELD (type) && TREE_CODE (TYPE_VFIELD (type)) != FIELD_DECL)
+ TYPE_VFIELD (type) = NULL_TREE;
+
+ /* Remove TYPE_METHODS list. While it would be nice to keep it
+ to enable ODR warnings about different method lists, doing so
+ seems to impractically increase size of LTO data streamed.
+ Keep the infrmation if TYPE_METHODS was non-NULL. This is used
+ by function.c and pretty printers. */
+ if (TYPE_METHODS (type))
+ TYPE_METHODS (type) = error_mark_node;
if (TYPE_BINFO (type))
- free_lang_data_in_binfo (TYPE_BINFO (type));
+ {
+ free_lang_data_in_binfo (TYPE_BINFO (type));
+ /* We need to preserve link to bases and virtual table for all
+ polymorphic types to make devirtualization machinery working.
+ Debug output cares only about bases, but output also
+ virtual table pointers so merging of -fdevirtualize and
+ -fno-devirtualize units is easier. */
+ if ((!BINFO_VTABLE (TYPE_BINFO (type))
+ || !flag_devirtualize)
+ && ((!BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
+ && !BINFO_VTABLE (TYPE_BINFO (type)))
+ || debug_info_level != DINFO_LEVEL_NONE))
+ TYPE_BINFO (type) = NULL;
+ }
}
else
{
static inline bool
need_assembler_name_p (tree decl)
{
- /* We use DECL_ASSEMBLER_NAME to hold mangled type names for One Definition Rule
- merging. */
+ /* We use DECL_ASSEMBLER_NAME to hold mangled type names for One Definition
+ Rule merging. This makes type_odr_p to return true on those types during
+ LTO and by comparing the mangled name, we can say what types are intended
+ to be equivalent across compilation unit.
+
+ We do not store names of type_in_anonymous_namespace_p.
+
+ Record, union and enumeration type have linkage that allows use
+ to check type_in_anonymous_namespace_p. We do not mangle compound types
+ that always can be compared structurally.
+
+ Similarly for builtin types, we compare properties of their main variant.
+ A special case are integer types where mangling do make differences
+ between char/signed char/unsigned char etc. Storing name for these makes
+ e.g. -fno-signed-char/-fsigned-char mismatches to be handled well.
+ See cp/mangle.c:write_builtin_type for details. */
+
if (flag_lto_odr_type_mering
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_NAME (decl)
&& decl == TYPE_NAME (TREE_TYPE (decl))
- && !is_lang_specific (TREE_TYPE (decl))
- && AGGREGATE_TYPE_P (TREE_TYPE (decl))
- && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)
- && !type_in_anonymous_namespace_p (TREE_TYPE (decl)))
+ && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
+ && (type_with_linkage_p (TREE_TYPE (decl))
+ || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE)
+ && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
return !DECL_ASSEMBLER_NAME_SET_P (decl);
/* Only FUNCTION_DECLs and VAR_DECLs are considered. */
if (TREE_CODE (decl) != FUNCTION_DECL
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;
+ if (!DECL_FUNCTION_SPECIFIC_TARGET (decl))
+ DECL_FUNCTION_SPECIFIC_TARGET (decl)
+ = target_option_default_node;
+ if (!DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl))
+ DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
+ = optimization_default_node;
}
/* DECL_SAVED_TREE holds the GENERIC representation for DECL.
/* Traverse every statement in FN. */
FOR_EACH_BB_FN (bb, fn)
{
+ gphi_iterator psi;
gimple_stmt_iterator si;
unsigned i;
- for (si = gsi_start_phis (bb); !gsi_end_p (si); gsi_next (&si))
+ for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
{
- gimple phi = gsi_stmt (si);
+ gphi *phi = psi.phi ();
for (i = 0; i < gimple_phi_num_args (phi); i++)
{
/* Traverse every type found freeing its language data. */
FOR_EACH_VEC_ELT (fld.types, i, t)
free_lang_data_in_type (t);
+#ifdef ENABLE_CHECKING
+ FOR_EACH_VEC_ELT (fld.types, i, t)
+ verify_type (t);
+#endif
delete fld.pset;
fld.worklist.release ();
/* If we are the LTO frontend we have freed lang-specific data already. */
if (in_lto_p
- || !flag_generate_lto)
+ || (!flag_generate_lto && !flag_generate_offload))
return 0;
/* Allocate and assign alias sets to the standard integer types
still be used indirectly via the get_alias_set langhook. */
lang_hooks.dwarf_name = lhd_dwarf_name;
lang_hooks.decl_printable_name = gimple_decl_printable_name;
+ lang_hooks.gimplify_expr = lhd_gimplify_expr;
+
/* We do not want the default decl_assembler_name implementation,
rather if we have fixed everything we want a wrapper around it
asserting that all non-local symbols already got their assembler
gcc_checking_assert (TREE_CODE (get_attribute_name (list))
== IDENTIFIER_NODE);
- /* Identifiers can be compared directly for equality. */
- if (attr_identifier == get_attribute_name (list))
+ if (cmp_attrib_identifiers (attr_identifier,
+ get_attribute_name (list)))
+ /* Found it. */
break;
-
- /* If they are not equal, they may still be one in the form
- 'text' while the other one is in the form '__text__'. TODO:
- If we were storing attributes in normalized 'text' form, then
- this could all go away and we could take full advantage of
- the fact that we're comparing identifiers. :-) */
- {
- size_t attr_len = IDENTIFIER_LENGTH (attr_identifier);
- size_t ident_len = IDENTIFIER_LENGTH (get_attribute_name (list));
-
- if (ident_len == attr_len + 4)
- {
- const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
- const char *q = IDENTIFIER_POINTER (attr_identifier);
- if (p[0] == '_' && p[1] == '_'
- && p[ident_len - 2] == '_' && p[ident_len - 1] == '_'
- && strncmp (q, p + 2, attr_len) == 0)
- break;
- }
- else if (ident_len + 4 == attr_len)
- {
- const char *p = IDENTIFIER_POINTER (get_attribute_name (list));
- const char *q = IDENTIFIER_POINTER (attr_identifier);
- if (q[0] == '_' && q[1] == '_'
- && q[attr_len - 2] == '_' && q[attr_len - 1] == '_'
- && strncmp (q + 2, p, ident_len) == 0)
- break;
- }
- }
list = TREE_CHAIN (list);
}
TYPE_MAIN_VARIANT (t) = t;
TYPE_NEXT_VARIANT (t) = 0;
+ /* We do not record methods in type copies nor variants
+ so we do not need to keep them up to date when new method
+ is inserted. */
+ if (RECORD_OR_UNION_TYPE_P (t))
+ TYPE_METHODS (t) = NULL_TREE;
+
/* Note that it is now possible for TYPE_MIN_VALUE to be a value
whose TREE_TYPE is not t. This can also happen in the Ada
frontend when using subtypes. */
print_debug_expr_statistics (void)
{
fprintf (stderr, "DECL_DEBUG_EXPR hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (debug_expr_for_decl),
- (long) htab_elements (debug_expr_for_decl),
- htab_collisions (debug_expr_for_decl));
+ (long) debug_expr_for_decl->size (),
+ (long) debug_expr_for_decl->elements (),
+ debug_expr_for_decl->collisions ());
}
/* Print out the statistics for the DECL_VALUE_EXPR hash table. */
print_value_expr_statistics (void)
{
fprintf (stderr, "DECL_VALUE_EXPR hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (value_expr_for_decl),
- (long) htab_elements (value_expr_for_decl),
- htab_collisions (value_expr_for_decl));
+ (long) value_expr_for_decl->size (),
+ (long) value_expr_for_decl->elements (),
+ value_expr_for_decl->collisions ());
}
/* Lookup a debug expression for FROM, and return it if we find one. */
struct tree_decl_map *h, in;
in.base.from = from;
- h = (struct tree_decl_map *)
- htab_find_with_hash (debug_expr_for_decl, &in, DECL_UID (from));
+ h = debug_expr_for_decl->find_with_hash (&in, DECL_UID (from));
if (h)
return h->to;
return NULL_TREE;
decl_debug_expr_insert (tree from, tree to)
{
struct tree_decl_map *h;
- void **loc;
h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;
- loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
- INSERT);
- *(struct tree_decl_map **) loc = h;
+ *debug_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
}
/* Lookup a value expression for FROM, and return it if we find one. */
struct tree_decl_map *h, in;
in.base.from = from;
- h = (struct tree_decl_map *)
- htab_find_with_hash (value_expr_for_decl, &in, DECL_UID (from));
+ h = value_expr_for_decl->find_with_hash (&in, DECL_UID (from));
if (h)
return h->to;
return NULL_TREE;
decl_value_expr_insert (tree from, tree to)
{
struct tree_decl_map *h;
- void **loc;
h = ggc_alloc<tree_decl_map> ();
h->base.from = from;
h->to = to;
- loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
- INSERT);
- *(struct tree_decl_map **) loc = h;
+ *value_expr_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT) = h;
}
/* Lookup a vector of debug arguments for FROM, and return it if we
return NULL;
gcc_checking_assert (debug_args_for_decl != NULL);
in.base.from = from;
- h = (struct tree_vec_map *)
- htab_find_with_hash (debug_args_for_decl, &in, DECL_UID (from));
+ h = debug_args_for_decl->find_with_hash (&in, DECL_UID (from));
if (h)
return &h->to;
return NULL;
decl_debug_args_insert (tree from)
{
struct tree_vec_map *h;
- void **loc;
+ tree_vec_map **loc;
if (DECL_HAS_DEBUG_ARGS_P (from))
return decl_debug_args_lookup (from);
if (debug_args_for_decl == NULL)
- debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
- tree_vec_map_eq, 0);
+ debug_args_for_decl = hash_table<tree_vec_map_cache_hasher>::create_ggc (64);
h = ggc_alloc<tree_vec_map> ();
h->base.from = from;
h->to = NULL;
- loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
- INSERT);
- *(struct tree_vec_map **) loc = h;
+ loc = debug_args_for_decl->find_slot_with_hash (h, DECL_UID (from), INSERT);
+ *loc = h;
DECL_HAS_DEBUG_ARGS_P (from) = 1;
return &h->to;
}
/* Returns true iff the types are equivalent. */
-static int
-type_hash_eq (const void *va, const void *vb)
+bool
+type_cache_hasher::equal (type_hash *a, type_hash *b)
{
- const struct type_hash *const a = (const struct type_hash *) va,
- *const b = (const struct type_hash *) vb;
-
/* First test the things that are the same for all types. */
if (a->hash != b->hash
|| TREE_CODE (a->type) != TREE_CODE (b->type)
return 1;
}
-/* Return the cached hash value. */
-
-static hashval_t
-type_hash_hash (const void *item)
-{
- return ((const struct type_hash *) item)->hash;
-}
-
/* Given TYPE, and HASHCODE its hash code, return the canonical
object for an identical type if one already exists.
Otherwise, return TYPE, and record it as the canonical object.
type_hash_canon (unsigned int hashcode, tree type)
{
type_hash in;
- void **loc;
+ type_hash **loc;
/* The hash table only contains main variants, so ensure that's what we're
being passed. */
in.hash = hashcode;
in.type = type;
- loc = htab_find_slot_with_hash (type_hash_table, &in, hashcode, INSERT);
+ loc = type_hash_table->find_slot_with_hash (&in, hashcode, INSERT);
if (*loc)
{
tree t1 = ((type_hash *) *loc)->type;
h = ggc_alloc<type_hash> ();
h->hash = hashcode;
h->type = type;
- *loc = (void *)h;
+ *loc = h;
return type;
}
}
-/* See if the data pointed to by the type hash table is marked. We consider
- it marked if the type is marked or if a debug type number or symbol
- table entry has been made for the type. */
-
-static int
-type_hash_marked_p (const void *p)
-{
- const_tree const type = ((const struct type_hash *) p)->type;
-
- return ggc_marked_p (type);
-}
-
static void
print_type_hash_statistics (void)
{
fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
- (long) htab_size (type_hash_table),
- (long) htab_elements (type_hash_table),
- htab_collisions (type_hash_table));
+ (long) type_hash_table->size (),
+ (long) type_hash_table->elements (),
+ type_hash_table->collisions ());
}
/* Compute a hash code for a list of attributes (chain of TREE_LIST nodes
bool can_alias_all)
{
tree t;
+ bool could_alias = can_alias_all;
if (to_type == error_mark_node)
return error_mark_node;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (to_type) != to_type)
+ else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
TYPE_CANONICAL (t)
= build_pointer_type_for_mode (TYPE_CANONICAL (to_type),
- mode, can_alias_all);
+ mode, false);
/* Lay out the type. This function has many callers that are concerned
with expression-construction, and this simplifies them all. */
bool can_alias_all)
{
tree t;
+ bool could_alias = can_alias_all;
if (to_type == error_mark_node)
return error_mark_node;
if (TYPE_STRUCTURAL_EQUALITY_P (to_type))
SET_TYPE_STRUCTURAL_EQUALITY (t);
- else if (TYPE_CANONICAL (to_type) != to_type)
+ else if (TYPE_CANONICAL (to_type) != to_type || could_alias)
TYPE_CANONICAL (t)
= build_reference_type_for_mode (TYPE_CANONICAL (to_type),
- mode, can_alias_all);
+ mode, false);
layout_type (t);
if (TREE_CODE (type) == QUAL_UNION_TYPE)
RETURN_TRUE_IF_VAR (DECL_QUALIFIER (t));
}
- break;
+ break;
case ARRAY_TYPE:
/* Do not call ourselves to avoid infinite recursion. This is
return NULL_TREE;
}
+#define TREE_MEM_USAGE_SPACES 40
+
/* Print debugging information about tree nodes generated during the compile,
and any language-specific information. */
{
int i;
int total_nodes, total_bytes;
- fprintf (stderr, "Kind Nodes Bytes\n");
- fprintf (stderr, "---------------------------------------\n");
+ fprintf (stderr, "\nKind Nodes Bytes\n");
+ mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
total_nodes = total_bytes = 0;
for (i = 0; i < (int) all_kinds; i++)
{
total_nodes += tree_node_counts[i];
total_bytes += tree_node_sizes[i];
}
- fprintf (stderr, "---------------------------------------\n");
+ mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
fprintf (stderr, "%-20s %7d %10d\n", "Total", total_nodes, total_bytes);
- fprintf (stderr, "---------------------------------------\n");
+ mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
fprintf (stderr, "Code Nodes\n");
- fprintf (stderr, "----------------------------\n");
+ mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
for (i = 0; i < (int) MAX_TREE_CODES; i++)
- fprintf (stderr, "%-20s %7d\n", get_tree_code_name ((enum tree_code) i),
+ fprintf (stderr, "%-32s %7d\n", get_tree_code_name ((enum tree_code) i),
tree_code_counts[i]);
- fprintf (stderr, "----------------------------\n");
+ mem_usage::print_dash_line (TREE_MEM_USAGE_SPACES);
+ fprintf (stderr, "\n");
ssanames_print_statistics ();
+ fprintf (stderr, "\n");
phinodes_print_statistics ();
+ fprintf (stderr, "\n");
}
else
fprintf (stderr, "(No per-node statistics)\n");
*p = '_';
}
+/* For anonymous aggregate types, we need some sort of name to
+ hold on to. In practice, this should not appear, but it should
+ not be harmful if it does. */
+bool
+anon_aggrname_p(const_tree id_node)
+{
+#ifndef NO_DOT_IN_LABEL
+ return (IDENTIFIER_POINTER (id_node)[0] == '.'
+ && IDENTIFIER_POINTER (id_node)[1] == '_');
+#else /* NO_DOT_IN_LABEL */
+#ifndef NO_DOLLAR_IN_LABEL
+ return (IDENTIFIER_POINTER (id_node)[0] == '$' \
+ && IDENTIFIER_POINTER (id_node)[1] == '_');
+#else /* NO_DOLLAR_IN_LABEL */
+#define ANON_AGGRNAME_PREFIX "__anon_"
+ return (!strncmp (IDENTIFIER_POINTER (id_node), ANON_AGGRNAME_PREFIX,
+ sizeof (ANON_AGGRNAME_PREFIX) - 1));
+#endif /* NO_DOLLAR_IN_LABEL */
+#endif /* NO_DOT_IN_LABEL */
+}
+
+/* Return a format for an anonymous aggregate name. */
+const char *
+anon_aggrname_format()
+{
+#ifndef NO_DOT_IN_LABEL
+ return "._%d";
+#else /* NO_DOT_IN_LABEL */
+#ifndef NO_DOLLAR_IN_LABEL
+ return "$_%d";
+#else /* NO_DOLLAR_IN_LABEL */
+ return "__anon_%d";
+#endif /* NO_DOLLAR_IN_LABEL */
+#endif /* NO_DOT_IN_LABEL */
+}
+
/* Generate a name for a special-purpose function.
The generated name may need to be unique across the whole link.
Changes to this function may also require corresponding changes to
void_type_node = make_node (VOID_TYPE);
layout_type (void_type_node);
+ pointer_bounds_type_node = targetm.chkp_bound_type ();
+
/* We are not going to have real types in C with less than byte alignment,
so we might as well not have any types that claim to have it. */
TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
local_define_builtin ("__builtin_unreachable", ftype, BUILT_IN_UNREACHABLE,
"__builtin_unreachable",
ECF_NOTHROW | ECF_LEAF | ECF_NORETURN
- | ECF_CONST | ECF_LEAF);
+ | ECF_CONST);
}
if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)
ftype = build_function_type_list (ptr_type_node, size_type_node,
size_type_node, NULL_TREE);
local_define_builtin ("__builtin_alloca_with_align", ftype,
- BUILT_IN_ALLOCA_WITH_ALIGN, "alloca",
+ BUILT_IN_ALLOCA_WITH_ALIGN,
+ "__builtin_alloca_with_align",
ECF_MALLOC | ECF_NOTHROW | ECF_LEAF);
/* If we're checking the stack, `alloca' can throw. */
{
unsigned HOST_WIDE_INT idx;
+ if (TREE_CLOBBER_P (init))
+ return false;
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (init), idx, elt)
if (!initializer_zerop (elt))
return false;
tree fntype = TREE_TYPE (fndecl);
tree fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fndecl);
- return fold_builtin_call_array (loc, TREE_TYPE (fntype), fn, n, argarray);
+ return fold_build_call_array_loc (loc, TREE_TYPE (fntype), fn, n, argarray);
}
/* Conveniently construct a function call expression. FNDECL names the
case OMP_CLAUSE:
switch (OMP_CLAUSE_CODE (*tp))
{
+ case OMP_CLAUSE_GANG:
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
+ /* FALLTHRU */
+
+ case OMP_CLAUSE_DEVICE_RESIDENT:
+ case OMP_CLAUSE_USE_DEVICE:
+ case OMP_CLAUSE_ASYNC:
+ case OMP_CLAUSE_WAIT:
+ case OMP_CLAUSE_WORKER:
+ case OMP_CLAUSE_VECTOR:
+ case OMP_CLAUSE_NUM_GANGS:
+ case OMP_CLAUSE_NUM_WORKERS:
+ case OMP_CLAUSE_VECTOR_LENGTH:
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_FIRSTPRIVATE:
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
/* FALLTHRU */
+ case OMP_CLAUSE_INDEPENDENT:
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
case OMP_CLAUSE_PARALLEL:
case OMP_CLAUSE_SECTIONS:
case OMP_CLAUSE_TASKGROUP:
+ case OMP_CLAUSE_AUTO:
+ case OMP_CLAUSE_SEQ:
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
case OMP_CLAUSE_LASTPRIVATE:
case OMP_CLAUSE_FROM:
case OMP_CLAUSE_TO:
case OMP_CLAUSE_MAP:
+ case OMP_CLAUSE__CACHE_:
WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
/* Return true if TYPE has a prototype. */
bool
-prototype_p (tree fntype)
+prototype_p (const_tree fntype)
{
tree t;
/* Return the hash code code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */
-static hashval_t
-cl_option_hash_hash (const void *x)
+hashval_t
+cl_option_hasher::hash (tree x)
{
- const_tree const t = (const_tree) x;
+ const_tree const t = x;
const char *p;
size_t i;
size_t len = 0;
}
else if (TREE_CODE (t) == TARGET_OPTION_NODE)
- {
- p = (const char *)TREE_TARGET_OPTION (t);
- len = sizeof (struct cl_target_option);
- }
+ return cl_target_option_hash (TREE_TARGET_OPTION (t));
else
gcc_unreachable ();
TARGET_OPTION tree node) is the same as that given by *Y, which is the
same. */
-static int
-cl_option_hash_eq (const void *x, const void *y)
+bool
+cl_option_hasher::equal (tree x, tree y)
{
- const_tree const xt = (const_tree) x;
- const_tree const yt = (const_tree) y;
+ const_tree const xt = x;
+ const_tree const yt = y;
const char *xp;
const char *yp;
size_t len;
else if (TREE_CODE (xt) == TARGET_OPTION_NODE)
{
- xp = (const char *)TREE_TARGET_OPTION (xt);
- yp = (const char *)TREE_TARGET_OPTION (yt);
- len = sizeof (struct cl_target_option);
+ return cl_target_option_eq (TREE_TARGET_OPTION (xt),
+ TREE_TARGET_OPTION (yt));
}
else
build_optimization_node (struct gcc_options *opts)
{
tree t;
- void **slot;
/* Use the cache of optimization nodes. */
cl_optimization_save (TREE_OPTIMIZATION (cl_optimization_node),
opts);
- slot = htab_find_slot (cl_option_hash_table, cl_optimization_node, INSERT);
- t = (tree) *slot;
+ tree *slot = cl_option_hash_table->find_slot (cl_optimization_node, INSERT);
+ t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
build_target_option_node (struct gcc_options *opts)
{
tree t;
- void **slot;
/* Use the cache of optimization nodes. */
cl_target_option_save (TREE_TARGET_OPTION (cl_target_option_node),
opts);
- slot = htab_find_slot (cl_option_hash_table, cl_target_option_node, INSERT);
- t = (tree) *slot;
+ tree *slot = cl_option_hash_table->find_slot (cl_target_option_node, INSERT);
+ t = *slot;
if (!t)
{
/* Insert this one into the hash table. */
return t;
}
-/* Reset TREE_TARGET_GLOBALS cache for TARGET_OPTION_NODE.
- Called through htab_traverse. */
-
-static int
-prepare_target_option_node_for_pch (void **slot, void *)
-{
- tree node = (tree) *slot;
- if (TREE_CODE (node) == TARGET_OPTION_NODE)
- TREE_TARGET_GLOBALS (node) = NULL;
- return 1;
-}
-
/* Clear TREE_TARGET_GLOBALS of all TARGET_OPTION_NODE trees,
so that they aren't saved during PCH writing. */
void
prepare_target_option_nodes_for_pch (void)
{
- htab_traverse (cl_option_hash_table, prepare_target_option_node_for_pch,
- NULL);
+ hash_table<cl_option_hasher>::iterator iter = cl_option_hash_table->begin ();
+ for (; iter != cl_option_hash_table->end (); ++iter)
+ if (TREE_CODE (*iter) == TARGET_OPTION_NODE)
+ TREE_TARGET_GLOBALS (*iter) = NULL;
}
/* Determine the "ultimate origin" of a block. The block may be an inlined
}
}
+/* Return true iff conversion from INNER_TYPE to OUTER_TYPE generates
+ no instruction. */
+
+bool
+tree_nop_conversion_p (const_tree outer_type, const_tree inner_type)
+{
+ /* 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)
+ || POINTER_TYPE_P (outer_type)
+ || TREE_CODE (outer_type) == OFFSET_TYPE)
+ && (INTEGRAL_TYPE_P (inner_type)
+ || POINTER_TYPE_P (inner_type)
+ || TREE_CODE (inner_type) == OFFSET_TYPE))
+ return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
+
+ /* Otherwise fall back on comparing machine modes (e.g. for
+ aggregate types, floats). */
+ return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+}
+
/* Return true iff conversion in EXP generates no instruction. Mark
it inline so that we fully inline into the stripping functions even
though we have two uses of this function. */
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)
- || POINTER_TYPE_P (outer_type)
- || TREE_CODE (outer_type) == OFFSET_TYPE)
- && (INTEGRAL_TYPE_P (inner_type)
- || POINTER_TYPE_P (inner_type)
- || TREE_CODE (inner_type) == OFFSET_TYPE))
- return TYPE_PRECISION (outer_type) == TYPE_PRECISION (inner_type);
-
- /* Otherwise fall back on comparing machine modes (e.g. for
- aggregate types, floats). */
- return TYPE_MODE (outer_type) == TYPE_MODE (inner_type);
+ return tree_nop_conversion_p (outer_type, inner_type);
}
/* Return true iff conversion in EXP generates no instruction. Don't
can't apply.) */
bool
-virtual_method_call_p (tree target)
+virtual_method_call_p (const_tree target)
{
if (TREE_CODE (target) != OBJ_TYPE_REF)
return false;
- target = TREE_TYPE (target);
- gcc_checking_assert (TREE_CODE (target) == POINTER_TYPE);
- target = TREE_TYPE (target);
- if (TREE_CODE (target) == FUNCTION_TYPE)
+ tree t = TREE_TYPE (target);
+ gcc_checking_assert (TREE_CODE (t) == POINTER_TYPE);
+ t = TREE_TYPE (t);
+ if (TREE_CODE (t) == FUNCTION_TYPE)
+ return false;
+ gcc_checking_assert (TREE_CODE (t) == METHOD_TYPE);
+ /* If we do not have BINFO associated, it means that type was built
+ without devirtualization enabled. Do not consider this a virtual
+ call. */
+ if (!TYPE_BINFO (obj_type_ref_class (target)))
return false;
- gcc_checking_assert (TREE_CODE (target) == METHOD_TYPE);
return true;
}
/* REF is OBJ_TYPE_REF, return the class the ref corresponds to. */
tree
-obj_type_ref_class (tree ref)
+obj_type_ref_class (const_tree ref)
{
gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
ref = TREE_TYPE (ref);
return TREE_TYPE (ref);
}
-/* Return true if T is in anonymous namespace. */
+/* Lookup sub-BINFO of BINFO of TYPE at offset POS. */
-bool
-type_in_anonymous_namespace_p (const_tree t)
+static tree
+lookup_binfo_at_offset (tree binfo, tree type, HOST_WIDE_INT pos)
{
- /* TREE_PUBLIC of TYPE_STUB_DECL may not be properly set for
- bulitin types; those have CONTEXT NULL. */
- if (!TYPE_CONTEXT (t))
- return false;
- return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t)));
+ unsigned int i;
+ tree base_binfo, b;
+
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (pos == tree_to_shwi (BINFO_OFFSET (base_binfo))
+ && types_same_for_odr (TREE_TYPE (base_binfo), type))
+ return base_binfo;
+ else if ((b = lookup_binfo_at_offset (base_binfo, type, pos)) != NULL)
+ return b;
+ return NULL;
}
/* Try to find a base info of BINFO that would have its field decl at offset
for (fld = TYPE_FIELDS (type); fld; fld = DECL_CHAIN (fld))
{
- if (TREE_CODE (fld) != FIELD_DECL)
+ if (TREE_CODE (fld) != FIELD_DECL || !DECL_ARTIFICIAL (fld))
continue;
pos = int_bit_position (fld);
if (!fld || TREE_CODE (TREE_TYPE (fld)) != RECORD_TYPE)
return NULL_TREE;
- if (!DECL_ARTIFICIAL (fld))
- {
- binfo = TYPE_BINFO (TREE_TYPE (fld));
- if (!binfo)
- return NULL_TREE;
- }
/* Offset 0 indicates the primary base, whose vtable contents are
represented in the binfo for the derived class. */
else if (offset != 0)
{
- tree base_binfo, binfo2 = binfo;
-
- /* Find BINFO corresponding to FLD. This is bit harder
- by a fact that in virtual inheritance we may need to walk down
- the non-virtual inheritance chain. */
- while (true)
- {
- tree containing_binfo = NULL, found_binfo = NULL;
- for (i = 0; BINFO_BASE_ITERATE (binfo2, i, base_binfo); i++)
- if (types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
- {
- found_binfo = base_binfo;
- break;
- }
- else
- if ((tree_to_shwi (BINFO_OFFSET (base_binfo))
- - tree_to_shwi (BINFO_OFFSET (binfo)))
- * BITS_PER_UNIT < pos
- /* Rule out types with no virtual methods or we can get confused
- here by zero sized bases. */
- && BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (base_binfo)))
- && (!containing_binfo
- || (tree_to_shwi (BINFO_OFFSET (containing_binfo))
- < tree_to_shwi (BINFO_OFFSET (base_binfo)))))
- containing_binfo = base_binfo;
- if (found_binfo)
- {
- binfo = found_binfo;
- break;
- }
- if (!containing_binfo)
- return NULL_TREE;
- binfo2 = containing_binfo;
- }
- }
+ tree found_binfo = NULL, base_binfo;
+ /* Offsets in BINFO are in bytes relative to the whole structure
+ while POS is in bits relative to the containing field. */
+ int binfo_offset = (tree_to_shwi (BINFO_OFFSET (binfo)) + pos
+ / BITS_PER_UNIT);
+
+ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (tree_to_shwi (BINFO_OFFSET (base_binfo)) == binfo_offset
+ && types_same_for_odr (TREE_TYPE (base_binfo), TREE_TYPE (fld)))
+ {
+ found_binfo = base_binfo;
+ break;
+ }
+ if (found_binfo)
+ binfo = found_binfo;
+ else
+ binfo = lookup_binfo_at_offset (binfo, TREE_TYPE (fld),
+ binfo_offset);
+ }
type = TREE_TYPE (fld);
offset -= pos;
/* Returns true if X is a typedef decl. */
bool
-is_typedef_decl (tree x)
+is_typedef_decl (const_tree x)
{
return (x && TREE_CODE (x) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
/* Returns true iff TYPE is a type variant created for a typedef. */
bool
-typedef_variant_p (tree type)
+typedef_variant_p (const_tree type)
{
return is_typedef_decl (TYPE_NAME (type));
}
else
msg = NULL;
+ bool w;
if (DECL_P (node))
{
- expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (node));
if (msg)
- warning (OPT_Wdeprecated_declarations,
- "%qD is deprecated (declared at %r%s:%d%R): %s",
- node, "locus", xloc.file, xloc.line, msg);
+ w = warning (OPT_Wdeprecated_declarations,
+ "%qD is deprecated: %s", node, msg);
else
- warning (OPT_Wdeprecated_declarations,
- "%qD is deprecated (declared at %r%s:%d%R)",
- node, "locus", xloc.file, xloc.line);
+ w = warning (OPT_Wdeprecated_declarations,
+ "%qD is deprecated", node);
+ if (w)
+ inform (DECL_SOURCE_LOCATION (node), "declared here");
}
else if (TYPE_P (node))
{
if (decl)
{
- expanded_location xloc
- = expand_location (DECL_SOURCE_LOCATION (decl));
if (what)
{
if (msg)
- warning (OPT_Wdeprecated_declarations,
- "%qE is deprecated (declared at %r%s:%d%R): %s",
- what, "locus", xloc.file, xloc.line, msg);
+ w = warning (OPT_Wdeprecated_declarations,
+ "%qE is deprecated: %s", what, msg);
else
- warning (OPT_Wdeprecated_declarations,
- "%qE is deprecated (declared at %r%s:%d%R)",
- what, "locus", xloc.file, xloc.line);
+ w = warning (OPT_Wdeprecated_declarations,
+ "%qE is deprecated", what);
}
else
{
if (msg)
- warning (OPT_Wdeprecated_declarations,
- "type is deprecated (declared at %r%s:%d%R): %s",
- "locus", xloc.file, xloc.line, msg);
+ w = warning (OPT_Wdeprecated_declarations,
+ "type is deprecated: %s", msg);
else
- warning (OPT_Wdeprecated_declarations,
- "type is deprecated (declared at %r%s:%d%R)",
- "locus", xloc.file, xloc.line);
+ w = warning (OPT_Wdeprecated_declarations,
+ "type is deprecated");
}
+ if (w)
+ inform (DECL_SOURCE_LOCATION (decl), "declared here");
}
else
{
return t;
}
+/* Return a tree of sizetype representing the size, in bytes, of the element
+ of EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+
+tree
+array_ref_element_size (tree exp)
+{
+ tree aligned_size = TREE_OPERAND (exp, 3);
+ tree elmt_type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)));
+ location_t loc = EXPR_LOCATION (exp);
+
+ /* If a size was specified in the ARRAY_REF, it's the size measured
+ in alignment units of the element type. So multiply by that value. */
+ if (aligned_size)
+ {
+ /* ??? tree_ssa_useless_type_conversion will eliminate casts to
+ sizetype from another type of the same width and signedness. */
+ if (TREE_TYPE (aligned_size) != sizetype)
+ aligned_size = fold_convert_loc (loc, sizetype, aligned_size);
+ return size_binop_loc (loc, MULT_EXPR, aligned_size,
+ size_int (TYPE_ALIGN_UNIT (elmt_type)));
+ }
+
+ /* Otherwise, take the size from that of the element type. Substitute
+ any PLACEHOLDER_EXPR that we have. */
+ else
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_SIZE_UNIT (elmt_type), exp);
+}
+
+/* Return a tree representing the lower bound of the array mentioned in
+ EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+
+tree
+array_ref_low_bound (tree exp)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+ /* If a lower bound is specified in EXP, use it. */
+ if (TREE_OPERAND (exp, 2))
+ return TREE_OPERAND (exp, 2);
+
+ /* Otherwise, if there is a domain type and it has a lower bound, use it,
+ substituting for a PLACEHOLDER_EXPR as needed. */
+ if (domain_type && TYPE_MIN_VALUE (domain_type))
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MIN_VALUE (domain_type), exp);
+
+ /* Otherwise, return a zero of the appropriate type. */
+ return build_int_cst (TREE_TYPE (TREE_OPERAND (exp, 1)), 0);
+}
+
+/* Return a tree representing the upper bound of the array mentioned in
+ EXP, an ARRAY_REF or an ARRAY_RANGE_REF. */
+
+tree
+array_ref_up_bound (tree exp)
+{
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+ /* If there is a domain type and it has an upper bound, use it, substituting
+ for a PLACEHOLDER_EXPR as needed. */
+ if (domain_type && TYPE_MAX_VALUE (domain_type))
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (TYPE_MAX_VALUE (domain_type), exp);
+
+ /* Otherwise fail. */
+ return NULL_TREE;
+}
+
+/* Returns true if REF is an array reference to an array at the end of
+ a structure. If this is the case, the array may be allocated larger
+ than its upper bound implies. */
+
+bool
+array_at_struct_end_p (tree ref)
+{
+ if (TREE_CODE (ref) != ARRAY_REF
+ && TREE_CODE (ref) != ARRAY_RANGE_REF)
+ return false;
+
+ while (handled_component_p (ref))
+ {
+ /* If the reference chain contains a component reference to a
+ non-union type and there follows another field the reference
+ is not at the end of a structure. */
+ if (TREE_CODE (ref) == COMPONENT_REF
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+ {
+ tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+ while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+ nextf = DECL_CHAIN (nextf);
+ if (nextf)
+ return false;
+ }
+
+ ref = TREE_OPERAND (ref, 0);
+ }
+
+ /* If the reference is based on a declared entity, the size of the array
+ is constrained by its given domain. */
+ if (DECL_P (ref))
+ return false;
+
+ return true;
+}
+
+/* Return a tree representing the offset, in bytes, of the field referenced
+ by EXP. This does not include any offset in DECL_FIELD_BIT_OFFSET. */
+
+tree
+component_ref_field_offset (tree exp)
+{
+ tree aligned_offset = TREE_OPERAND (exp, 2);
+ tree field = TREE_OPERAND (exp, 1);
+ location_t loc = EXPR_LOCATION (exp);
+
+ /* If an offset was specified in the COMPONENT_REF, it's the offset measured
+ in units of DECL_OFFSET_ALIGN / BITS_PER_UNIT. So multiply by that
+ value. */
+ if (aligned_offset)
+ {
+ /* ??? tree_ssa_useless_type_conversion will eliminate casts to
+ sizetype from another type of the same width and signedness. */
+ if (TREE_TYPE (aligned_offset) != sizetype)
+ aligned_offset = fold_convert_loc (loc, sizetype, aligned_offset);
+ return size_binop_loc (loc, MULT_EXPR, aligned_offset,
+ size_int (DECL_OFFSET_ALIGN (field)
+ / BITS_PER_UNIT));
+ }
+
+ /* Otherwise, take the offset from that of the field. Substitute
+ any PLACEHOLDER_EXPR that we have. */
+ else
+ return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
+}
+
+/* Return the machine mode of T. For vectors, returns the mode of the
+ inner type. The main use case is to feed the result to HONOR_NANS,
+ avoiding the BLKmode that a direct TYPE_MODE (T) might return. */
+
+machine_mode
+element_mode (const_tree t)
+{
+ if (!TYPE_P (t))
+ t = TREE_TYPE (t);
+ if (VECTOR_TYPE_P (t) || TREE_CODE (t) == COMPLEX_TYPE)
+ t = TREE_TYPE (t);
+ return TYPE_MODE (t);
+}
+
+
+/* Veirfy that basic properties of T match TV and thus T can be a variant of
+ TV. TV should be the more specified variant (i.e. the main variant). */
+
+static bool
+verify_type_variant (const_tree t, tree tv)
+{
+ /* Type variant can differ by:
+
+ - TYPE_QUALS: TYPE_READONLY, TYPE_VOLATILE, TYPE_ATOMIC, TYPE_RESTRICT,
+ ENCODE_QUAL_ADDR_SPACE.
+ - main variant may be TYPE_COMPLETE_P and variant types !TYPE_COMPLETE_P
+ in this case some values may not be set in the variant types
+ (see TYPE_COMPLETE_P checks).
+ - it is possible to have TYPE_ARTIFICIAL variant of non-artifical type
+ - by TYPE_NAME and attributes (i.e. when variant originate by typedef)
+ - TYPE_CANONICAL (TYPE_ALIAS_SET is the same among variants)
+ - by the alignment: TYPE_ALIGN and TYPE_USER_ALIGN
+ - during LTO by TYPE_CONTEXT if type is TYPE_FILE_SCOPE_P
+ this is necessary to make it possible to merge types form different TUs
+ - arrays, pointers and references may have TREE_TYPE that is a variant
+ of TREE_TYPE of their main variants.
+ - aggregates may have new TYPE_FIELDS list that list variants of
+ the main variant TYPE_FIELDS.
+ - vector types may differ by TYPE_VECTOR_OPAQUE
+ - TYPE_METHODS is always NULL for vairant types and maintained for
+ main variant only.
+ */
+
+ /* Convenience macro for matching individual fields. */
+#define verify_variant_match(flag) \
+ do { \
+ if (flag (tv) != flag (t)) \
+ { \
+ error ("type variant differs by " #flag "."); \
+ debug_tree (tv); \
+ return false; \
+ } \
+ } while (false)
+
+ /* tree_base checks. */
+
+ verify_variant_match (TREE_CODE);
+ /* FIXME: Ada builds non-artificial variants of artificial types. */
+ if (TYPE_ARTIFICIAL (tv) && 0)
+ verify_variant_match (TYPE_ARTIFICIAL);
+ if (POINTER_TYPE_P (tv))
+ verify_variant_match (TYPE_REF_CAN_ALIAS_ALL);
+ /* FIXME: TYPE_SIZES_GIMPLIFIED may differs for Ada build. */
+ verify_variant_match (TYPE_UNSIGNED);
+ verify_variant_match (TYPE_ALIGN_OK);
+ verify_variant_match (TYPE_PACKED);
+ if (TREE_CODE (t) == REFERENCE_TYPE)
+ verify_variant_match (TYPE_REF_IS_RVALUE);
+ verify_variant_match (TYPE_SATURATING);
+ /* FIXME: This check trigger during libstdc++ build. */
+ if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t) && 0)
+ verify_variant_match (TYPE_FINAL_P);
+
+ /* tree_type_common checks. */
+
+ if (COMPLETE_TYPE_P (t))
+ {
+ verify_variant_match (TYPE_SIZE);
+ verify_variant_match (TYPE_MODE);
+ if (TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv)
+ /* FIXME: ideally we should compare pointer equality, but java FE
+ produce variants where size is INTEGER_CST of different type (int
+ wrt size_type) during libjava biuld. */
+ && !operand_equal_p (TYPE_SIZE_UNIT (t), TYPE_SIZE_UNIT (tv), 0))
+ {
+ error ("type variant has different TYPE_SIZE_UNIT");
+ debug_tree (tv);
+ error ("type variant's TYPE_SIZE_UNIT");
+ debug_tree (TYPE_SIZE_UNIT (tv));
+ error ("type's TYPE_SIZE_UNIT");
+ debug_tree (TYPE_SIZE_UNIT (t));
+ return false;
+ }
+ }
+ verify_variant_match (TYPE_PRECISION);
+ verify_variant_match (TYPE_NEEDS_CONSTRUCTING);
+ if (RECORD_OR_UNION_TYPE_P (t))
+ verify_variant_match (TYPE_TRANSPARENT_AGGR);
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ verify_variant_match (TYPE_NONALIASED_COMPONENT);
+ /* During LTO we merge variant lists from diferent translation units
+ that may differ BY TYPE_CONTEXT that in turn may point
+ to TRANSLATION_UNIT_DECL.
+ Ada also builds variants of types with different TYPE_CONTEXT. */
+ if ((!in_lto_p || !TYPE_FILE_SCOPE_P (t)) && 0)
+ verify_variant_match (TYPE_CONTEXT);
+ verify_variant_match (TYPE_STRING_FLAG);
+ if (TYPE_ALIAS_SET_KNOWN_P (t) && TYPE_ALIAS_SET_KNOWN_P (tv))
+ verify_variant_match (TYPE_ALIAS_SET);
+
+ /* tree_type_non_common checks. */
+
+ /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
+ and dangle the pointer from time to time. */
+ if (RECORD_OR_UNION_TYPE_P (t) && TYPE_VFIELD (t) != TYPE_VFIELD (tv)
+ && (in_lto_p || !TYPE_VFIELD (tv)
+ || TREE_CODE (TYPE_VFIELD (tv)) != TREE_LIST))
+ {
+ error ("type variant has different TYPE_VFIELD");
+ debug_tree (tv);
+ return false;
+ }
+ if ((TREE_CODE (t) == ENUMERAL_TYPE && COMPLETE_TYPE_P (t))
+ || TREE_CODE (t) == INTEGER_TYPE
+ || TREE_CODE (t) == BOOLEAN_TYPE
+ || TREE_CODE (t) == REAL_TYPE
+ || TREE_CODE (t) == FIXED_POINT_TYPE)
+ {
+ verify_variant_match (TYPE_MAX_VALUE);
+ verify_variant_match (TYPE_MIN_VALUE);
+ }
+ if (TREE_CODE (t) == METHOD_TYPE)
+ verify_variant_match (TYPE_METHOD_BASETYPE);
+ if (RECORD_OR_UNION_TYPE_P (t) && TYPE_METHODS (t))
+ {
+ error ("type variant has TYPE_METHODS");
+ debug_tree (tv);
+ return false;
+ }
+ if (TREE_CODE (t) == OFFSET_TYPE)
+ verify_variant_match (TYPE_OFFSET_BASETYPE);
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ verify_variant_match (TYPE_ARRAY_MAX_SIZE);
+ /* FIXME: Be lax and allow TYPE_BINFO to be missing in variant types
+ or even type's main variant. This is needed to make bootstrap pass
+ and the bug seems new in GCC 5.
+ C++ FE should be updated to make this consistent and we should check
+ that TYPE_BINFO is always NULL for !COMPLETE_TYPE_P and otherwise there
+ is a match with main variant.
+
+ Also disable the check for Java for now because of parser hack that builds
+ first an dummy BINFO and then sometimes replace it by real BINFO in some
+ of the copies. */
+ if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t) && TYPE_BINFO (tv)
+ && TYPE_BINFO (t) != TYPE_BINFO (tv)
+ /* FIXME: Java sometimes keep dump TYPE_BINFOs on variant types.
+ Since there is no cheap way to tell C++/Java type w/o LTO, do checking
+ at LTO time only. */
+ && (in_lto_p && odr_type_p (t)))
+ {
+ error ("type variant has different TYPE_BINFO");
+ debug_tree (tv);
+ error ("type variant's TYPE_BINFO");
+ debug_tree (TYPE_BINFO (tv));
+ error ("type's TYPE_BINFO");
+ debug_tree (TYPE_BINFO (t));
+ return false;
+ }
+
+ /* Check various uses of TYPE_VALUES_RAW. */
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ verify_variant_match (TYPE_VALUES);
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ verify_variant_match (TYPE_DOMAIN);
+ /* Permit incomplete variants of complete type. While FEs may complete
+ all variants, this does not happen for C++ templates in all cases. */
+ else if (RECORD_OR_UNION_TYPE_P (t)
+ && COMPLETE_TYPE_P (t)
+ && TYPE_FIELDS (t) != TYPE_FIELDS (tv))
+ {
+ tree f1, f2;
+
+ /* Fortran builds qualified variants as new records with items of
+ qualified type. Verify that they looks same. */
+ for (f1 = TYPE_FIELDS (t), f2 = TYPE_FIELDS (tv);
+ f1 && f2;
+ f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+ if (TREE_CODE (f1) != FIELD_DECL || TREE_CODE (f2) != FIELD_DECL
+ || (TYPE_MAIN_VARIANT (TREE_TYPE (f1))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (f2))
+ /* FIXME: gfc_nonrestricted_type builds all types as variants
+ with exception of pointer types. It deeply copies the type
+ which means that we may end up with a variant type
+ referring non-variant pointer. We may change it to
+ produce types as variants, too, like
+ objc_get_protocol_qualified_type does. */
+ && !POINTER_TYPE_P (TREE_TYPE (f1)))
+ || DECL_FIELD_OFFSET (f1) != DECL_FIELD_OFFSET (f2)
+ || DECL_FIELD_BIT_OFFSET (f1) != DECL_FIELD_BIT_OFFSET (f2))
+ break;
+ if (f1 || f2)
+ {
+ error ("type variant has different TYPE_FIELDS");
+ debug_tree (tv);
+ error ("first mismatch is field");
+ debug_tree (f1);
+ error ("and field");
+ debug_tree (f2);
+ return false;
+ }
+ }
+ else if ((TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE))
+ verify_variant_match (TYPE_ARG_TYPES);
+ /* For C++ the qualified variant of array type is really an array type
+ of qualified TREE_TYPE.
+ objc builds variants of pointer where pointer to type is a variant, too
+ in objc_get_protocol_qualified_type. */
+ if (TREE_TYPE (t) != TREE_TYPE (tv)
+ && ((TREE_CODE (t) != ARRAY_TYPE
+ && !POINTER_TYPE_P (t))
+ || TYPE_MAIN_VARIANT (TREE_TYPE (t))
+ != TYPE_MAIN_VARIANT (TREE_TYPE (tv))))
+ {
+ error ("type variant has different TREE_TYPE");
+ debug_tree (tv);
+ error ("type variant's TREE_TYPE");
+ debug_tree (TREE_TYPE (tv));
+ error ("type's TREE_TYPE");
+ debug_tree (TREE_TYPE (t));
+ return false;
+ }
+ if (type_with_alias_set_p (t)
+ && !gimple_canonical_types_compatible_p (t, tv, false))
+ {
+ error ("type is not compatible with its vairant");
+ debug_tree (tv);
+ error ("type variant's TREE_TYPE");
+ debug_tree (TREE_TYPE (tv));
+ error ("type's TREE_TYPE");
+ debug_tree (TREE_TYPE (t));
+ return false;
+ }
+ return true;
+#undef verify_variant_match
+}
+
+
+/* The TYPE_CANONICAL merging machinery. It should closely resemble
+ the middle-end types_compatible_p function. It needs to avoid
+ claiming types are different for types that should be treated
+ the same with respect to TBAA. Canonical types are also used
+ for IL consistency checks via the useless_type_conversion_p
+ predicate which does not handle all type kinds itself but falls
+ back to pointer-comparison of TYPE_CANONICAL for aggregates
+ for example. */
+
+/* Return true iff T1 and T2 are structurally identical for what
+ TBAA is concerned.
+ This function is used both by lto.c canonical type merging and by the
+ verifier. If TRUST_TYPE_CANONICAL we do not look into structure of types
+ that have TYPE_CANONICAL defined and assume them equivalent. */
+
+bool
+gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
+ bool trust_type_canonical)
+{
+ /* Type variants should be same as the main variant. When not doing sanity
+ checking to verify this fact, go to main variants and save some work. */
+ if (trust_type_canonical)
+ {
+ t1 = TYPE_MAIN_VARIANT (t1);
+ t2 = TYPE_MAIN_VARIANT (t2);
+ }
+
+ /* Check first for the obvious case of pointer identity. */
+ if (t1 == t2)
+ return true;
+
+ /* Check that we have two types to compare. */
+ if (t1 == NULL_TREE || t2 == NULL_TREE)
+ return false;
+
+ /* We consider complete types always compatible with incomplete type.
+ This does not make sense for canonical type calculation and thus we
+ need to ensure that we are never called on it.
+
+ FIXME: For more correctness the function probably should have three modes
+ 1) mode assuming that types are complete mathcing their structure
+ 2) mode allowing incomplete types but producing equivalence classes
+ and thus ignoring all info from complete types
+ 3) mode allowing incomplete types to match complete but checking
+ compatibility between complete types.
+
+ 1 and 2 can be used for canonical type calculation. 3 is the real
+ definition of type compatibility that can be used i.e. for warnings during
+ declaration merging. */
+
+ gcc_assert (!trust_type_canonical
+ || (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
+ /* If the types have been previously registered and found equal
+ they still are. */
+ if (TYPE_CANONICAL (t1) && TYPE_CANONICAL (t2)
+ && trust_type_canonical)
+ return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
+
+ /* Can't be the same type if the types don't have the same code. */
+ if (tree_code_for_canonical_type_merging (TREE_CODE (t1))
+ != tree_code_for_canonical_type_merging (TREE_CODE (t2)))
+ return false;
+
+ /* Qualifiers do not matter for canonical type comparison purposes. */
+
+ /* Void types and nullptr types are always the same. */
+ if (TREE_CODE (t1) == VOID_TYPE
+ || TREE_CODE (t1) == NULLPTR_TYPE)
+ return true;
+
+ /* Can't be the same type if they have different mode. */
+ if (TYPE_MODE (t1) != TYPE_MODE (t2))
+ return false;
+
+ /* Non-aggregate types can be handled cheaply. */
+ if (INTEGRAL_TYPE_P (t1)
+ || SCALAR_FLOAT_TYPE_P (t1)
+ || FIXED_POINT_TYPE_P (t1)
+ || TREE_CODE (t1) == VECTOR_TYPE
+ || TREE_CODE (t1) == COMPLEX_TYPE
+ || TREE_CODE (t1) == OFFSET_TYPE
+ || POINTER_TYPE_P (t1))
+ {
+ /* Can't be the same type if they have different sign or precision. */
+ if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
+ || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
+ return false;
+
+ /* Fortran's C_SIGNED_CHAR is !TYPE_STRING_FLAG but needs to be
+ interoperable with "signed char". Unless all frontends are revisited
+ to agree on these types, we must ignore the flag completely. */
+
+ /* Fortran standard define C_PTR type that is compatible with every
+ C pointer. For this reason we need to glob all pointers into one.
+ Still pointers in different address spaces are not compatible. */
+ if (POINTER_TYPE_P (t1))
+ {
+ if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
+ != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
+ return false;
+ }
+
+ /* Tail-recurse to components. */
+ if (TREE_CODE (t1) == VECTOR_TYPE
+ || TREE_CODE (t1) == COMPLEX_TYPE)
+ return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
+ TREE_TYPE (t2),
+ trust_type_canonical);
+
+ return true;
+ }
+
+ /* Do type-specific comparisons. */
+ switch (TREE_CODE (t1))
+ {
+ case ARRAY_TYPE:
+ /* Array types are the same if the element types are the same and
+ the number of elements are the same. */
+ if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
+ trust_type_canonical)
+ || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+ || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
+ return false;
+ else
+ {
+ tree i1 = TYPE_DOMAIN (t1);
+ tree i2 = TYPE_DOMAIN (t2);
+
+ /* For an incomplete external array, the type domain can be
+ NULL_TREE. Check this condition also. */
+ if (i1 == NULL_TREE && i2 == NULL_TREE)
+ return true;
+ else if (i1 == NULL_TREE || i2 == NULL_TREE)
+ return false;
+ else
+ {
+ tree min1 = TYPE_MIN_VALUE (i1);
+ tree min2 = TYPE_MIN_VALUE (i2);
+ tree max1 = TYPE_MAX_VALUE (i1);
+ tree max2 = TYPE_MAX_VALUE (i2);
+
+ /* The minimum/maximum values have to be the same. */
+ if ((min1 == min2
+ || (min1 && min2
+ && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
+ && TREE_CODE (min2) == PLACEHOLDER_EXPR)
+ || operand_equal_p (min1, min2, 0))))
+ && (max1 == max2
+ || (max1 && max2
+ && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
+ && TREE_CODE (max2) == PLACEHOLDER_EXPR)
+ || operand_equal_p (max1, max2, 0)))))
+ return true;
+ else
+ return false;
+ }
+ }
+
+ case METHOD_TYPE:
+ case FUNCTION_TYPE:
+ /* Function types are the same if the return type and arguments types
+ are the same. */
+ if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2),
+ trust_type_canonical))
+ return false;
+
+ if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
+ return true;
+ else
+ {
+ tree parms1, parms2;
+
+ for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
+ parms1 && parms2;
+ parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
+ {
+ if (!gimple_canonical_types_compatible_p
+ (TREE_VALUE (parms1), TREE_VALUE (parms2),
+ trust_type_canonical))
+ return false;
+ }
+
+ if (parms1 || parms2)
+ return false;
+
+ return true;
+ }
+
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ {
+ tree f1, f2;
+
+ /* For aggregate types, all the fields must be the same. */
+ for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
+ f1 || f2;
+ f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+ {
+ /* Skip non-fields. */
+ while (f1 && TREE_CODE (f1) != FIELD_DECL)
+ f1 = TREE_CHAIN (f1);
+ while (f2 && TREE_CODE (f2) != FIELD_DECL)
+ f2 = TREE_CHAIN (f2);
+ if (!f1 || !f2)
+ break;
+ /* The fields must have the same name, offset and type. */
+ if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+ || !gimple_compare_field_offset (f1, f2)
+ || !gimple_canonical_types_compatible_p
+ (TREE_TYPE (f1), TREE_TYPE (f2),
+ trust_type_canonical))
+ return false;
+ }
+
+ /* If one aggregate has more fields than the other, they
+ are not the same. */
+ if (f1 || f2)
+ return false;
+
+ return true;
+ }
+
+ default:
+ /* Consider all types with language specific trees in them mutually
+ compatible. This is executed only from verify_type and false
+ positives can be tolerated. */
+ gcc_assert (!in_lto_p);
+ return true;
+ }
+}
+
+/* Verify type T. */
+
+void
+verify_type (const_tree t)
+{
+ bool error_found = false;
+ tree mv = TYPE_MAIN_VARIANT (t);
+ if (!mv)
+ {
+ error ("Main variant is not defined");
+ error_found = true;
+ }
+ else if (mv != TYPE_MAIN_VARIANT (mv))
+ {
+ error ("TYPE_MAIN_VARIANT has different TYPE_MAIN_VARIANT");
+ debug_tree (mv);
+ error_found = true;
+ }
+ else if (t != mv && !verify_type_variant (t, mv))
+ error_found = true;
+
+ tree ct = TYPE_CANONICAL (t);
+ if (!ct)
+ ;
+ else if (TYPE_CANONICAL (t) != ct)
+ {
+ error ("TYPE_CANONICAL has different TYPE_CANONICAL");
+ debug_tree (ct);
+ error_found = true;
+ }
+ /* Method and function types can not be used to address memory and thus
+ TYPE_CANONICAL really matters only for determining useless conversions.
+
+ FIXME: C++ FE produce declarations of builtin functions that are not
+ compatible with main variants. */
+ else if (TREE_CODE (t) == FUNCTION_TYPE)
+ ;
+ else if (t != ct
+ /* FIXME: gimple_canonical_types_compatible_p can not compare types
+ with variably sized arrays because their sizes possibly
+ gimplified to different variables. */
+ && !variably_modified_type_p (ct, NULL)
+ && !gimple_canonical_types_compatible_p (t, ct, false))
+ {
+ error ("TYPE_CANONICAL is not compatible");
+ debug_tree (ct);
+ error_found = true;
+ }
+
+
+ /* Check various uses of TYPE_MINVAL. */
+ if (RECORD_OR_UNION_TYPE_P (t))
+ {
+ /* FIXME: C FE uses TYPE_VFIELD to record C_TYPE_INCOMPLETE_VARS
+ and danagle the pointer from time to time. */
+ if (TYPE_VFIELD (t)
+ && TREE_CODE (TYPE_VFIELD (t)) != FIELD_DECL
+ && TREE_CODE (TYPE_VFIELD (t)) != TREE_LIST)
+ {
+ error ("TYPE_VFIELD is not FIELD_DECL nor TREE_LIST");
+ debug_tree (TYPE_VFIELD (t));
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == POINTER_TYPE)
+ {
+ if (TYPE_NEXT_PTR_TO (t)
+ && TREE_CODE (TYPE_NEXT_PTR_TO (t)) != POINTER_TYPE)
+ {
+ error ("TYPE_NEXT_PTR_TO is not POINTER_TYPE");
+ debug_tree (TYPE_NEXT_PTR_TO (t));
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == REFERENCE_TYPE)
+ {
+ if (TYPE_NEXT_REF_TO (t)
+ && TREE_CODE (TYPE_NEXT_REF_TO (t)) != REFERENCE_TYPE)
+ {
+ error ("TYPE_NEXT_REF_TO is not REFERENCE_TYPE");
+ debug_tree (TYPE_NEXT_REF_TO (t));
+ error_found = true;
+ }
+ }
+ else if (INTEGRAL_TYPE_P (t) || TREE_CODE (t) == REAL_TYPE
+ || TREE_CODE (t) == FIXED_POINT_TYPE)
+ {
+ /* FIXME: The following check should pass:
+ useless_type_conversion_p (const_cast <tree> (t),
+ TREE_TYPE (TYPE_MIN_VALUE (t))
+ but does not for C sizetypes in LTO. */
+ }
+ /* Java uses TYPE_MINVAL for TYPE_ARGUMENT_SIGNATURE. */
+ else if (TYPE_MINVAL (t)
+ && ((TREE_CODE (t) != METHOD_TYPE && TREE_CODE (t) != FUNCTION_TYPE)
+ || in_lto_p))
+ {
+ error ("TYPE_MINVAL non-NULL");
+ debug_tree (TYPE_MINVAL (t));
+ error_found = true;
+ }
+
+ /* Check various uses of TYPE_MAXVAL. */
+ if (RECORD_OR_UNION_TYPE_P (t))
+ {
+ if (TYPE_METHODS (t) && TREE_CODE (TYPE_METHODS (t)) != FUNCTION_DECL
+ && TREE_CODE (TYPE_METHODS (t)) != TEMPLATE_DECL
+ && TYPE_METHODS (t) != error_mark_node)
+ {
+ error ("TYPE_METHODS is not FUNCTION_DECL, TEMPLATE_DECL nor error_mark_node");
+ debug_tree (TYPE_METHODS (t));
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
+ {
+ if (TYPE_METHOD_BASETYPE (t)
+ && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != RECORD_TYPE
+ && TREE_CODE (TYPE_METHOD_BASETYPE (t)) != UNION_TYPE)
+ {
+ error ("TYPE_METHOD_BASETYPE is not record nor union");
+ debug_tree (TYPE_METHOD_BASETYPE (t));
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == OFFSET_TYPE)
+ {
+ if (TYPE_OFFSET_BASETYPE (t)
+ && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != RECORD_TYPE
+ && TREE_CODE (TYPE_OFFSET_BASETYPE (t)) != UNION_TYPE)
+ {
+ error ("TYPE_OFFSET_BASETYPE is not record nor union");
+ debug_tree (TYPE_OFFSET_BASETYPE (t));
+ error_found = true;
+ }
+ }
+ else if (INTEGRAL_TYPE_P (t) || TREE_CODE (t) == REAL_TYPE
+ || TREE_CODE (t) == FIXED_POINT_TYPE)
+ {
+ /* FIXME: The following check should pass:
+ useless_type_conversion_p (const_cast <tree> (t),
+ TREE_TYPE (TYPE_MAX_VALUE (t))
+ but does not for C sizetypes in LTO. */
+ }
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ {
+ if (TYPE_ARRAY_MAX_SIZE (t)
+ && TREE_CODE (TYPE_ARRAY_MAX_SIZE (t)) != INTEGER_CST)
+ {
+ error ("TYPE_ARRAY_MAX_SIZE not INTEGER_CST");
+ debug_tree (TYPE_ARRAY_MAX_SIZE (t));
+ error_found = true;
+ }
+ }
+ else if (TYPE_MAXVAL (t))
+ {
+ error ("TYPE_MAXVAL non-NULL");
+ debug_tree (TYPE_MAXVAL (t));
+ error_found = true;
+ }
+
+ /* Check various uses of TYPE_BINFO. */
+ if (RECORD_OR_UNION_TYPE_P (t))
+ {
+ if (!TYPE_BINFO (t))
+ ;
+ else if (TREE_CODE (TYPE_BINFO (t)) != TREE_BINFO)
+ {
+ error ("TYPE_BINFO is not TREE_BINFO");
+ debug_tree (TYPE_BINFO (t));
+ error_found = true;
+ }
+ /* FIXME: Java builds invalid empty binfos that do not have
+ TREE_TYPE set. */
+ else if (TREE_TYPE (TYPE_BINFO (t)) != TYPE_MAIN_VARIANT (t) && 0)
+ {
+ error ("TYPE_BINFO type is not TYPE_MAIN_VARIANT");
+ debug_tree (TREE_TYPE (TYPE_BINFO (t)));
+ error_found = true;
+ }
+ }
+ else if (TYPE_LANG_SLOT_1 (t) && in_lto_p)
+ {
+ error ("TYPE_LANG_SLOT_1 (binfo) field is non-NULL");
+ debug_tree (TYPE_LANG_SLOT_1 (t));
+ error_found = true;
+ }
+
+ /* Check various uses of TYPE_VALUES_RAW. */
+ if (TREE_CODE (t) == ENUMERAL_TYPE)
+ for (tree l = TYPE_VALUES (t); l; l = TREE_CHAIN (l))
+ {
+ tree value = TREE_VALUE (l);
+ tree name = TREE_PURPOSE (l);
+
+ /* C FE porduce INTEGER_CST of INTEGER_TYPE, while C++ FE uses
+ CONST_DECL of ENUMERAL TYPE. */
+ if (TREE_CODE (value) != INTEGER_CST && TREE_CODE (value) != CONST_DECL)
+ {
+ error ("Enum value is not CONST_DECL or INTEGER_CST");
+ debug_tree (value);
+ debug_tree (name);
+ error_found = true;
+ }
+ if (TREE_CODE (TREE_TYPE (value)) != INTEGER_TYPE
+ && !useless_type_conversion_p (const_cast <tree> (t), TREE_TYPE (value)))
+ {
+ error ("Enum value type is not INTEGER_TYPE nor convertible to the enum");
+ debug_tree (value);
+ debug_tree (name);
+ error_found = true;
+ }
+ if (TREE_CODE (name) != IDENTIFIER_NODE)
+ {
+ error ("Enum value name is not IDENTIFIER_NODE");
+ debug_tree (value);
+ debug_tree (name);
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == ARRAY_TYPE)
+ {
+ if (TYPE_DOMAIN (t) && TREE_CODE (TYPE_DOMAIN (t)) != INTEGER_TYPE)
+ {
+ error ("Array TYPE_DOMAIN is not integer type");
+ debug_tree (TYPE_DOMAIN (t));
+ error_found = true;
+ }
+ }
+ else if (RECORD_OR_UNION_TYPE_P (t))
+ for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
+ {
+ /* TODO: verify properties of decls. */
+ if (TREE_CODE (fld) == FIELD_DECL)
+ ;
+ else if (TREE_CODE (fld) == TYPE_DECL)
+ ;
+ else if (TREE_CODE (fld) == CONST_DECL)
+ ;
+ else if (TREE_CODE (fld) == VAR_DECL)
+ ;
+ else if (TREE_CODE (fld) == TEMPLATE_DECL)
+ ;
+ else if (TREE_CODE (fld) == USING_DECL)
+ ;
+ else
+ {
+ error ("Wrong tree in TYPE_FIELDS list");
+ debug_tree (fld);
+ error_found = true;
+ }
+ }
+ else if (TREE_CODE (t) == INTEGER_TYPE
+ || TREE_CODE (t) == BOOLEAN_TYPE
+ || TREE_CODE (t) == OFFSET_TYPE
+ || TREE_CODE (t) == REFERENCE_TYPE
+ || TREE_CODE (t) == NULLPTR_TYPE
+ || TREE_CODE (t) == POINTER_TYPE)
+ {
+ if (TYPE_CACHED_VALUES_P (t) != (TYPE_CACHED_VALUES (t) != NULL))
+ {
+ error ("TYPE_CACHED_VALUES_P is %i while TYPE_CACHED_VALUES is %p",
+ TYPE_CACHED_VALUES_P (t), (void *)TYPE_CACHED_VALUES (t));
+ error_found = true;
+ }
+ else if (TYPE_CACHED_VALUES_P (t) && TREE_CODE (TYPE_CACHED_VALUES (t)) != TREE_VEC)
+ {
+ error ("TYPE_CACHED_VALUES is not TREE_VEC");
+ debug_tree (TYPE_CACHED_VALUES (t));
+ error_found = true;
+ }
+ /* Verify just enough of cache to ensure that no one copied it to new type.
+ All copying should go by copy_node that should clear it. */
+ else if (TYPE_CACHED_VALUES_P (t))
+ {
+ int i;
+ for (i = 0; i < TREE_VEC_LENGTH (TYPE_CACHED_VALUES (t)); i++)
+ if (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)
+ && TREE_TYPE (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i)) != t)
+ {
+ error ("wrong TYPE_CACHED_VALUES entry");
+ debug_tree (TREE_VEC_ELT (TYPE_CACHED_VALUES (t), i));
+ error_found = true;
+ break;
+ }
+ }
+ }
+ else if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE)
+ for (tree l = TYPE_ARG_TYPES (t); l; l = TREE_CHAIN (l))
+ {
+ /* C++ FE uses TREE_PURPOSE to store initial values. */
+ if (TREE_PURPOSE (l) && in_lto_p)
+ {
+ error ("TREE_PURPOSE is non-NULL in TYPE_ARG_TYPES list");
+ debug_tree (l);
+ error_found = true;
+ }
+ if (!TYPE_P (TREE_VALUE (l)))
+ {
+ error ("Wrong entry in TYPE_ARG_TYPES list");
+ debug_tree (l);
+ error_found = true;
+ }
+ }
+ else if (!is_lang_specific (t) && TYPE_VALUES_RAW (t))
+ {
+ error ("TYPE_VALUES_RAW field is non-NULL");
+ debug_tree (TYPE_VALUES_RAW (t));
+ error_found = true;
+ }
+ if (TREE_CODE (t) != INTEGER_TYPE
+ && TREE_CODE (t) != BOOLEAN_TYPE
+ && TREE_CODE (t) != OFFSET_TYPE
+ && TREE_CODE (t) != REFERENCE_TYPE
+ && TREE_CODE (t) != NULLPTR_TYPE
+ && TREE_CODE (t) != POINTER_TYPE
+ && TYPE_CACHED_VALUES_P (t))
+ {
+ error ("TYPE_CACHED_VALUES_P is set while it should not");
+ error_found = true;
+ }
+ if (TYPE_STRING_FLAG (t)
+ && TREE_CODE (t) != ARRAY_TYPE && TREE_CODE (t) != INTEGER_TYPE)
+ {
+ error ("TYPE_STRING_FLAG is set on wrong type code");
+ error_found = true;
+ }
+ else if (TYPE_STRING_FLAG (t))
+ {
+ const_tree b = t;
+ if (TREE_CODE (b) == ARRAY_TYPE)
+ b = TREE_TYPE (t);
+ /* Java builds arrays with TYPE_STRING_FLAG of promoted_char_type
+ that is 32bits. */
+ if (TREE_CODE (b) != INTEGER_TYPE)
+ {
+ error ("TYPE_STRING_FLAG is set on type that does not look like "
+ "char nor array of chars");
+ error_found = true;
+ }
+ }
+
+ /* ipa-devirt makes an assumption that TYPE_METHOD_BASETYPE is always
+ TYPE_MAIN_VARIANT and it would be odd to add methods only to variatns
+ of a type. */
+ if (TREE_CODE (t) == METHOD_TYPE
+ && TYPE_MAIN_VARIANT (TYPE_METHOD_BASETYPE (t)) != TYPE_METHOD_BASETYPE (t))
+ {
+ error ("TYPE_METHOD_BASETYPE is not main variant");
+ error_found = true;
+ }
+
+ if (error_found)
+ {
+ debug_tree (const_cast <tree> (t));
+ internal_error ("verify_type failed");
+ }
+}
+
#include "gt-tree.h"