aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree.c')
-rw-r--r--gcc/tree.c1807
1 files changed, 393 insertions, 1414 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index 7c44c22..3d15948 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "gimple-fold.h"
#include "escaped_string.h"
+#include "gimple-range.h"
/* Tree code classes. */
@@ -266,8 +267,6 @@ static void print_type_hash_statistics (void);
static void print_debug_expr_statistics (void);
static void print_value_expr_statistics (void);
-static tree build_array_type_1 (tree, tree, bool, bool, bool);
-
tree global_trees[TI_MAX];
tree integer_types[itk_none];
@@ -276,7 +275,7 @@ struct int_n_trees_t int_n_trees [NUM_INT_N_ENTS];
bool tree_contains_struct[MAX_TREE_CODES][64];
-/* Number of operands for each OpenMP clause. */
+/* Number of operands for each OMP clause. */
unsigned const char omp_clause_num_ops[] =
{
0, /* OMP_CLAUSE_ERROR */
@@ -290,6 +289,7 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_COPYIN */
1, /* OMP_CLAUSE_COPYPRIVATE */
3, /* OMP_CLAUSE_LINEAR */
+ 1, /* OMP_CLAUSE_AFFINITY */
2, /* OMP_CLAUSE_ALIGNED */
2, /* OMP_CLAUSE_ALLOCATE */
1, /* OMP_CLAUSE_DEPEND */
@@ -350,6 +350,7 @@ unsigned const char omp_clause_num_ops[] =
0, /* OMP_CLAUSE_DEFAULTMAP */
0, /* OMP_CLAUSE_ORDER */
0, /* OMP_CLAUSE_BIND */
+ 1, /* OMP_CLAUSE_FILTER */
1, /* OMP_CLAUSE__SIMDUID_ */
0, /* OMP_CLAUSE__SIMT_ */
0, /* OMP_CLAUSE_INDEPENDENT */
@@ -361,6 +362,7 @@ unsigned const char omp_clause_num_ops[] =
3, /* OMP_CLAUSE_TILE */
0, /* OMP_CLAUSE_IF_PRESENT */
0, /* OMP_CLAUSE_FINALIZE */
+ 0, /* OMP_CLAUSE_NOHOST */
};
const char * const omp_clause_code_name[] =
@@ -376,6 +378,7 @@ const char * const omp_clause_code_name[] =
"copyin",
"copyprivate",
"linear",
+ "affinity",
"aligned",
"allocate",
"depend",
@@ -436,6 +439,7 @@ const char * const omp_clause_code_name[] =
"defaultmap",
"order",
"bind",
+ "filter",
"_simduid_",
"_simt_",
"independent",
@@ -447,6 +451,7 @@ const char * const omp_clause_code_name[] =
"tile",
"if_present",
"finalize",
+ "nohost",
};
@@ -722,6 +727,112 @@ overwrite_decl_assembler_name (tree decl, tree name)
lang_hooks.overwrite_decl_assembler_name (decl, name);
}
+/* Return true if DECL may need an assembler name to be set. */
+
+static inline bool
+need_assembler_name_p (tree decl)
+{
+ /* 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 (TREE_CODE (decl) == TYPE_DECL)
+ {
+ if (DECL_NAME (decl)
+ && decl == TYPE_NAME (TREE_TYPE (decl))
+ && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
+ && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
+ && ((TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
+ && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
+ || TYPE_CXX_ODR_P (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);
+ return false;
+ }
+ /* Only FUNCTION_DECLs and VAR_DECLs are considered. */
+ if (!VAR_OR_FUNCTION_DECL_P (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_P (decl))
+ return false;
+
+ /* For VAR_DECLs, only static, public and external symbols need an
+ assembler name. */
+ if (VAR_P (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 (fndecl_built_in_p (decl)
+ && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
+ return false;
+
+ /* Functions represented in the callgraph need an assembler name. */
+ if (cgraph_node::get (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;
+}
+
+/* If T needs an assembler name, have one created for it. */
+
+void
+assign_assembler_name_if_needed (tree t)
+{
+ if (need_assembler_name_p (t))
+ {
+ /* 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.
+
+ 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);
+
+ decl_assembler_name (t);
+
+ input_location = saved_location;
+ }
+}
+
/* When the target supports COMDAT groups, this indicates which group the
DECL is associated with. This can be either an IDENTIFIER_NODE or a
decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */
@@ -1940,7 +2051,7 @@ make_vector (unsigned log2_npatterns,
are extracted from V, a vector of CONSTRUCTOR_ELT. */
tree
-build_vector_from_ctor (tree type, vec<constructor_elt, va_gc> *v)
+build_vector_from_ctor (tree type, const vec<constructor_elt, va_gc> *v)
{
if (vec_safe_length (v) == 0)
return build_zero_cst (type);
@@ -5245,1252 +5356,6 @@ protected_set_expr_location_if_unset (tree t, location_t loc)
if (t && !EXPR_HAS_LOCATION (t))
protected_set_expr_location (t, loc);
}
-
-/* Data used when collecting DECLs and TYPEs for language data removal. */
-
-class free_lang_data_d
-{
-public:
- free_lang_data_d () : decls (100), types (100) {}
-
- /* Worklist to avoid excessive recursion. */
- auto_vec<tree> worklist;
-
- /* Set of traversed objects. Used to avoid duplicate visits. */
- hash_set<tree> pset;
-
- /* Array of symbols to process with free_lang_data_in_decl. */
- auto_vec<tree> decls;
-
- /* Array of types to process with free_lang_data_in_type. */
- auto_vec<tree> types;
-};
-
-
-/* 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, class free_lang_data_d *fld)
-{
- if (DECL_P (t))
- fld->decls.safe_push (t);
- else if (TYPE_P (t))
- fld->types.safe_push (t);
- else
- gcc_unreachable ();
-}
-
-/* Push tree node T into FLD->WORKLIST. */
-
-static inline void
-fld_worklist_push (tree t, class free_lang_data_d *fld)
-{
- if (t && !is_lang_specific (t) && !fld->pset.contains (t))
- fld->worklist.safe_push ((t));
-}
-
-
-
-/* Return simplified TYPE_NAME of TYPE. */
-
-static tree
-fld_simplified_type_name (tree type)
-{
- if (!TYPE_NAME (type) || TREE_CODE (TYPE_NAME (type)) != TYPE_DECL)
- return TYPE_NAME (type);
- /* Drop TYPE_DECLs in TYPE_NAME in favor of the identifier in the
- TYPE_DECL if the type doesn't have linkage.
- this must match fld_ */
- if (type != TYPE_MAIN_VARIANT (type)
- || (!DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type))
- && (TREE_CODE (type) != RECORD_TYPE
- || !TYPE_BINFO (type)
- || !BINFO_VTABLE (TYPE_BINFO (type)))))
- return DECL_NAME (TYPE_NAME (type));
- return TYPE_NAME (type);
-}
-
-/* Do same comparsion as check_qualified_type skipping lang part of type
- and be more permissive about type names: we only care that names are
- same (for diagnostics) and that ODR names are the same.
- If INNER_TYPE is non-NULL, be sure that TREE_TYPE match it. */
-
-static bool
-fld_type_variant_equal_p (tree t, tree v, tree inner_type)
-{
- if (TYPE_QUALS (t) != TYPE_QUALS (v)
- /* We want to match incomplete variants with complete types.
- In this case we need to ignore alignment. */
- || ((!RECORD_OR_UNION_TYPE_P (t) || COMPLETE_TYPE_P (v))
- && (TYPE_ALIGN (t) != TYPE_ALIGN (v)
- || TYPE_USER_ALIGN (t) != TYPE_USER_ALIGN (v)))
- || fld_simplified_type_name (t) != fld_simplified_type_name (v)
- || !attribute_list_equal (TYPE_ATTRIBUTES (t),
- TYPE_ATTRIBUTES (v))
- || (inner_type && TREE_TYPE (v) != inner_type))
- return false;
-
- return true;
-}
-
-/* Find variant of FIRST that match T and create new one if necessary.
- Set TREE_TYPE to INNER_TYPE if non-NULL. */
-
-static tree
-fld_type_variant (tree first, tree t, class free_lang_data_d *fld,
- tree inner_type = NULL)
-{
- if (first == TYPE_MAIN_VARIANT (t))
- return t;
- for (tree v = first; v; v = TYPE_NEXT_VARIANT (v))
- if (fld_type_variant_equal_p (t, v, inner_type))
- return v;
- tree v = build_variant_type_copy (first);
- TYPE_READONLY (v) = TYPE_READONLY (t);
- TYPE_VOLATILE (v) = TYPE_VOLATILE (t);
- TYPE_ATOMIC (v) = TYPE_ATOMIC (t);
- TYPE_RESTRICT (v) = TYPE_RESTRICT (t);
- TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t);
- TYPE_NAME (v) = TYPE_NAME (t);
- TYPE_ATTRIBUTES (v) = TYPE_ATTRIBUTES (t);
- TYPE_CANONICAL (v) = TYPE_CANONICAL (t);
- /* Variants of incomplete types should have alignment
- set to BITS_PER_UNIT. Do not copy the actual alignment. */
- if (!RECORD_OR_UNION_TYPE_P (v) || COMPLETE_TYPE_P (v))
- {
- SET_TYPE_ALIGN (v, TYPE_ALIGN (t));
- TYPE_USER_ALIGN (v) = TYPE_USER_ALIGN (t);
- }
- if (inner_type)
- TREE_TYPE (v) = inner_type;
- gcc_checking_assert (fld_type_variant_equal_p (t,v, inner_type));
- if (!fld->pset.add (v))
- add_tree_to_fld_list (v, fld);
- return v;
-}
-
-/* Map complete types to incomplete types. */
-
-static hash_map<tree, tree> *fld_incomplete_types;
-
-/* Map types to simplified types. */
-
-static hash_map<tree, tree> *fld_simplified_types;
-
-/* Produce variant of T whose TREE_TYPE is T2. If it is main variant,
- use MAP to prevent duplicates. */
-
-static tree
-fld_process_array_type (tree t, tree t2, hash_map<tree, tree> *map,
- class free_lang_data_d *fld)
-{
- if (TREE_TYPE (t) == t2)
- return t;
-
- if (TYPE_MAIN_VARIANT (t) != t)
- {
- return fld_type_variant
- (fld_process_array_type (TYPE_MAIN_VARIANT (t),
- TYPE_MAIN_VARIANT (t2), map, fld),
- t, fld, t2);
- }
-
- bool existed;
- tree &array
- = map->get_or_insert (t, &existed);
- if (!existed)
- {
- array
- = build_array_type_1 (t2, TYPE_DOMAIN (t), TYPE_TYPELESS_STORAGE (t),
- false, false);
- TYPE_CANONICAL (array) = TYPE_CANONICAL (t);
- if (!fld->pset.add (array))
- add_tree_to_fld_list (array, fld);
- }
- return array;
-}
-
-/* Return CTX after removal of contexts that are not relevant */
-
-static tree
-fld_decl_context (tree ctx)
-{
- /* Variably modified types are needed for tree_is_indexable to decide
- whether the type needs to go to local or global section.
- This code is semi-broken but for now it is easiest to keep contexts
- as expected. */
- if (ctx && TYPE_P (ctx)
- && !variably_modified_type_p (ctx, NULL_TREE))
- {
- while (ctx && TYPE_P (ctx))
- ctx = TYPE_CONTEXT (ctx);
- }
- return ctx;
-}
-
-/* For T being aggregate type try to turn it into a incomplete variant.
- Return T if no simplification is possible. */
-
-static tree
-fld_incomplete_type_of (tree t, class free_lang_data_d *fld)
-{
- if (!t)
- return NULL;
- if (POINTER_TYPE_P (t))
- {
- tree t2 = fld_incomplete_type_of (TREE_TYPE (t), fld);
- if (t2 != TREE_TYPE (t))
- {
- tree first;
- if (TREE_CODE (t) == POINTER_TYPE)
- first = build_pointer_type_for_mode (t2, TYPE_MODE (t),
- TYPE_REF_CAN_ALIAS_ALL (t));
- else
- first = build_reference_type_for_mode (t2, TYPE_MODE (t),
- TYPE_REF_CAN_ALIAS_ALL (t));
- gcc_assert (TYPE_CANONICAL (t2) != t2
- && TYPE_CANONICAL (t2) == TYPE_CANONICAL (TREE_TYPE (t)));
- if (!fld->pset.add (first))
- add_tree_to_fld_list (first, fld);
- return fld_type_variant (first, t, fld);
- }
- return t;
- }
- if (TREE_CODE (t) == ARRAY_TYPE)
- return fld_process_array_type (t,
- fld_incomplete_type_of (TREE_TYPE (t), fld),
- fld_incomplete_types, fld);
- if ((!RECORD_OR_UNION_TYPE_P (t) && TREE_CODE (t) != ENUMERAL_TYPE)
- || !COMPLETE_TYPE_P (t))
- return t;
- if (TYPE_MAIN_VARIANT (t) == t)
- {
- bool existed;
- tree &copy
- = fld_incomplete_types->get_or_insert (t, &existed);
-
- if (!existed)
- {
- copy = build_distinct_type_copy (t);
-
- /* It is possible that type was not seen by free_lang_data yet. */
- if (!fld->pset.add (copy))
- add_tree_to_fld_list (copy, fld);
- TYPE_SIZE (copy) = NULL;
- TYPE_USER_ALIGN (copy) = 0;
- TYPE_SIZE_UNIT (copy) = NULL;
- TYPE_CANONICAL (copy) = TYPE_CANONICAL (t);
- TREE_ADDRESSABLE (copy) = 0;
- if (AGGREGATE_TYPE_P (t))
- {
- SET_TYPE_MODE (copy, VOIDmode);
- SET_TYPE_ALIGN (copy, BITS_PER_UNIT);
- TYPE_TYPELESS_STORAGE (copy) = 0;
- TYPE_FIELDS (copy) = NULL;
- TYPE_BINFO (copy) = NULL;
- TYPE_FINAL_P (copy) = 0;
- TYPE_EMPTY_P (copy) = 0;
- }
- else
- {
- TYPE_VALUES (copy) = NULL;
- ENUM_IS_OPAQUE (copy) = 0;
- ENUM_IS_SCOPED (copy) = 0;
- }
-
- /* Build copy of TYPE_DECL in TYPE_NAME if necessary.
- This is needed for ODR violation warnings to come out right (we
- want duplicate TYPE_DECLs whenever the type is duplicated because
- of ODR violation. Because lang data in the TYPE_DECL may not
- have been freed yet, rebuild it from scratch and copy relevant
- fields. */
- TYPE_NAME (copy) = fld_simplified_type_name (copy);
- tree name = TYPE_NAME (copy);
-
- if (name && TREE_CODE (name) == TYPE_DECL)
- {
- gcc_checking_assert (TREE_TYPE (name) == t);
- tree name2 = build_decl (DECL_SOURCE_LOCATION (name), TYPE_DECL,
- DECL_NAME (name), copy);
- if (DECL_ASSEMBLER_NAME_SET_P (name))
- SET_DECL_ASSEMBLER_NAME (name2, DECL_ASSEMBLER_NAME (name));
- SET_DECL_ALIGN (name2, 0);
- DECL_CONTEXT (name2) = fld_decl_context
- (DECL_CONTEXT (name));
- TYPE_NAME (copy) = name2;
- }
- }
- return copy;
- }
- return (fld_type_variant
- (fld_incomplete_type_of (TYPE_MAIN_VARIANT (t), fld), t, fld));
-}
-
-/* Simplify type T for scenarios where we do not need complete pointer
- types. */
-
-static tree
-fld_simplified_type (tree t, class free_lang_data_d *fld)
-{
- if (!t)
- return t;
- if (POINTER_TYPE_P (t))
- return fld_incomplete_type_of (t, fld);
- /* FIXME: This triggers verification error, see PR88140. */
- if (TREE_CODE (t) == ARRAY_TYPE && 0)
- return fld_process_array_type (t, fld_simplified_type (TREE_TYPE (t), fld),
- fld_simplified_types, fld);
- return t;
-}
-
-/* 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_VTABLE, 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_VIRTUALS (binfo) = NULL_TREE;
- BINFO_BASE_ACCESSES (binfo) = NULL;
- BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE;
- BINFO_SUBVTT_INDEX (binfo) = NULL_TREE;
- BINFO_VPTR_FIELD (binfo) = NULL_TREE;
- TREE_PUBLIC (binfo) = 0;
-
- FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (binfo), i, t)
- free_lang_data_in_binfo (t);
-}
-
-
-/* Reset all language specific information still present in TYPE. */
-
-static void
-free_lang_data_in_type (tree type, class free_lang_data_d *fld)
-{
- 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;
-
- TYPE_NEEDS_CONSTRUCTING (type) = 0;
-
- /* Purge non-marked variants from the variants chain, so that they
- don't reappear in the IL after free_lang_data. */
- while (TYPE_NEXT_VARIANT (type)
- && !fld->pset.contains (TYPE_NEXT_VARIANT (type)))
- {
- tree t = TYPE_NEXT_VARIANT (type);
- TYPE_NEXT_VARIANT (type) = TYPE_NEXT_VARIANT (t);
- /* Turn the removed types into distinct types. */
- TYPE_MAIN_VARIANT (t) = t;
- TYPE_NEXT_VARIANT (t) = NULL_TREE;
- }
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld);
- /* 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. */
- for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
- {
- TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld);
- 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);
- if (!fld->pset.add (TREE_VALUE (p)))
- free_lang_data_in_type (TREE_VALUE (p), fld);
- }
- /* C++ FE uses TREE_PURPOSE to store initial values. */
- TREE_PURPOSE (p) = NULL;
- }
- }
- else if (TREE_CODE (type) == METHOD_TYPE)
- {
- TREE_TYPE (type) = fld_simplified_type (TREE_TYPE (type), fld);
- for (tree p = TYPE_ARG_TYPES (type); p; p = TREE_CHAIN (p))
- {
- /* C++ FE uses TREE_PURPOSE to store initial values. */
- TREE_VALUE (p) = fld_simplified_type (TREE_VALUE (p), fld);
- TREE_PURPOSE (p) = NULL;
- }
- }
- else if (RECORD_OR_UNION_TYPE_P (type))
- {
- /* Remove members that are not FIELD_DECLs from the field list
- of an aggregate. These occur in C++. */
- for (tree *prev = &TYPE_FIELDS (type), member; (member = *prev);)
- if (TREE_CODE (member) == FIELD_DECL)
- prev = &DECL_CHAIN (member);
- else
- *prev = DECL_CHAIN (member);
-
- TYPE_VFIELD (type) = NULL_TREE;
-
- if (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. */
- if (!BINFO_VTABLE (TYPE_BINFO (type)))
- TYPE_BINFO (type) = NULL;
- }
- }
- else if (INTEGRAL_TYPE_P (type)
- || SCALAR_FLOAT_TYPE_P (type)
- || FIXED_POINT_TYPE_P (type))
- {
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- {
- ENUM_IS_OPAQUE (type) = 0;
- ENUM_IS_SCOPED (type) = 0;
- /* Type values are used only for C++ ODR checking. Drop them
- for all type variants and non-ODR types.
- For ODR types the data is freed in free_odr_warning_data. */
- if (!TYPE_VALUES (type))
- ;
- else if (TYPE_MAIN_VARIANT (type) != type
- || !type_with_linkage_p (type)
- || type_in_anonymous_namespace_p (type))
- TYPE_VALUES (type) = NULL;
- else
- register_odr_enum (type);
- }
- free_lang_data_in_one_sizepos (&TYPE_MIN_VALUE (type));
- free_lang_data_in_one_sizepos (&TYPE_MAX_VALUE (type));
- }
-
- TYPE_LANG_SLOT_1 (type) = NULL_TREE;
-
- free_lang_data_in_one_sizepos (&TYPE_SIZE (type));
- free_lang_data_in_one_sizepos (&TYPE_SIZE_UNIT (type));
-
- if (TYPE_CONTEXT (type)
- && TREE_CODE (TYPE_CONTEXT (type)) == BLOCK)
- {
- tree ctx = TYPE_CONTEXT (type);
- do
- {
- ctx = BLOCK_SUPERCONTEXT (ctx);
- }
- while (ctx && TREE_CODE (ctx) == BLOCK);
- TYPE_CONTEXT (type) = ctx;
- }
-
- TYPE_STUB_DECL (type) = NULL;
- TYPE_NAME (type) = fld_simplified_type_name (type);
-}
-
-
-/* Return true if DECL may need an assembler name to be set. */
-
-static inline bool
-need_assembler_name_p (tree decl)
-{
- /* 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 (TREE_CODE (decl) == TYPE_DECL)
- {
- if (DECL_NAME (decl)
- && decl == TYPE_NAME (TREE_TYPE (decl))
- && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TREE_TYPE (decl)
- && !TYPE_ARTIFICIAL (TREE_TYPE (decl))
- && ((TREE_CODE (TREE_TYPE (decl)) != RECORD_TYPE
- && TREE_CODE (TREE_TYPE (decl)) != UNION_TYPE)
- || TYPE_CXX_ODR_P (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);
- return false;
- }
- /* Only FUNCTION_DECLs and VAR_DECLs are considered. */
- if (!VAR_OR_FUNCTION_DECL_P (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_P (decl))
- return false;
-
- /* For VAR_DECLs, only static, public and external symbols need an
- assembler name. */
- if (VAR_P (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 (fndecl_built_in_p (decl)
- && DECL_BUILT_IN_CLASS (decl) != BUILT_IN_FRONTEND)
- return false;
-
- /* Functions represented in the callgraph need an assembler name. */
- if (cgraph_node::get (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;
-}
-
-
-/* Reset all language specific information still present in symbol
- DECL. */
-
-static void
-free_lang_data_in_decl (tree decl, class free_lang_data_d *fld)
-{
- 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;
-
- 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)
- {
- DECL_FCONTEXT (decl) = NULL;
- free_lang_data_in_one_sizepos (&DECL_FIELD_OFFSET (decl));
- if (TREE_CODE (DECL_CONTEXT (decl)) == QUAL_UNION_TYPE)
- DECL_QUALIFIER (decl) = NULL_TREE;
- }
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- struct cgraph_node *node;
- /* Frontends do not set TREE_ADDRESSABLE on public variables even though
- the address may be taken in other unit, so this flag has no practical
- use for middle-end.
-
- It would make more sense if frontends set TREE_ADDRESSABLE to 0 only
- for public objects that indeed cannot be adressed, but it is not
- the case. Set the flag to true so we do not get merge failures for
- i.e. virtual tables between units that take address of it and
- units that don't. */
- if (TREE_PUBLIC (decl))
- TREE_ADDRESSABLE (decl) = true;
- TREE_TYPE (decl) = fld_simplified_type (TREE_TYPE (decl), fld);
- if (!(node = cgraph_node::get (decl))
- || (!node->definition && !node->clones))
- {
- if (node)
- node->release_body ();
- else
- {
- release_function_body (decl);
- DECL_ARGUMENTS (decl) = NULL;
- DECL_RESULT (decl) = NULL;
- DECL_INITIAL (decl) = error_mark_node;
- }
- }
- if (gimple_has_body_p (decl) || (node && node->thunk))
- {
- tree t;
-
- /* 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;
- 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.
- At this point, it is not needed anymore. */
- DECL_SAVED_TREE (decl) = NULL_TREE;
-
- /* Clear the abstract origin if it refers to a method.
- Otherwise dwarf2out.c will ICE as we splice functions out of
- TYPE_FIELDS and thus the origin will not be output
- correctly. */
- if (DECL_ABSTRACT_ORIGIN (decl)
- && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
- && RECORD_OR_UNION_TYPE_P
- (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
- DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
-
- DECL_VINDEX (decl) = NULL_TREE;
- }
- else if (VAR_P (decl))
- {
- /* See comment above why we set the flag for functions. */
- if (TREE_PUBLIC (decl))
- TREE_ADDRESSABLE (decl) = true;
- if ((DECL_EXTERNAL (decl)
- && (!TREE_STATIC (decl) || !TREE_READONLY (decl)))
- || (decl_function_context (decl) && !TREE_STATIC (decl)))
- DECL_INITIAL (decl) = NULL_TREE;
- }
- else if (TREE_CODE (decl) == TYPE_DECL)
- {
- DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
- DECL_VISIBILITY_SPECIFIED (decl) = 0;
- TREE_PUBLIC (decl) = 0;
- TREE_PRIVATE (decl) = 0;
- DECL_ARTIFICIAL (decl) = 0;
- TYPE_DECL_SUPPRESS_DEBUG (decl) = 0;
- DECL_INITIAL (decl) = NULL_TREE;
- DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
- DECL_MODE (decl) = VOIDmode;
- SET_DECL_ALIGN (decl, 0);
- /* TREE_TYPE is cleared at WPA time in free_odr_warning_data. */
- }
- else if (TREE_CODE (decl) == FIELD_DECL)
- {
- TREE_TYPE (decl) = fld_simplified_type (TREE_TYPE (decl), fld);
- DECL_INITIAL (decl) = NULL_TREE;
- }
- else if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
- && DECL_INITIAL (decl)
- && TREE_CODE (DECL_INITIAL (decl)) == BLOCK)
- {
- /* Strip builtins from the translation-unit BLOCK. We still have targets
- without builtin_decl_explicit support and also builtins are shared
- nodes and thus we can't use TREE_CHAIN in multiple lists. */
- tree *nextp = &BLOCK_VARS (DECL_INITIAL (decl));
- while (*nextp)
- {
- tree var = *nextp;
- if (TREE_CODE (var) == FUNCTION_DECL
- && fndecl_built_in_p (var))
- *nextp = TREE_CHAIN (var);
- else
- nextp = &TREE_CHAIN (var);
- }
- }
- /* We need to keep field decls associated with their trees. Otherwise tree
- merging may merge some fileds and keep others disjoint wich in turn will
- not do well with TREE_CHAIN pointers linking them.
-
- Also do not drop containing types for virtual methods and tables because
- these are needed by devirtualization.
- C++ destructors are special because C++ frontends sometimes produces
- virtual destructor as an alias of non-virtual destructor. In
- devirutalization code we always walk through aliases and we need
- context to be preserved too. See PR89335 */
- if (TREE_CODE (decl) != FIELD_DECL
- && ((TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
- || (!DECL_VIRTUAL_P (decl)
- && (TREE_CODE (decl) != FUNCTION_DECL
- || !DECL_CXX_DESTRUCTOR_P (decl)))))
- DECL_CONTEXT (decl) = fld_decl_context (DECL_CONTEXT (decl));
-}
-
-
-/* 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;
- class free_lang_data_d *fld = (class 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) == FIELD_DECL)
- {
- fld_worklist_push (DECL_FIELD_OFFSET (t), fld);
- fld_worklist_push (DECL_BIT_FIELD_TYPE (t), fld);
- fld_worklist_push (DECL_FIELD_BIT_OFFSET (t), fld);
- fld_worklist_push (DECL_FCONTEXT (t), fld);
- }
-
- if ((VAR_P (t) || 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
- && TREE_CODE (t) != TYPE_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);
- /* While we do not stream TYPE_POINTER_TO and TYPE_REFERENCE_TO
- lists, we may look types up in these lists and use them while
- optimizing the function body. Thus we need to free lang data
- in them. */
- if (TREE_CODE (t) == POINTER_TYPE)
- fld_worklist_push (TYPE_NEXT_PTR_TO (t), fld);
- if (TREE_CODE (t) == REFERENCE_TYPE)
- fld_worklist_push (TYPE_NEXT_REF_TO (t), fld);
- if (!POINTER_TYPE_P (t))
- fld_worklist_push (TYPE_MIN_VALUE_RAW (t), fld);
- /* TYPE_MAX_VALUE_RAW is TYPE_BINFO for record types. */
- if (!RECORD_OR_UNION_TYPE_P (t))
- fld_worklist_push (TYPE_MAX_VALUE_RAW (t), fld);
- fld_worklist_push (TYPE_MAIN_VARIANT (t), fld);
- /* Do not walk TYPE_NEXT_VARIANT. We do not stream it and thus
- do not and want not to reach unused variants this way. */
- if (TYPE_CONTEXT (t))
- {
- tree ctx = TYPE_CONTEXT (t);
- /* We adjust BLOCK TYPE_CONTEXTs to the innermost non-BLOCK one.
- So push that instead. */
- while (ctx && TREE_CODE (ctx) == BLOCK)
- ctx = BLOCK_SUPERCONTEXT (ctx);
- fld_worklist_push (ctx, fld);
- }
- fld_worklist_push (TYPE_CANONICAL (t), fld);
-
- if (RECORD_OR_UNION_TYPE_P (t) && TYPE_BINFO (t))
- {
- unsigned i;
- tree tem;
- FOR_EACH_VEC_ELT (*BINFO_BASE_BINFOS (TYPE_BINFO (t)), i, tem)
- fld_worklist_push (TREE_TYPE (tem), fld);
- fld_worklist_push (BINFO_TYPE (TYPE_BINFO (t)), fld);
- fld_worklist_push (BINFO_VTABLE (TYPE_BINFO (t)), fld);
- }
- 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);
- }
- }
- if (FUNC_OR_METHOD_TYPE_P (t))
- fld_worklist_push (TYPE_METHOD_BASETYPE (t), fld);
-
- fld_worklist_push (TYPE_STUB_DECL (t), fld);
- *ws = 0;
- }
- else if (TREE_CODE (t) == BLOCK)
- {
- for (tree *tem = &BLOCK_VARS (t); *tem; )
- {
- if (TREE_CODE (*tem) != LABEL_DECL
- && (TREE_CODE (*tem) != VAR_DECL
- || !auto_var_in_fn_p (*tem, DECL_CONTEXT (*tem))))
- {
- gcc_assert (TREE_CODE (*tem) != RESULT_DECL
- && TREE_CODE (*tem) != PARM_DECL);
- *tem = TREE_CHAIN (*tem);
- }
- else
- {
- fld_worklist_push (*tem, fld);
- tem = &TREE_CHAIN (*tem);
- }
- }
- for (tree tem = BLOCK_SUBBLOCKS (t); tem; tem = BLOCK_CHAIN (tem))
- fld_worklist_push (tem, fld);
- fld_worklist_push (BLOCK_ABSTRACT_ORIGIN (t), fld);
- }
-
- if (TREE_CODE (t) != IDENTIFIER_NODE
- && CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_TYPED))
- fld_worklist_push (TREE_TYPE (t), fld);
-
- return NULL_TREE;
-}
-
-
-/* Find decls and types in T. */
-
-static void
-find_decls_types (tree t, class free_lang_data_d *fld)
-{
- while (1)
- {
- if (!fld->pset.contains (t))
- walk_tree (&t, find_decls_types_r, fld, &fld->pset);
- if (fld->worklist.is_empty ())
- break;
- t = fld->worklist.pop ();
- }
-}
-
-/* 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, class 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, class free_lang_data_d *fld)
-{
- basic_block bb;
- struct function *fn;
- unsigned ix;
- 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_EACH_LOCAL_DECL (fn, ix, t)
- find_decls_types (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)
- {
- gphi_iterator psi;
- gimple_stmt_iterator si;
- unsigned i;
-
- for (psi = gsi_start_phis (bb); !gsi_end_p (psi); gsi_next (&psi))
- {
- gphi *phi = psi.phi ();
-
- 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);
-
- if (is_gimple_call (stmt))
- find_decls_types (gimple_call_fntype (stmt), fld);
-
- for (i = 0; i < gimple_num_ops (stmt); i++)
- {
- tree arg = gimple_op (stmt, i);
- find_decls_types (arg, fld);
- /* find_decls_types doesn't walk TREE_PURPOSE of TREE_LISTs,
- which we need for asm stmts. */
- if (arg
- && TREE_CODE (arg) == TREE_LIST
- && TREE_PURPOSE (arg)
- && gimple_code (stmt) == GIMPLE_ASM)
- find_decls_types (TREE_PURPOSE (arg), fld);
- }
- }
- }
-}
-
-
-/* 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 void
-find_decls_types_in_var (varpool_node *v, class free_lang_data_d *fld)
-{
- find_decls_types (v->decl, fld);
-}
-
-/* If T needs an assembler name, have one created for it. */
-
-void
-assign_assembler_name_if_needed (tree t)
-{
- if (need_assembler_name_p (t))
- {
- /* 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.
-
- 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);
-
- decl_assembler_name (t);
-
- input_location = saved_location;
- }
-}
-
-
-/* Free language specific information for every operand and expression
- in every node of the call graph. This process operates in three stages:
-
- 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.
-
- 2- All the decls found are sent to free_lang_data_in_decl.
-
- 3- All the types found are sent to free_lang_data_in_type.
-
- 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 (class free_lang_data_d *fld)
-{
- struct cgraph_node *n;
- varpool_node *v;
- tree t;
- unsigned i;
- alias_pair *p;
-
- /* Find decls and types in the body of every function in the callgraph. */
- FOR_EACH_FUNCTION (n)
- find_decls_types_in_node (n, fld);
-
- FOR_EACH_VEC_SAFE_ELT (alias_pairs, i, p)
- find_decls_types (p->decl, fld);
-
- /* Find decls and types in every varpool symbol. */
- FOR_EACH_VARIABLE (v)
- 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_EACH_VEC_ELT (fld->decls, i, t)
- assign_assembler_name_if_needed (t);
-
- /* Traverse every decl found freeing its language data. */
- FOR_EACH_VEC_ELT (fld->decls, i, t)
- free_lang_data_in_decl (t, fld);
-
- /* Traverse every type found freeing its language data. */
- FOR_EACH_VEC_ELT (fld->types, i, t)
- free_lang_data_in_type (t, fld);
-}
-
-
-/* Free resources that are used by FE but are not needed once they are done. */
-
-static unsigned
-free_lang_data (void)
-{
- unsigned i;
- class free_lang_data_d fld;
-
- /* If we are the LTO frontend we have freed lang-specific data already. */
- if (in_lto_p
- || (!flag_generate_lto && !flag_generate_offload))
- {
- /* Rebuild type inheritance graph even when not doing LTO to get
- consistent profile data. */
- rebuild_type_inheritance_graph ();
- return 0;
- }
-
- fld_incomplete_types = new hash_map<tree, tree>;
- fld_simplified_types = new hash_map<tree, tree>;
-
- /* Provide a dummy TRANSLATION_UNIT_DECL if the FE failed to provide one. */
- if (vec_safe_is_empty (all_translation_units))
- build_translation_unit_decl (NULL_TREE);
-
- /* 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 (&fld);
-
- /* Create gimple variants for common types. */
- for (unsigned i = 0;
- i < sizeof (builtin_structptr_types) / sizeof (builtin_structptr_type);
- ++i)
- builtin_structptr_types[i].node = builtin_structptr_types[i].base;
-
- /* Reset some langhooks. Do not reset types_compatible_p, it may
- 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;
- lang_hooks.overwrite_decl_assembler_name = lhd_overwrite_decl_assembler_name;
- lang_hooks.print_xnode = lhd_print_tree_nothing;
- lang_hooks.print_decl = lhd_print_tree_nothing;
- lang_hooks.print_type = lhd_print_tree_nothing;
- lang_hooks.print_identifier = lhd_print_tree_nothing;
-
- lang_hooks.tree_inlining.var_mod_type_p = hook_bool_tree_tree_false;
-
- if (flag_checking)
- {
- int i;
- tree t;
-
- FOR_EACH_VEC_ELT (fld.types, i, t)
- verify_type (t);
- }
-
- /* 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
- name and only produce assembler names for local symbols. Or rather
- make sure we never call decl_assembler_name on local symbols and
- devise a separate, middle-end private scheme for it. */
-
- /* Reset diagnostic machinery. */
- tree_diagnostics_defaults (global_dc);
-
- rebuild_type_inheritance_graph ();
-
- delete fld_incomplete_types;
- delete fld_simplified_types;
-
- return 0;
-}
-
-
-namespace {
-
-const pass_data pass_data_ipa_free_lang_data =
-{
- SIMPLE_IPA_PASS, /* type */
- "*free_lang_data", /* name */
- OPTGROUP_NONE, /* optinfo_flags */
- TV_IPA_FREE_LANG_DATA, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0, /* todo_flags_finish */
-};
-
-class pass_ipa_free_lang_data : public simple_ipa_opt_pass
-{
-public:
- pass_ipa_free_lang_data (gcc::context *ctxt)
- : simple_ipa_opt_pass (pass_data_ipa_free_lang_data, ctxt)
- {}
-
- /* opt_pass methods: */
- virtual unsigned int execute (function *) { return free_lang_data (); }
-
-}; // class pass_ipa_free_lang_data
-
-} // anon namespace
-
-simple_ipa_opt_pass *
-make_pass_ipa_free_lang_data (gcc::context *ctxt)
-{
- return new pass_ipa_free_lang_data (ctxt);
-}
/* Set the type qualifiers for TYPE to TYPE_QUALS, which is a bitmask
of the various TYPE_QUAL values. */
@@ -7934,9 +6799,10 @@ operation_no_trapping_overflow (tree type, enum tree_code code)
constructed by language-dependent code, not here.) */
/* Construct, lay out and return the type of pointers to TO_TYPE with
- mode MODE. If CAN_ALIAS_ALL is TRUE, indicate this type can
- reference all of memory. If such a type has already been
- constructed, reuse it. */
+ mode MODE. If MODE is VOIDmode, a pointer mode for the address
+ space of TO_TYPE will be picked. If CAN_ALIAS_ALL is TRUE,
+ indicate this type can reference all of memory. If such a type has
+ already been constructed, reuse it. */
tree
build_pointer_type_for_mode (tree to_type, machine_mode mode,
@@ -7948,6 +6814,12 @@ build_pointer_type_for_mode (tree to_type, machine_mode mode,
if (to_type == error_mark_node)
return error_mark_node;
+ if (mode == VOIDmode)
+ {
+ addr_space_t as = TYPE_ADDR_SPACE (to_type);
+ mode = targetm.addr_space.pointer_mode (as);
+ }
+
/* If the pointed-to type has the may_alias attribute set, force
a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */
if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
@@ -7999,10 +6871,7 @@ build_pointer_type_for_mode (tree to_type, machine_mode mode,
tree
build_pointer_type (tree to_type)
{
- addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
- : TYPE_ADDR_SPACE (to_type);
- machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
- return build_pointer_type_for_mode (to_type, pointer_mode, false);
+ return build_pointer_type_for_mode (to_type, VOIDmode, false);
}
/* Same as build_pointer_type_for_mode, but for REFERENCE_TYPE. */
@@ -8017,6 +6886,12 @@ build_reference_type_for_mode (tree to_type, machine_mode mode,
if (to_type == error_mark_node)
return error_mark_node;
+ if (mode == VOIDmode)
+ {
+ addr_space_t as = TYPE_ADDR_SPACE (to_type);
+ mode = targetm.addr_space.pointer_mode (as);
+ }
+
/* If the pointed-to type has the may_alias attribute set, force
a TYPE_REF_CAN_ALIAS_ALL pointer to be generated. */
if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (to_type)))
@@ -8068,10 +6943,7 @@ build_reference_type_for_mode (tree to_type, machine_mode mode,
tree
build_reference_type (tree to_type)
{
- addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
- : TYPE_ADDR_SPACE (to_type);
- machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
- return build_reference_type_for_mode (to_type, pointer_mode, false);
+ return build_reference_type_for_mode (to_type, VOIDmode, false);
}
#define MAX_INT_CACHED_PREC \
@@ -8261,7 +7133,7 @@ subrange_type_for_debug_p (const_tree type, tree *lowval, tree *highval)
If SHARED is true, reuse such a type that has already been constructed.
If SET_CANONICAL is true, compute TYPE_CANONICAL from the element type. */
-static tree
+tree
build_array_type_1 (tree elt_type, tree index_type, bool typeless_storage,
bool shared, bool set_canonical)
{
@@ -8765,7 +7637,8 @@ excess_precision_type (tree type)
enum excess_precision_type requested_type
= (flag_excess_precision == EXCESS_PRECISION_FAST
? EXCESS_PRECISION_TYPE_FAST
- : EXCESS_PRECISION_TYPE_STANDARD);
+ : (flag_excess_precision == EXCESS_PRECISION_FLOAT16
+ ? EXCESS_PRECISION_TYPE_FLOAT16 :EXCESS_PRECISION_TYPE_STANDARD));
enum flt_eval_method target_flt_eval_method
= targetm.c.excess_precision (requested_type);
@@ -9725,7 +8598,7 @@ get_file_function_name (const char *type)
We also assign sub_I and sub_D sufixes to constructors called from
the global static constructors. These are always local. */
else if (((type[0] == 'I' || type[0] == 'D') && targetm.have_ctors_dtors)
- || (strncmp (type, "sub_", 4) == 0
+ || (startswith (type, "sub_")
&& (type[4] == 'I' || type[4] == 'D')))
{
const char *file = main_input_filename;
@@ -10638,6 +9511,19 @@ build_common_builtin_nodes (void)
tree tmp, ftype;
int ecf_flags;
+ if (!builtin_decl_explicit_p (BUILT_IN_CLEAR_PADDING))
+ {
+ ftype = build_function_type_list (void_type_node,
+ ptr_type_node,
+ ptr_type_node,
+ integer_type_node,
+ NULL_TREE);
+ local_define_builtin ("__builtin_clear_padding", ftype,
+ BUILT_IN_CLEAR_PADDING,
+ "__builtin_clear_padding",
+ ECF_LEAF | ECF_NOTHROW);
+ }
+
if (!builtin_decl_explicit_p (BUILT_IN_UNREACHABLE)
|| !builtin_decl_explicit_p (BUILT_IN_ABORT))
{
@@ -11417,7 +10303,7 @@ build_empty_stmt (location_t loc)
}
-/* Build an OpenMP clause with code CODE. LOC is the location of the
+/* Build an OMP clause with code CODE. LOC is the location of the
clause. */
tree
@@ -12219,127 +11105,12 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
break;
case OMP_CLAUSE:
- switch (OMP_CLAUSE_CODE (*tp))
- {
- case OMP_CLAUSE_GANG:
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 1));
- /* FALLTHRU */
-
- 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:
- case OMP_CLAUSE_COPYIN:
- case OMP_CLAUSE_COPYPRIVATE:
- case OMP_CLAUSE_FINAL:
- case OMP_CLAUSE_IF:
- case OMP_CLAUSE_NUM_THREADS:
- case OMP_CLAUSE_SCHEDULE:
- case OMP_CLAUSE_UNIFORM:
- case OMP_CLAUSE_DEPEND:
- case OMP_CLAUSE_NONTEMPORAL:
- case OMP_CLAUSE_NUM_TEAMS:
- case OMP_CLAUSE_THREAD_LIMIT:
- case OMP_CLAUSE_DEVICE:
- case OMP_CLAUSE_DIST_SCHEDULE:
- case OMP_CLAUSE_SAFELEN:
- case OMP_CLAUSE_SIMDLEN:
- case OMP_CLAUSE_ORDERED:
- case OMP_CLAUSE_PRIORITY:
- case OMP_CLAUSE_GRAINSIZE:
- case OMP_CLAUSE_NUM_TASKS:
- case OMP_CLAUSE_HINT:
- case OMP_CLAUSE_TO_DECLARE:
- case OMP_CLAUSE_LINK:
- case OMP_CLAUSE_DETACH:
- case OMP_CLAUSE_USE_DEVICE_PTR:
- case OMP_CLAUSE_USE_DEVICE_ADDR:
- case OMP_CLAUSE_IS_DEVICE_PTR:
- case OMP_CLAUSE_INCLUSIVE:
- case OMP_CLAUSE_EXCLUSIVE:
- case OMP_CLAUSE__LOOPTEMP_:
- case OMP_CLAUSE__REDUCTEMP_:
- case OMP_CLAUSE__CONDTEMP_:
- case OMP_CLAUSE__SCANTEMP_:
- case OMP_CLAUSE__SIMDUID_:
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, 0));
- /* FALLTHRU */
-
- case OMP_CLAUSE_INDEPENDENT:
- case OMP_CLAUSE_NOWAIT:
- case OMP_CLAUSE_DEFAULT:
- case OMP_CLAUSE_UNTIED:
- case OMP_CLAUSE_MERGEABLE:
- case OMP_CLAUSE_PROC_BIND:
- case OMP_CLAUSE_DEVICE_TYPE:
- case OMP_CLAUSE_INBRANCH:
- case OMP_CLAUSE_NOTINBRANCH:
- case OMP_CLAUSE_FOR:
- case OMP_CLAUSE_PARALLEL:
- case OMP_CLAUSE_SECTIONS:
- case OMP_CLAUSE_TASKGROUP:
- case OMP_CLAUSE_NOGROUP:
- case OMP_CLAUSE_THREADS:
- case OMP_CLAUSE_SIMD:
- case OMP_CLAUSE_DEFAULTMAP:
- case OMP_CLAUSE_ORDER:
- case OMP_CLAUSE_BIND:
- case OMP_CLAUSE_AUTO:
- case OMP_CLAUSE_SEQ:
- case OMP_CLAUSE_TILE:
- case OMP_CLAUSE__SIMT_:
- case OMP_CLAUSE_IF_PRESENT:
- case OMP_CLAUSE_FINALIZE:
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_LASTPRIVATE:
- WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LASTPRIVATE_STMT (*tp));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_COLLAPSE:
- {
- int i;
- for (i = 0; i < 3; i++)
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
- }
-
- case OMP_CLAUSE_LINEAR:
- WALK_SUBTREE (OMP_CLAUSE_DECL (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LINEAR_STEP (*tp));
- WALK_SUBTREE (OMP_CLAUSE_LINEAR_STMT (*tp));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
-
- case OMP_CLAUSE_ALIGNED:
- case OMP_CLAUSE_ALLOCATE:
- 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));
-
- case OMP_CLAUSE_REDUCTION:
- case OMP_CLAUSE_TASK_REDUCTION:
- case OMP_CLAUSE_IN_REDUCTION:
- {
- int i;
- for (i = 0; i < 5; i++)
- WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
- WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
- }
-
- default:
- gcc_unreachable ();
- }
+ {
+ int len = omp_clause_num_ops[OMP_CLAUSE_CODE (*tp)];
+ for (int i = 0; i < len; i++)
+ WALK_SUBTREE (OMP_CLAUSE_OPERAND (*tp, i));
+ WALK_SUBTREE_TAIL (OMP_CLAUSE_CHAIN (*tp));
+ }
break;
case TARGET_EXPR:
@@ -13279,6 +12050,78 @@ warn_deprecated_use (tree node, tree attr)
return w;
}
+/* Error out with an identifier which was marked 'unavailable'. */
+void
+error_unavailable_use (tree node, tree attr)
+{
+ escaped_string msg;
+
+ if (node == 0)
+ return;
+
+ if (!attr)
+ {
+ if (DECL_P (node))
+ attr = DECL_ATTRIBUTES (node);
+ else if (TYPE_P (node))
+ {
+ tree decl = TYPE_STUB_DECL (node);
+ if (decl)
+ attr = lookup_attribute ("unavailable",
+ TYPE_ATTRIBUTES (TREE_TYPE (decl)));
+ }
+ }
+
+ if (attr)
+ attr = lookup_attribute ("unavailable", attr);
+
+ if (attr)
+ msg.escape (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))));
+
+ if (DECL_P (node))
+ {
+ auto_diagnostic_group d;
+ if (msg)
+ error ("%qD is unavailable: %s", node, (const char *) msg);
+ else
+ error ("%qD is unavailable", node);
+ inform (DECL_SOURCE_LOCATION (node), "declared here");
+ }
+ else if (TYPE_P (node))
+ {
+ tree what = NULL_TREE;
+ tree decl = TYPE_STUB_DECL (node);
+
+ if (TYPE_NAME (node))
+ {
+ if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
+ what = TYPE_NAME (node);
+ else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
+ && DECL_NAME (TYPE_NAME (node)))
+ what = DECL_NAME (TYPE_NAME (node));
+ }
+
+ auto_diagnostic_group d;
+ if (what)
+ {
+ if (msg)
+ error ("%qE is unavailable: %s", what, (const char *) msg);
+ else
+ error ("%qE is unavailable", what);
+ }
+ else
+ {
+ if (msg)
+ error ("type is unavailable: %s", (const char *) msg);
+ else
+ error ("type is unavailable");
+ }
+
+ if (decl)
+ inform (DECL_SOURCE_LOCATION (decl), "declared here");
+ }
+}
+
/* Return true if REF has a COMPONENT_REF with a bit-field field declaration
somewhere in it. */
@@ -13451,7 +12294,7 @@ get_tree_code_name (enum tree_code code)
invalid values, so force an unsigned comparison. */
if (unsigned (code) >= MAX_TREE_CODES)
{
- if (code == 0xa5a5)
+ if ((unsigned)code == 0xa5a5)
return "ggc_freed";
return invalid;
}
@@ -13517,6 +12360,8 @@ drop_tree_overflow (tree t)
tree
get_base_address (tree t)
{
+ if (TREE_CODE (t) == WITH_SIZE_EXPR)
+ t = TREE_OPERAND (t, 0);
while (handled_component_p (t))
t = TREE_OPERAND (t, 0);
@@ -13525,11 +12370,6 @@ get_base_address (tree t)
&& TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
t = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
- /* ??? Either the alias oracle or all callers need to properly deal
- with WITH_SIZE_EXPRs before we can look through those. */
- if (TREE_CODE (t) == WITH_SIZE_EXPR)
- return NULL_TREE;
-
return t;
}
@@ -13692,13 +12532,11 @@ array_at_struct_end_p (tree ref)
|| ! TYPE_MAX_VALUE (TYPE_DOMAIN (atype)))
return true;
- if (TREE_CODE (ref) == MEM_REF
- && TREE_CODE (TREE_OPERAND (ref, 0)) == ADDR_EXPR)
- ref = TREE_OPERAND (TREE_OPERAND (ref, 0), 0);
-
/* If the reference is based on a declared entity, the size of the array
is constrained by its given domain. (Do not trust commons PR/69368). */
- if (DECL_P (ref)
+ ref = get_base_address (ref);
+ if (ref
+ && DECL_P (ref)
&& !(flag_unconstrained_commons
&& VAR_P (ref) && DECL_COMMON (ref))
&& DECL_SIZE_UNIT (ref)
@@ -14099,8 +12937,10 @@ verify_type_variant (const_tree t, tree tv)
verify_variant_match (TREE_CODE);
/* FIXME: Ada builds non-artificial variants of artificial types. */
- if (TYPE_ARTIFICIAL (tv) && 0)
+#if 0
+ if (TYPE_ARTIFICIAL (tv))
verify_variant_match (TYPE_ARTIFICIAL);
+#endif
if (POINTER_TYPE_P (tv))
verify_variant_match (TYPE_REF_CAN_ALIAS_ALL);
/* FIXME: TYPE_SIZES_GIMPLIFIED may differs for Ada build. */
@@ -14113,8 +12953,10 @@ verify_type_variant (const_tree t, tree tv)
else
verify_variant_match (TYPE_SATURATING);
/* FIXME: This check trigger during libstdc++ build. */
- if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t) && 0)
+#if 0
+ if (RECORD_OR_UNION_TYPE_P (t) && COMPLETE_TYPE_P (t))
verify_variant_match (TYPE_FINAL_P);
+#endif
/* tree_type_common checks. */
@@ -14149,8 +12991,10 @@ verify_type_variant (const_tree t, tree tv)
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)
+#if 0
+ if (!in_lto_p || !TYPE_FILE_SCOPE_P (t))
verify_variant_match (TYPE_CONTEXT);
+#endif
if (TREE_CODE (t) == ARRAY_TYPE || TREE_CODE (t) == INTEGER_TYPE)
verify_variant_match (TYPE_STRING_FLAG);
if (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE)
@@ -14965,8 +13809,8 @@ get_range_pos_neg (tree arg)
if (TREE_CODE (arg) != SSA_NAME)
return 3;
- wide_int arg_min, arg_max;
- while (get_range_info (arg, &arg_min, &arg_max) != VR_RANGE)
+ value_range r;
+ while (!get_global_range_query ()->range_of_expr (r, arg) || r.kind () != VR_RANGE)
{
gimple *g = SSA_NAME_DEF_STMT (arg);
if (is_gimple_assign (g)
@@ -14992,16 +13836,16 @@ get_range_pos_neg (tree arg)
{
/* For unsigned values, the "positive" range comes
below the "negative" range. */
- if (!wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+ if (!wi::neg_p (wi::sext (r.upper_bound (), prec), SIGNED))
return 1;
- if (wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+ if (wi::neg_p (wi::sext (r.lower_bound (), prec), SIGNED))
return 2;
}
else
{
- if (!wi::neg_p (wi::sext (arg_min, prec), SIGNED))
+ if (!wi::neg_p (wi::sext (r.lower_bound (), prec), SIGNED))
return 1;
- if (wi::neg_p (wi::sext (arg_max, prec), SIGNED))
+ if (wi::neg_p (wi::sext (r.upper_bound (), prec), SIGNED))
return 2;
}
return 3;
@@ -15438,17 +14282,28 @@ verify_type_context (location_t loc, type_context_kind context,
|| targetm.verify_type_context (loc, context, type, silent_p));
}
-/* Return that NEW_ASM and DELETE_ASM name a valid pair of new and
- delete operators. */
+/* Return true if NEW_ASM and DELETE_ASM name a valid pair of new and
+ delete operators. Return false if they may or may not name such
+ a pair and, when nonnull, set *PCERTAIN to true if they certainly
+ do not. */
bool
-valid_new_delete_pair_p (tree new_asm, tree delete_asm)
+valid_new_delete_pair_p (tree new_asm, tree delete_asm,
+ bool *pcertain /* = NULL */)
{
+ bool certain;
+ if (!pcertain)
+ pcertain = &certain;
+
const char *new_name = IDENTIFIER_POINTER (new_asm);
const char *delete_name = IDENTIFIER_POINTER (delete_asm);
unsigned int new_len = IDENTIFIER_LENGTH (new_asm);
unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm);
+ /* The following failures are due to invalid names so they're not
+ considered certain mismatches. */
+ *pcertain = false;
+
if (new_len < 5 || delete_len < 6)
return false;
if (new_name[0] == '_')
@@ -15461,11 +14316,19 @@ valid_new_delete_pair_p (tree new_asm, tree delete_asm)
++delete_name, --delete_len;
if (new_len < 4 || delete_len < 5)
return false;
+
+ /* The following failures are due to names of user-defined operators
+ so they're also not considered certain mismatches. */
+
/* *_len is now just the length after initial underscores. */
if (new_name[0] != 'Z' || new_name[1] != 'n')
return false;
if (delete_name[0] != 'Z' || delete_name[1] != 'd')
return false;
+
+ /* The following failures are certain mismatches. */
+ *pcertain = true;
+
/* _Znw must match _Zdl, _Zna must match _Zda. */
if ((new_name[2] != 'w' || delete_name[2] != 'l')
&& (new_name[2] != 'a' || delete_name[2] != 'a'))
@@ -15504,9 +14367,125 @@ valid_new_delete_pair_p (tree new_asm, tree delete_asm)
&& !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
return true;
}
+
+ /* The negative result is conservative. */
+ *pcertain = false;
return false;
}
+/* Return the zero-based number corresponding to the argument being
+ deallocated if FNDECL is a deallocation function or an out-of-bounds
+ value if it isn't. */
+
+unsigned
+fndecl_dealloc_argno (tree fndecl)
+{
+ /* A call to operator delete isn't recognized as one to a built-in. */
+ if (DECL_IS_OPERATOR_DELETE_P (fndecl))
+ {
+ if (DECL_IS_REPLACEABLE_OPERATOR (fndecl))
+ return 0;
+
+ /* Avoid placement delete that's not been inlined. */
+ tree fname = DECL_ASSEMBLER_NAME (fndecl);
+ if (id_equal (fname, "_ZdlPvS_") // ordinary form
+ || id_equal (fname, "_ZdaPvS_")) // array form
+ return UINT_MAX;
+ return 0;
+ }
+
+ /* TODO: Handle user-defined functions with attribute malloc? Handle
+ known non-built-ins like fopen? */
+ if (fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
+ {
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case BUILT_IN_FREE:
+ case BUILT_IN_REALLOC:
+ return 0;
+ default:
+ break;
+ }
+ return UINT_MAX;
+ }
+
+ tree attrs = DECL_ATTRIBUTES (fndecl);
+ if (!attrs)
+ return UINT_MAX;
+
+ for (tree atfree = attrs;
+ (atfree = lookup_attribute ("*dealloc", atfree));
+ atfree = TREE_CHAIN (atfree))
+ {
+ tree alloc = TREE_VALUE (atfree);
+ if (!alloc)
+ continue;
+
+ tree pos = TREE_CHAIN (alloc);
+ if (!pos)
+ return 0;
+
+ pos = TREE_VALUE (pos);
+ return TREE_INT_CST_LOW (pos) - 1;
+ }
+
+ return UINT_MAX;
+}
+
+/* If EXPR refers to a character array or pointer declared attribute
+ nonstring, return a decl for that array or pointer and set *REF
+ to the referenced enclosing object or pointer. Otherwise return
+ null. */
+
+tree
+get_attr_nonstring_decl (tree expr, tree *ref)
+{
+ tree decl = expr;
+ tree var = NULL_TREE;
+ if (TREE_CODE (decl) == SSA_NAME)
+ {
+ gimple *def = SSA_NAME_DEF_STMT (decl);
+
+ if (is_gimple_assign (def))
+ {
+ tree_code code = gimple_assign_rhs_code (def);
+ if (code == ADDR_EXPR
+ || code == COMPONENT_REF
+ || code == VAR_DECL)
+ decl = gimple_assign_rhs1 (def);
+ }
+ else
+ var = SSA_NAME_VAR (decl);
+ }
+
+ if (TREE_CODE (decl) == ADDR_EXPR)
+ decl = TREE_OPERAND (decl, 0);
+
+ /* To simplify calling code, store the referenced DECL regardless of
+ the attribute determined below, but avoid storing the SSA_NAME_VAR
+ obtained above (it's not useful for dataflow purposes). */
+ if (ref)
+ *ref = decl;
+
+ /* Use the SSA_NAME_VAR that was determined above to see if it's
+ declared nonstring. Otherwise drill down into the referenced
+ DECL. */
+ if (var)
+ decl = var;
+ else if (TREE_CODE (decl) == ARRAY_REF)
+ decl = TREE_OPERAND (decl, 0);
+ else if (TREE_CODE (decl) == COMPONENT_REF)
+ decl = TREE_OPERAND (decl, 1);
+ else if (TREE_CODE (decl) == MEM_REF)
+ return get_attr_nonstring_decl (TREE_OPERAND (decl, 0), ref);
+
+ if (DECL_P (decl)
+ && lookup_attribute ("nonstring", DECL_ATTRIBUTES (decl)))
+ return decl;
+
+ return NULL_TREE;
+}
+
#if CHECKING_P
namespace selftest {
@@ -15558,7 +14537,7 @@ test_labels ()
are given by VALS. */
static tree
-build_vector (tree type, vec<tree> vals MEM_STAT_DECL)
+build_vector (tree type, const vec<tree> &vals MEM_STAT_DECL)
{
gcc_assert (known_eq (vals.length (), TYPE_VECTOR_SUBPARTS (type)));
tree_vector_builder builder (type, vals.length (), 1);
@@ -15569,7 +14548,7 @@ build_vector (tree type, vec<tree> vals MEM_STAT_DECL)
/* Check that VECTOR_CST ACTUAL contains the elements in EXPECTED. */
static void
-check_vector_cst (vec<tree> expected, tree actual)
+check_vector_cst (const vec<tree> &expected, tree actual)
{
ASSERT_KNOWN_EQ (expected.length (),
TYPE_VECTOR_SUBPARTS (TREE_TYPE (actual)));
@@ -15582,7 +14561,7 @@ check_vector_cst (vec<tree> expected, tree actual)
and that its elements match EXPECTED. */
static void
-check_vector_cst_duplicate (vec<tree> expected, tree actual,
+check_vector_cst_duplicate (const vec<tree> &expected, tree actual,
unsigned int npatterns)
{
ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
@@ -15598,7 +14577,7 @@ check_vector_cst_duplicate (vec<tree> expected, tree actual,
EXPECTED. */
static void
-check_vector_cst_fill (vec<tree> expected, tree actual,
+check_vector_cst_fill (const vec<tree> &expected, tree actual,
unsigned int npatterns)
{
ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));
@@ -15613,7 +14592,7 @@ check_vector_cst_fill (vec<tree> expected, tree actual,
and that its elements match EXPECTED. */
static void
-check_vector_cst_stepped (vec<tree> expected, tree actual,
+check_vector_cst_stepped (const vec<tree> &expected, tree actual,
unsigned int npatterns)
{
ASSERT_EQ (npatterns, VECTOR_CST_NPATTERNS (actual));