mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 03:46:53 -05:00
c, c++: Use c*_build_qualified_type instead of build_qualified_type from within build_type_attribute_qual_variant [PR101312]
The following testcases ICE in various ways because of the interaction between attributes and C/C++ c*_build_qualified_type behavior on array types and how they affect TYPE_CANONICAL. For array types, C/C++ moves qualifiers to the element type, but when a cv qualified array build that way has an attribute applied to it, we call build_type_attribute_qual_variant and that doesn't have that handling and builds non-qualified version of the array type with qualified element type and puts it as TYPE_CANONICAL of the type with attribute which is a distinct type copy. The following patch adds a langhook, so that even build_type_attribute_qual_variant uses for C/C++ for array types c*_build_qualified_type. There has been already a related langhook lang_hooks.types.copy_lang_qualifiers used solely for C++, so instead of adding another langhook this adds a combined langhook for those two, where C can handle array types specially and otherwise build_qualified_type, while C++ ditto + do the function/method type modifiers propagation as well. Unfortunately there is a terrible array_as_string hack used by some of the middle-end warnings which creates some array type with sometimes an artificial attribute and then has hacks in the c-family type printing to tweak the printed form, and this hack relies on the previous behavior of build_type_attribute_qual_variant where it even for C/C++ kept element type quals unmodified and added normally invalid quals on the array type itself. The patch stops using build_type_attribute_qual_variant for that and instead uses copy_node on the type and adjusts the quals and adds the attribute to the copy and then ggc_frees it. Also it renames the attribute from "array" to "array " to make it clear it is internal attribute users can't specify even in vendor attributes. 2026-01-28 Jakub Jelinek <jakub@redhat.com> PR c/101312 gcc/ * langhooks.h (struct lang_hooks_for_types): Remove copy_lang_qualifiers. Add build_lang_qualified_type. * langhooks.cc (lhd_build_lang_qualified_type): New function. * langhooks-def.h (lhd_build_lang_qualified_type): Declare. (LANG_HOOKS_COPY_LANG_QUALIFIERS): Remove. (LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE): Add. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Use LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE instead of LANG_HOOKS_COPY_LANG_QUALIFIERS. * attribs.cc (build_type_attribute_qual_variant): Use lang_hooks.types.build_lang_qualified_type instead of build_qualified_type and/or build_qualified_type with optional lang_hooks.types.copy_lang_qualifiers call. (attr_access::array_as_string): Use "array " attribute instead of "array". If attribute has been created or intended quals differ from quals of build_array_type, use copy_node and adjust quals and attributes on the copy, print and then ggc_free. gcc/c-family/ * c-pretty-print.cc (c_pretty_printer::direct_abstract_declarator): Look up "array " attribute instead of "array". gcc/c/ * c-tree.h (c_build_lang_qualified_type): Declare. * c-objc-common.h (LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE): Define. * c-objc-common.cc (c_build_lang_qualified_type): New function. gcc/cp/ * cp-tree.h (cxx_build_lang_qualified_type): Declare. * cp-objcp-common.h (LANG_HOOKS_COPY_LANG_QUALIFIERS): Remove. (LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE): Define. * tree.cc (cxx_build_lang_qualified_type): New function. gcc/testsuite/ * c-c++-common/pr101312-1.c: New test. * c-c++-common/pr101312-2.c: New test.
This commit is contained in:
committed by
Jakub Jelinek
parent
5c2a5bfcd4
commit
3d2a91a376
@@ -1322,14 +1322,15 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
|
||||
warning (OPT_Wattributes,
|
||||
"ignoring attributes applied to %qT after definition",
|
||||
TYPE_MAIN_VARIANT (ttype));
|
||||
return build_qualified_type (ttype, quals);
|
||||
return lang_hooks.types.build_lang_qualified_type (ttype, NULL_TREE,
|
||||
quals);
|
||||
}
|
||||
|
||||
ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
|
||||
if (lang_hooks.types.copy_lang_qualifiers
|
||||
&& otype != TYPE_MAIN_VARIANT (otype))
|
||||
ttype = (lang_hooks.types.copy_lang_qualifiers
|
||||
(ttype, TYPE_MAIN_VARIANT (otype)));
|
||||
tree mtype = NULL_TREE;
|
||||
if (otype != TYPE_MAIN_VARIANT (otype))
|
||||
mtype = TYPE_MAIN_VARIANT (otype);
|
||||
ttype = lang_hooks.types.build_lang_qualified_type (ttype, mtype,
|
||||
TYPE_UNQUALIFIED);
|
||||
|
||||
tree dtype = ntype = build_distinct_type_copy (ttype);
|
||||
|
||||
@@ -1354,13 +1355,15 @@ build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
|
||||
else if (TYPE_CANONICAL (ntype) == ntype)
|
||||
TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
|
||||
|
||||
ttype = build_qualified_type (ntype, quals);
|
||||
if (lang_hooks.types.copy_lang_qualifiers
|
||||
&& otype != TYPE_MAIN_VARIANT (otype))
|
||||
ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype);
|
||||
if (otype != TYPE_MAIN_VARIANT (otype))
|
||||
mtype = otype;
|
||||
else
|
||||
mtype = NULL_TREE;
|
||||
ttype = lang_hooks.types.build_lang_qualified_type (ntype, mtype, quals);
|
||||
}
|
||||
else if (TYPE_QUALS (ttype) != quals)
|
||||
ttype = build_qualified_type (ttype, quals);
|
||||
ttype = lang_hooks.types.build_lang_qualified_type (ttype, NULL_TREE,
|
||||
quals);
|
||||
|
||||
return ttype;
|
||||
}
|
||||
@@ -2652,6 +2655,7 @@ std::string
|
||||
attr_access::array_as_string (tree type) const
|
||||
{
|
||||
std::string typstr;
|
||||
bool free_type = false;
|
||||
|
||||
if (type == error_mark_node)
|
||||
return std::string ();
|
||||
@@ -2692,12 +2696,35 @@ attr_access::array_as_string (tree type) const
|
||||
[*] is represented the same as [0] this hack only works for
|
||||
the most significant bound like static and the others are
|
||||
rendered as [0]. */
|
||||
arat = build_tree_list (get_identifier ("array"), flag);
|
||||
arat = build_tree_list (get_identifier ("array "), flag);
|
||||
}
|
||||
|
||||
const int quals = TYPE_QUALS (type);
|
||||
type = build_array_type (eltype, index_type);
|
||||
type = build_type_attribute_qual_variant (type, arat, quals);
|
||||
if (arat || TYPE_QUALS (type) != quals)
|
||||
{
|
||||
/* We create a new array type which is only used during
|
||||
printing. Can't use build_type_attribute_qual_variant
|
||||
because it might with some lang hooks e.g. try to push
|
||||
qualifiers to the element type, while for the printing
|
||||
this wants the element type qualifiers to be unmodified
|
||||
and ARRAY_TYPE qualifiers to be a copy of the pointer
|
||||
type qualifiers. Furthermore, a type with somtimes
|
||||
weird qualifiers or artificial attribute should be
|
||||
freed right after the use. */
|
||||
type = copy_node (type);
|
||||
if (arat)
|
||||
{
|
||||
TREE_CHAIN (arat) = TYPE_ATTRIBUTES (type);
|
||||
TYPE_ATTRIBUTES (type) = arat;
|
||||
}
|
||||
TYPE_READONLY (type) = (quals & TYPE_QUAL_CONST) != 0;
|
||||
TYPE_VOLATILE (type) = (quals & TYPE_QUAL_VOLATILE) != 0;
|
||||
TYPE_ATOMIC (type) = (quals & TYPE_QUAL_ATOMIC) != 0;
|
||||
TYPE_RESTRICT (type) = (quals & TYPE_QUAL_RESTRICT) != 0;
|
||||
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (quals);
|
||||
free_type = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Format the type using the current pretty printer. The generic tree
|
||||
@@ -2705,6 +2732,8 @@ attr_access::array_as_string (tree type) const
|
||||
std::unique_ptr<pretty_printer> pp (global_dc->clone_printer ());
|
||||
pp_printf (pp.get (), "%qT", type);
|
||||
typstr = pp_formatted_text (pp.get ());
|
||||
if (free_type)
|
||||
ggc_free (type);
|
||||
|
||||
return typstr;
|
||||
}
|
||||
|
||||
@@ -634,7 +634,7 @@ c_pretty_printer::direct_abstract_declarator (tree t)
|
||||
add_space = true;
|
||||
}
|
||||
|
||||
if (tree arr = lookup_attribute ("array", TYPE_ATTRIBUTES (t)))
|
||||
if (tree arr = lookup_attribute ("array ", TYPE_ATTRIBUTES (t)))
|
||||
{
|
||||
if (TREE_VALUE (arr))
|
||||
{
|
||||
|
||||
@@ -70,6 +70,17 @@ c_register_features ()
|
||||
}
|
||||
}
|
||||
|
||||
/* Langhook for building qualified types. */
|
||||
|
||||
tree
|
||||
c_build_lang_qualified_type (tree type, tree, int type_quals)
|
||||
{
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return c_build_qualified_type (type, type_quals);
|
||||
else
|
||||
return build_qualified_type (type, type_quals);
|
||||
}
|
||||
|
||||
bool
|
||||
c_missing_noreturn_ok_p (tree decl)
|
||||
{
|
||||
|
||||
@@ -59,6 +59,8 @@ extern void c_register_features ();
|
||||
#define LANG_HOOKS_PRINT_IDENTIFIER c_print_identifier
|
||||
#undef LANG_HOOKS_TYPES_COMPATIBLE_P
|
||||
#define LANG_HOOKS_TYPES_COMPATIBLE_P c_types_compatible_p
|
||||
#undef LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE
|
||||
#define LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE c_build_lang_qualified_type
|
||||
#undef LANG_HOOKS_MISSING_NORETURN_OK_P
|
||||
#define LANG_HOOKS_MISSING_NORETURN_OK_P c_missing_noreturn_ok_p
|
||||
#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
|
||||
|
||||
@@ -780,6 +780,7 @@ extern tree c_finish_bc_name (location_t, tree, bool);
|
||||
|
||||
/* in c-objc-common.cc */
|
||||
extern bool c_objc_common_init (void);
|
||||
extern tree c_build_lang_qualified_type (tree, tree, int);
|
||||
extern bool c_missing_noreturn_ok_p (tree);
|
||||
extern bool c_warn_unused_global_decl (const_tree);
|
||||
extern void c_initialize_diagnostics (diagnostics::context *);
|
||||
|
||||
@@ -112,8 +112,8 @@ extern tree cxx_simulate_record_decl (location_t, const char *,
|
||||
cxx_simulate_builtin_function_decl
|
||||
#undef LANG_HOOKS_TYPE_HASH_EQ
|
||||
#define LANG_HOOKS_TYPE_HASH_EQ cxx_type_hash_eq
|
||||
#undef LANG_HOOKS_COPY_LANG_QUALIFIERS
|
||||
#define LANG_HOOKS_COPY_LANG_QUALIFIERS cxx_copy_lang_qualifiers
|
||||
#undef LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE
|
||||
#define LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE cxx_build_lang_qualified_type
|
||||
#undef LANG_HOOKS_MISSING_NORETURN_OK_P
|
||||
#define LANG_HOOKS_MISSING_NORETURN_OK_P cp_missing_noreturn_ok_p
|
||||
#undef LANG_HOOKS_BLOCK_MAY_FALLTHRU
|
||||
|
||||
@@ -7540,6 +7540,7 @@ extern tmpl_spec_kind current_tmpl_spec_kind (int);
|
||||
extern tree cxx_builtin_function (tree decl);
|
||||
extern tree cxx_builtin_function_ext_scope (tree decl);
|
||||
extern tree cxx_simulate_builtin_function_decl (tree);
|
||||
extern tree cxx_build_lang_qualified_type (tree, tree, int);
|
||||
extern tree check_elaborated_type_specifier (enum tag_types, tree, bool);
|
||||
extern void warn_extern_redeclared_static (tree, tree);
|
||||
extern tree cxx_comdat_group (tree);
|
||||
|
||||
@@ -1470,6 +1470,27 @@ c_build_qualified_type (tree type, int type_quals, tree /* orig_qual_type */,
|
||||
return cp_build_qualified_type (type, type_quals);
|
||||
}
|
||||
|
||||
/* Implementation of the build_lang_qualified_type langhook. */
|
||||
tree
|
||||
cxx_build_lang_qualified_type (tree type, tree otype, int type_quals)
|
||||
{
|
||||
/* Only handle ARRAY_TYPEs using cp_build_qualified_type, so that
|
||||
quals are pushed to the element type. That is needed for PR101312.
|
||||
For other types just keep using build_qualified_type with
|
||||
cxx_copy_lang_qualifiers if needed, otherwise we can run into
|
||||
issues with FUNCTION_TYPEs with cv-qualifier-seq vs. type-specifier,
|
||||
or REFERENCE_TYPE which will error on certain TYPE_QUALS. */
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
return cp_build_qualified_type (type, type_quals);
|
||||
else
|
||||
{
|
||||
tree ret = build_qualified_type (type, type_quals);
|
||||
if (otype)
|
||||
ret = cxx_copy_lang_qualifiers (ret, otype);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Make a variant of TYPE, qualified with the TYPE_QUALS. Handles
|
||||
arrays correctly. In particular, if TYPE is an array of T's, and
|
||||
|
||||
@@ -63,6 +63,7 @@ extern tree lhd_type_for_size (unsigned precision, int unsignedp);
|
||||
extern void lhd_incomplete_type_error (location_t, const_tree, const_tree);
|
||||
extern tree lhd_type_promotes_to (tree);
|
||||
extern void lhd_register_builtin_type (tree, const char *);
|
||||
extern tree lhd_build_lang_qualified_type (tree, tree, int);
|
||||
extern bool lhd_decl_ok_for_sibcall (const_tree);
|
||||
extern size_t lhd_tree_size (enum tree_code);
|
||||
extern HOST_WIDE_INT lhd_to_target_charset (HOST_WIDE_INT);
|
||||
@@ -212,7 +213,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
|
||||
#define LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES \
|
||||
lhd_omp_firstprivatize_type_sizes
|
||||
#define LANG_HOOKS_TYPE_HASH_EQ NULL
|
||||
#define LANG_HOOKS_COPY_LANG_QUALIFIERS NULL
|
||||
#define LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE lhd_build_lang_qualified_type
|
||||
#define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL
|
||||
#define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL
|
||||
#define LANG_HOOKS_GET_TYPE_BIAS NULL
|
||||
@@ -240,7 +241,7 @@ extern tree lhd_unit_size_without_reusable_padding (tree);
|
||||
LANG_HOOKS_TYPE_MAX_SIZE, \
|
||||
LANG_HOOKS_OMP_FIRSTPRIVATIZE_TYPE_SIZES, \
|
||||
LANG_HOOKS_TYPE_HASH_EQ, \
|
||||
LANG_HOOKS_COPY_LANG_QUALIFIERS, \
|
||||
LANG_HOOKS_BUILD_LANG_QUALIFIED_TYPE, \
|
||||
LANG_HOOKS_GET_ARRAY_DESCR_INFO, \
|
||||
LANG_HOOKS_GET_SUBRANGE_BOUNDS, \
|
||||
LANG_HOOKS_GET_TYPE_BIAS, \
|
||||
|
||||
@@ -202,6 +202,16 @@ lhd_register_builtin_type (tree ARG_UNUSED (type),
|
||||
{
|
||||
}
|
||||
|
||||
/* Return a version of the TYPE, qualified as indicated by the
|
||||
TYPE_QUALS, if one exists. If no qualified version exists yet,
|
||||
creates it and returns it. */
|
||||
tree
|
||||
lhd_build_lang_qualified_type (tree type, tree ARG_UNUSED (otype),
|
||||
int type_quals)
|
||||
{
|
||||
return build_qualified_type (type, type_quals);
|
||||
}
|
||||
|
||||
/* Invalid use of an incomplete type. */
|
||||
void
|
||||
lhd_incomplete_type_error (location_t ARG_UNUSED (loc),
|
||||
|
||||
@@ -134,9 +134,10 @@ struct lang_hooks_for_types
|
||||
FUNCTION_TYPE or METHOD_TYPE. */
|
||||
bool (*type_hash_eq) (const_tree, const_tree);
|
||||
|
||||
/* If non-NULL, return TYPE1 with any language-specific modifiers copied from
|
||||
TYPE2. */
|
||||
tree (*copy_lang_qualifiers) (const_tree, const_tree);
|
||||
/* Return a version of the TYPE, qualified as indicated by the
|
||||
TYPE_QUALS in a language-specific way, if one exists, otherwise create it.
|
||||
If OTYPE is non-NULL, copy extra language modifiers from it too. */
|
||||
tree (*build_lang_qualified_type) (tree, tree, int);
|
||||
|
||||
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
|
||||
for the debugger about the array bounds, strides, etc. */
|
||||
|
||||
4
gcc/testsuite/c-c++-common/pr101312-1.c
Normal file
4
gcc/testsuite/c-c++-common/pr101312-1.c
Normal file
@@ -0,0 +1,4 @@
|
||||
/* PR c/101312 */
|
||||
/* { dg-do compile } */
|
||||
|
||||
volatile int a[1] __attribute__((may_alias));
|
||||
5
gcc/testsuite/c-c++-common/pr101312-2.c
Normal file
5
gcc/testsuite/c-c++-common/pr101312-2.c
Normal file
@@ -0,0 +1,5 @@
|
||||
/* PR c/101312 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-g" } */
|
||||
|
||||
volatile int a[1] __attribute__((may_alias));
|
||||
Reference in New Issue
Block a user