diff options
author | Martin Sebor <msebor@redhat.com> | 2021-04-28 19:01:40 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-04-28 19:05:41 -0600 |
commit | 2de7c792569d7a227426aaeb124686a856614da7 (patch) | |
tree | 20e4f8fd06cff9097a8c4696e918f39584b2ddc7 /gcc/tree.c | |
parent | cc806126215c3f4dc187eff3bf923458d8cc6b4f (diff) | |
download | gcc-2de7c792569d7a227426aaeb124686a856614da7.zip gcc-2de7c792569d7a227426aaeb124686a856614da7.tar.gz gcc-2de7c792569d7a227426aaeb124686a856614da7.tar.bz2 |
Move pass free_lang_data to its own file.
gcc/ChangeLog:
* Makefile.in (OBJS): Add ipa-free-lang-data.o.
* ipa-free-lang-data.cc: New file.
* tree.c: Move pass free_lang_data to file above.
(build_array_type_1): Declare extern.
* tree.h (build_array_type_1): Declare.
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 1358 |
1 files changed, 107 insertions, 1251 deletions
@@ -266,8 +266,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]; @@ -722,6 +720,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. */ @@ -5245,1254 +5349,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 © - = 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 0 - if (TREE_CODE (t) == ARRAY_TYPE) - return fld_process_array_type (t, fld_simplified_type (TREE_TYPE (t), fld), - fld_simplified_types, fld); -#endif - 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->declare_variant_alt) - 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. */ @@ -8263,7 +7119,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) { |