aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree.c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
commitafae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch)
treed632cc867d10410ba9fb750523be790b86846ac4 /gcc/tree.c
parent9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff)
parentd2eb616a0f7bea78164912aa438c29fe1ef5774a (diff)
downloadgcc-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.c270
1 files changed, 238 insertions, 32 deletions
diff --git a/gcc/tree.c b/gcc/tree.c
index fa03d96..5fd9da3 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -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 {