diff options
author | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
---|---|---|
committer | Thomas Koenig <tkoenig@gcc.gnu.org> | 2021-01-03 21:40:04 +0100 |
commit | afae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch) | |
tree | d632cc867d10410ba9fb750523be790b86846ac4 /gcc/tree.c | |
parent | 9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff) | |
parent | d2eb616a0f7bea78164912aa438c29fe1ef5774a (diff) | |
download | gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.zip gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.gz gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.bz2 |
Merge branch 'master' into devel/coarray_native
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 270 |
1 files changed, 238 insertions, 32 deletions
@@ -291,6 +291,7 @@ unsigned const char omp_clause_num_ops[] = 1, /* OMP_CLAUSE_COPYPRIVATE */ 3, /* OMP_CLAUSE_LINEAR */ 2, /* OMP_CLAUSE_ALIGNED */ + 2, /* OMP_CLAUSE_ALLOCATE */ 1, /* OMP_CLAUSE_DEPEND */ 1, /* OMP_CLAUSE_NONTEMPORAL */ 1, /* OMP_CLAUSE_UNIFORM */ @@ -375,6 +376,7 @@ const char * const omp_clause_code_name[] = "copyprivate", "linear", "aligned", + "allocate", "depend", "nontemporal", "uniform", @@ -771,6 +773,33 @@ set_decl_section_name (tree node, const char *value) snode->set_section (value); } +/* Set section name of NODE to match the section name of OTHER. + + set_decl_section_name (decl, other) is equivalent to + set_decl_section_name (decl, DECL_SECTION_NAME (other)), but possibly more + efficient. */ +void +set_decl_section_name (tree decl, const_tree other) +{ + struct symtab_node *other_node = symtab_node::get (other); + if (other_node) + { + struct symtab_node *decl_node; + if (VAR_P (decl)) + decl_node = varpool_node::get_create (decl); + else + decl_node = cgraph_node::get_create (decl); + decl_node->set_section (*other_node); + } + else + { + struct symtab_node *decl_node = symtab_node::get (decl); + if (!decl_node) + return; + decl_node->set_section (NULL); + } +} + /* Return TLS model of a variable NODE. */ enum tls_model decl_tls_model (const_tree node) @@ -835,6 +864,7 @@ tree_code_size (enum tree_code code) case BOOLEAN_TYPE: case INTEGER_TYPE: case REAL_TYPE: + case OPAQUE_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: case NULLPTR_TYPE: @@ -1212,7 +1242,7 @@ copy_node (tree node MEM_STAT_DECL) SET_DECL_VALUE_EXPR (t, DECL_VALUE_EXPR (node)); DECL_HAS_VALUE_EXPR_P (t) = 1; } - /* DECL_DEBUG_EXPR is copied explicitely by callers. */ + /* DECL_DEBUG_EXPR is copied explicitly by callers. */ if (VAR_P (node)) { DECL_HAS_DEBUG_EXPR_P (t) = 0; @@ -1725,8 +1755,15 @@ wide_int_to_tree (tree type, const poly_wide_int_ref &value) return build_poly_int_cst (type, value); } -void -cache_integer_cst (tree t) +/* Insert INTEGER_CST T into a cache of integer constants. And return + the cached constant (which may or may not be T). If MIGHT_DUPLICATE + is false, and T falls into the type's 'smaller values' range, there + cannot be an existing entry. Otherwise, if MIGHT_DUPLICATE is true, + or the value is large, should an existing entry exist, it is + returned (rather than inserting T). */ + +tree +cache_integer_cst (tree t, bool might_duplicate ATTRIBUTE_UNUSED) { tree type = TREE_TYPE (t); int ix = -1; @@ -1735,20 +1772,25 @@ cache_integer_cst (tree t) gcc_assert (!TREE_OVERFLOW (t)); + /* The caching indices here must match those in + wide_int_to_type_1. */ switch (TREE_CODE (type)) { case NULLPTR_TYPE: - gcc_assert (integer_zerop (t)); + gcc_checking_assert (integer_zerop (t)); /* Fallthru. */ case POINTER_TYPE: case REFERENCE_TYPE: - /* Cache NULL pointer. */ - if (integer_zerop (t)) - { - limit = 1; + { + if (integer_zerop (t)) ix = 0; - } + else if (integer_onep (t)) + ix = 2; + + if (ix >= 0) + limit = 3; + } break; case BOOLEAN_TYPE: @@ -1815,21 +1857,32 @@ cache_integer_cst (tree t) TYPE_CACHED_VALUES (type) = make_tree_vec (limit); } - gcc_assert (TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) == NULL_TREE); - TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; + if (tree r = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix)) + { + gcc_checking_assert (might_duplicate); + t = r; + } + else + TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t; } else { /* Use the cache of larger shared ints. */ tree *slot = int_cst_hash_table->find_slot (t, INSERT); - /* If there is already an entry for the number verify it's the - same. */ - if (*slot) - gcc_assert (wi::to_wide (tree (*slot)) == wi::to_wide (t)); + if (tree r = *slot) + { + /* If there is already an entry for the number verify it's the + same value. */ + gcc_checking_assert (wi::to_wide (tree (r)) == wi::to_wide (t)); + /* And return the cached value. */ + t = r; + } else /* Otherwise insert this one into the hash table. */ *slot = t; } + + return t; } @@ -2132,7 +2185,7 @@ build_constructor_from_vec (tree type, const vec<tree, va_gc> *vals) { vec<constructor_elt, va_gc> *v = NULL; - for (tree t : *vals) + for (tree t : vals) CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, t); return build_constructor (type, v); @@ -2248,6 +2301,22 @@ build_real_from_int_cst (tree type, const_tree i) return v; } +/* Return a new REAL_CST node whose type is TYPE + and whose value is the integer value I which has sign SGN. */ + +tree +build_real_from_wide (tree type, const wide_int_ref &i, signop sgn) +{ + REAL_VALUE_TYPE d; + + /* Clear all bits of the real value type so that we can later do + bitwise comparisons to see if two values are the same. */ + memset (&d, 0, sizeof d); + + real_from_integer (&d, TYPE_MODE (type), i, sgn); + return build_real (type, d); +} + /* Return a newly constructed STRING_CST node whose value is the LEN characters at STR when STR is nonnull, or all zeros otherwise. Note that for a C string literal, LEN should include the trailing NUL. @@ -3414,7 +3483,17 @@ array_type_nelts (const_tree type) /* TYPE_MAX_VALUE may not be set if the array has unknown length. */ if (!max) - return error_mark_node; + { + /* zero sized arrays are represented from C FE as complete types with + NULL TYPE_MAX_VALUE and zero TYPE_SIZE, while C++ FE represents + them as min 0, max -1. */ + if (COMPLETE_TYPE_P (type) + && integer_zerop (TYPE_SIZE (type)) + && integer_zerop (min)) + return build_int_cst (TREE_TYPE (min), -1); + + return error_mark_node; + } return (integer_zerop (min) ? max @@ -3893,6 +3972,7 @@ type_contains_placeholder_1 (const_tree type) switch (TREE_CODE (type)) { case VOID_TYPE: + case OPAQUE_TYPE: case COMPLEX_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: @@ -7021,6 +7101,7 @@ type_cache_hasher::equal (type_hash *a, type_hash *b) switch (TREE_CODE (a->type)) { case VOID_TYPE: + case OPAQUE_TYPE: case COMPLEX_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: @@ -10514,7 +10595,7 @@ set_call_expr_flags (tree decl, int flags) if (flags & ECF_RET1) DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("fn spec"), - build_tree_list (NULL_TREE, build_string (1, "1")), + build_tree_list (NULL_TREE, build_string (2, "1 ")), DECL_ATTRIBUTES (decl)); if ((flags & ECF_TM_PURE) && flag_tm) apply_tm_attr (decl, get_identifier ("transaction_pure")); @@ -10576,10 +10657,10 @@ build_common_builtin_nodes (void) if (!builtin_decl_explicit_p (BUILT_IN_MEMCPY)) local_define_builtin ("__builtin_memcpy", ftype, BUILT_IN_MEMCPY, - "memcpy", ECF_NOTHROW | ECF_LEAF | ECF_RET1); + "memcpy", ECF_NOTHROW | ECF_LEAF); if (!builtin_decl_explicit_p (BUILT_IN_MEMMOVE)) local_define_builtin ("__builtin_memmove", ftype, BUILT_IN_MEMMOVE, - "memmove", ECF_NOTHROW | ECF_LEAF | ECF_RET1); + "memmove", ECF_NOTHROW | ECF_LEAF); } if (!builtin_decl_explicit_p (BUILT_IN_MEMCMP)) @@ -10597,7 +10678,7 @@ build_common_builtin_nodes (void) ptr_type_node, integer_type_node, size_type_node, NULL_TREE); local_define_builtin ("__builtin_memset", ftype, BUILT_IN_MEMSET, - "memset", ECF_NOTHROW | ECF_LEAF | ECF_RET1); + "memset", ECF_NOTHROW | ECF_LEAF); } /* If we're checking the stack, `alloca' can throw. */ @@ -10652,6 +10733,12 @@ build_common_builtin_nodes (void) ftype = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, NULL_TREE); + if (!builtin_decl_explicit_p (BUILT_IN_CLEAR_CACHE)) + local_define_builtin ("__builtin___clear_cache", ftype, + BUILT_IN_CLEAR_CACHE, + "__clear_cache", + ECF_NOTHROW); + local_define_builtin ("__builtin_nonlocal_goto", ftype, BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto", @@ -10926,8 +11013,15 @@ build_truth_vector_type_for_mode (poly_uint64 nunits, machine_mode mask_mode) { gcc_assert (mask_mode != BLKmode); - poly_uint64 vsize = GET_MODE_BITSIZE (mask_mode); - unsigned HOST_WIDE_INT esize = vector_element_size (vsize, nunits); + unsigned HOST_WIDE_INT esize; + if (VECTOR_MODE_P (mask_mode)) + { + poly_uint64 vsize = GET_MODE_BITSIZE (mask_mode); + esize = vector_element_size (vsize, nunits); + } + else + esize = 1; + tree bool_type = build_nonstandard_boolean_type (esize); return make_vector_type (bool_type, nunits, mask_mode); @@ -12206,6 +12300,7 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data, 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: @@ -12515,8 +12610,40 @@ tree_nonartificial_location (tree exp) return EXPR_LOCATION (exp); } +/* Return the location into which EXP has been inlined. Analogous + to tree_nonartificial_location() above but not limited to artificial + functions declared inline. If SYSTEM_HEADER is true, return + the macro expansion point of the location if it's in a system header */ -/* These are the hash table functions for the hash table of OPTIMIZATION_NODEq +location_t +tree_inlined_location (tree exp, bool system_header /* = true */) +{ + location_t loc = UNKNOWN_LOCATION; + + tree block = TREE_BLOCK (exp); + + while (block && TREE_CODE (block) == BLOCK + && BLOCK_ABSTRACT_ORIGIN (block)) + { + tree ao = BLOCK_ABSTRACT_ORIGIN (block); + if (TREE_CODE (ao) == FUNCTION_DECL) + loc = BLOCK_SOURCE_LOCATION (block); + else if (TREE_CODE (ao) != BLOCK) + break; + + block = BLOCK_SUPERCONTEXT (block); + } + + if (loc == UNKNOWN_LOCATION) + loc = EXPR_LOCATION (exp); + + if (system_header) + return expansion_point_location_if_in_system_header (loc); + + return loc; +} + +/* These are the hash table functions for the hash table of OPTIMIZATION_NODE nodes. */ /* Return the hash code X, an OPTIMIZATION_NODE or TARGET_OPTION code. */ @@ -13651,9 +13778,9 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */) { gcc_assert (TREE_CODE (ref) == COMPONENT_REF); - special_array_member arkbuf; + special_array_member sambuf; if (!sam) - sam = &arkbuf; + sam = &sambuf; *sam = special_array_member::none; /* The object/argument referenced by the COMPONENT_REF and its type. */ @@ -13667,7 +13794,13 @@ component_ref_size (tree ref, special_array_member *sam /* = NULL */) { tree memtype = TREE_TYPE (member); if (TREE_CODE (memtype) != ARRAY_TYPE) - return memsize; + /* DECL_SIZE may be less than TYPE_SIZE in C++ when referring + to the type of a class with a virtual base which doesn't + reflect the size of the virtual's members (see pr97595). + If that's the case fail for now and implement something + more robust in the future. */ + return (tree_int_cst_equal (memsize, TYPE_SIZE_UNIT (memtype)) + ? memsize : NULL_TREE); bool trailing = array_at_struct_end_p (ref); bool zero_length = integer_zerop (memsize); @@ -14983,6 +15116,10 @@ maybe_wrap_with_location (tree expr, location_t loc) if (EXCEPTIONAL_CLASS_P (expr)) return expr; + /* Compiler-generated temporary variables don't need a wrapper. */ + if (DECL_P (expr) && DECL_ARTIFICIAL (expr) && DECL_IGNORED_P (expr)) + return expr; + /* If any auto_suppress_location_wrappers are active, don't create wrappers. */ if (suppress_location_wrappers > 0) @@ -15074,22 +15211,22 @@ get_nonnull_args (const_tree fntype) /* Returns true if TYPE is a type where it and all of its subobjects (recursively) are of structure, union, or array type. */ -static bool -default_is_empty_type (tree type) +bool +is_empty_type (const_tree type) { if (RECORD_OR_UNION_TYPE_P (type)) { for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && !DECL_PADDING_P (field) - && !default_is_empty_type (TREE_TYPE (field))) + && !is_empty_type (TREE_TYPE (field))) return false; return true; } else if (TREE_CODE (type) == ARRAY_TYPE) return (integer_minus_onep (array_type_nelts (type)) || TYPE_DOMAIN (type) == NULL_TREE - || default_is_empty_type (TREE_TYPE (type))); + || is_empty_type (TREE_TYPE (type))); return false; } @@ -15108,7 +15245,7 @@ default_is_empty_record (const_tree type) if (TREE_ADDRESSABLE (type)) return false; - return default_is_empty_type (TYPE_MAIN_VARIANT (type)); + return is_empty_type (TYPE_MAIN_VARIANT (type)); } /* Determine whether TYPE is a structure with a flexible array member, @@ -15281,6 +15418,75 @@ 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. */ + +bool +valid_new_delete_pair_p (tree new_asm, tree delete_asm) +{ + 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); + + if (new_len < 5 || delete_len < 6) + return false; + if (new_name[0] == '_') + ++new_name, --new_len; + if (new_name[0] == '_') + ++new_name, --new_len; + if (delete_name[0] == '_') + ++delete_name, --delete_len; + if (delete_name[0] == '_') + ++delete_name, --delete_len; + if (new_len < 4 || delete_len < 5) + return false; + /* *_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; + /* _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')) + return false; + /* 'j', 'm' and 'y' correspond to size_t. */ + if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y') + return false; + if (delete_name[3] != 'P' || delete_name[4] != 'v') + return false; + if (new_len == 4 + || (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14))) + { + /* _ZnXY or _ZnXYRKSt9nothrow_t matches + _ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */ + if (delete_len == 5) + return true; + if (delete_len == 6 && delete_name[5] == new_name[3]) + return true; + if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14)) + return true; + } + else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15)) + || (new_len == 33 + && !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29))) + { + /* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches + _ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or + _ZdXPvSt11align_val_tRKSt9nothrow_t. */ + if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15)) + return true; + if (delete_len == 21 + && delete_name[5] == new_name[3] + && !memcmp (delete_name + 6, "St11align_val_t", 15)) + return true; + if (delete_len == 34 + && !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29)) + return true; + } + return false; +} + #if CHECKING_P namespace selftest { |