2025-12-18 Jakub Jelinek <[email protected]>
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". Temporarily override
lang_hooks.types.build_lang_qualified_type to
lhd_build_lang_qualified_type as the hack relies on that behavior.
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.
--- gcc/langhooks.h.jj 2025-07-27 17:19:23.607127969 +0200
+++ gcc/langhooks.h 2025-12-18 12:57:10.780239979 +0100
@@ -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. */
--- gcc/langhooks.cc.jj 2025-10-11 22:30:51.527481745 +0200
+++ gcc/langhooks.cc 2025-12-18 12:19:41.234383962 +0100
@@ -202,6 +202,16 @@ lhd_register_builtin_type (tree ARG_UNUS
{
}
+/* 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),
--- gcc/langhooks-def.h.jj 2025-07-27 17:19:23.607127969 +0200
+++ gcc/langhooks-def.h 2025-12-18 12:17:28.864684315 +0100
@@ -63,6 +63,7 @@ extern tree lhd_type_for_size (unsigned
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_reusab
#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_reusab
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, \
--- gcc/attribs.cc.jj 2025-12-08 23:28:55.081950885 +0100
+++ gcc/attribs.cc 2025-12-18 13:16:24.200295574 +0100
@@ -1322,14 +1322,15 @@ build_type_attribute_qual_variant (tree
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
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;
}
@@ -2660,12 +2663,24 @@ attr_access::array_as_string (tree type)
[*] 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);
+ /* This terrible hack relies on
+ lang_hooks.types.build_lang_qualified_type not honoring the
+ C/C++ FE array handling, so that quals from the pointed type
+ stay unmodified on element type and quals from the pointer
+ type are installed without errors on the array type. */
+ auto save_build_lang_qualified_type
+ = lang_hooks.types.build_lang_qualified_type;
+ extern tree lhd_build_lang_qualified_type (tree, tree, int);
+ lang_hooks.types.build_lang_qualified_type
+ = lhd_build_lang_qualified_type;
type = build_type_attribute_qual_variant (type, arat, quals);
+ lang_hooks.types.build_lang_qualified_type
+ = save_build_lang_qualified_type;
}
/* Format the type using the current pretty printer. The generic tree
--- gcc/c-family/c-pretty-print.cc.jj 2025-09-23 15:22:09.984552905 +0200
+++ gcc/c-family/c-pretty-print.cc 2025-12-18 13:05:30.823630822 +0100
@@ -634,7 +634,7 @@ c_pretty_printer::direct_abstract_declar
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))
{
--- gcc/c/c-tree.h.jj 2025-11-27 21:34:24.276458859 +0100
+++ gcc/c/c-tree.h 2025-12-18 12:14:13.951071552 +0100
@@ -776,6 +776,7 @@ extern tree c_finish_bc_name (location_t
/* 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 *);
--- gcc/c/c-objc-common.h.jj 2025-05-30 14:37:31.489079636 +0200
+++ gcc/c/c-objc-common.h 2025-12-16 22:26:49.120983402 +0100
@@ -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
--- gcc/c/c-objc-common.cc.jj 2025-09-23 15:22:09.986552878 +0200
+++ gcc/c/c-objc-common.cc 2025-12-18 12:14:00.347307960 +0100
@@ -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)
{
--- gcc/cp/cp-tree.h.jj 2025-12-16 22:26:28.436420328 +0100
+++ gcc/cp/cp-tree.h 2025-12-18 12:12:07.605267206 +0100
@@ -7370,6 +7370,7 @@ extern tmpl_spec_kind current_tmpl_spec_
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);
--- gcc/cp/cp-objcp-common.h.jj 2025-05-30 14:32:05.168473440 +0200
+++ gcc/cp/cp-objcp-common.h 2025-12-16 22:26:49.122248232 +0100
@@ -112,8 +112,8 @@ extern tree cxx_simulate_record_decl (lo
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
--- gcc/cp/tree.cc.jj 2025-11-24 18:30:41.669332263 +0100
+++ gcc/cp/tree.cc 2025-12-18 12:57:31.851426620 +0100
@@ -1390,6 +1390,21 @@ c_build_qualified_type (tree type, int t
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)
+{
+ 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
--- gcc/testsuite/c-c++-common/pr101312-1.c.jj 2025-12-16 22:26:49.123005327
+0100
+++ gcc/testsuite/c-c++-common/pr101312-1.c 2025-12-16 22:26:49.123005327
+0100
@@ -0,0 +1,4 @@
+/* PR c/101312 */
+/* { dg-do compile } */
+
+volatile int a[1] __attribute__((may_alias));
--- gcc/testsuite/c-c++-common/pr101312-2.c.jj 2025-12-16 22:26:49.123089596
+0100
+++ gcc/testsuite/c-c++-common/pr101312-2.c 2025-12-16 22:26:49.123089596
+0100
@@ -0,0 +1,5 @@
+/* PR c/101312 */
+/* { dg-do compile } */
+/* { dg-options "-g" } */
+
+volatile int a[1] __attribute__((may_alias));
Jakub