aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog220
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in5
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-attribs.cc19
-rw-r--r--gcc/c/ChangeLog42
-rw-r--r--gcc/c/c-parser.cc101
-rw-r--r--gcc/c/c-tree.h3
-rw-r--r--gcc/c/c-typeck.cc213
-rw-r--r--gcc/common.opt2
-rw-r--r--gcc/common/config/riscv/riscv-common.cc5
-rw-r--r--gcc/config/i386/i386.h34
-rw-r--r--gcc/config/i386/i386.md14
-rw-r--r--gcc/config/i386/predicates.md6
-rwxr-xr-xgcc/config/riscv/arch-canonicalize563
-rw-r--r--gcc/config/riscv/riscv.h10
-rwxr-xr-xgcc/configure44
-rw-r--r--gcc/configure.ac29
-rw-r--r--gcc/cp/ChangeLog25
-rw-r--r--gcc/cp/constexpr.cc21
-rw-r--r--gcc/cp/mangle.cc51
-rw-r--r--gcc/cp/parser.cc113
-rw-r--r--gcc/cp/semantics.cc5
-rw-r--r--gcc/d/ChangeLog4
-rw-r--r--gcc/d/Make-lang.in2
-rw-r--r--gcc/doc/install.texi2
-rw-r--r--gcc/doc/invoke.texi13
-rw-r--r--gcc/gengtype-lex.l11
-rw-r--r--gcc/gimple-lower-bitint.cc83
-rw-r--r--gcc/gimplify.cc45
-rw-r--r--gcc/match.pd19
-rw-r--r--gcc/testsuite/ChangeLog109
-rw-r--r--gcc/testsuite/c-c++-common/cpp/comment-ff-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c21
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c23
-rw-r--r--gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c17
-rw-r--r--gcc/testsuite/g++.dg/abi/mangle82.C85
-rw-r--r--gcc/testsuite/g++.dg/cpp26/constexpr-new3.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class73.C30
-rw-r--r--gcc/testsuite/gcc.dg/bitint-125.c15
-rw-r--r--gcc/testsuite/gcc.dg/bitintext.h28
-rw-r--r--gcc/testsuite/gcc.dg/pr121217.c19
-rw-r--r--gcc/testsuite/gcc.dg/torture/bitint-83.c48
-rw-r--r--gcc/testsuite/gcc.dg/torture/bitint-84.c18
-rw-r--r--gcc/testsuite/gcc.dg/torture/bitint-85.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool-ai.c7
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool-vi.c5
-rw-r--r--gcc/testsuite/gcc.dg/torture/hardbool.c68
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-gather-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/vla-tert-1.c293
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c8
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-unset-1.c7
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-unset-2.c7
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-unset-3.c7
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-unset-4.c7
-rw-r--r--gcc/testsuite/gcc.target/riscv/arch-unset-5.c7
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f032
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c46
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f032
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c46
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c47
-rw-r--r--gcc/tree-pretty-print.cc10
-rw-r--r--gcc/tree-vect-data-refs.cc61
-rw-r--r--gcc/tree-vect-slp.cc22
-rw-r--r--gcc/tree-vect-stmts.cc74
-rw-r--r--gcc/tree-vectorizer.h9
-rw-r--r--gcc/tree.cc4
-rw-r--r--gcc/tree.h6
-rw-r--r--libgcc/ChangeLog6
-rw-r--r--libgcc/enable-execute-stack-mprotect.c1
-rw-r--r--libgfortran/ChangeLog7
-rw-r--r--libgomp/ChangeLog20
-rw-r--r--libgomp/target.c14
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c65
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c58
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c67
-rw-r--r--libiberty/ChangeLog5
-rw-r--r--libiberty/testsuite/test-doubly-linked-list.c13
79 files changed, 2671 insertions, 521 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d975768..b600551 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,223 @@
+2025-08-06 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/96226
+ * config/i386/predicates.md (and_operator): New operator.
+ * config/i386/i386.md (splitter after *<rotate_insn><mode>3_mask):
+ Use and_operator to match AND RTX and use its mode
+ in the split pattern.
+
+2025-08-06 Gerald Pfeifer <gerald@pfeifer.com>
+
+ PR target/69374
+ * doc/install.texi (Prerequisites): Replace bzip2 by xz.
+
+2025-08-06 Yangyu Chen <cyy@cyyself.name>
+
+ * config/i386/i386.h (PTA_BDVER1):
+ Add missing PTA_POPCNT and PTA_LZCNT with PTA_ABM.
+ (PTA_ZNVER1): Ditto.
+ (PTA_BTVER1): Ditto.
+ (PTA_LUJIAZUI): Ditto.
+ (PTA_YONGFENG): Do not include extra PTA_LZCNT.
+
+2025-08-06 Sam James <sam@gentoo.org>
+
+ PR libstdc++/29286
+ * Makefile.in (ALIASING_FLAGS): Drop.
+ * configure: Regenerate.
+ * configure.ac: Drop -fno-strict-aliasing workaround for < GCC 4.3.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.cc (vect_supportable_dr_alignment):
+ Prune dead code.
+
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * common.opt: Document additional ABI version 21 change.
+ * doc/invoke.texi: Likewise.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vectorizer.h (_slp_tree::gs_scale): New.
+ (_slp_tree::gs_base): Likewise.
+ (SLP_TREE_GS_SCALE): Likewise.
+ (SLP_TREE_GS_BASE): Likewise.
+ (vect_describe_gather_scatter_call): Declare.
+ * tree-vect-slp.cc (_slp_tree::_slp_tree): Initialize
+ new members.
+ (vect_build_slp_tree_2): Record gather/scatter base and scale.
+ (vect_get_and_check_slp_defs): For gather/scatter IFNs
+ describe the call to first_gs_info.
+ * tree-vect-data-refs.cc (vect_gather_scatter_fn_p): Add
+ mode of operation with fixed offset vector type.
+ (vect_describe_gather_scatter_call): Export.
+ * tree-vect-stmts.cc (get_load_store_type): Do not call
+ vect_check_gather_scatter to fill gs_info, instead populate
+ from the SLP tree. Check which of, IFN, decl or fallback
+ is supported and record that decision.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.cc (vectorizable_store): Build proper
+ alias + align pointer value for gather/scatter and SLP
+ and use it.
+ (vectorizable_load): Likewise.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.cc (check_load_store_for_partial_vectors):
+ Remove redundant gather/scatter target support check, instead
+ check the recorded ifns. Also allow legacy gather/scatter
+ with loop masking.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gimple-lower-bitint.cc (gimple_lower_bitint): Fix up last
+ commit, cast limb_prec to unsigned before comparison.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * match.pd: Preserve conversion to _BitInt before a VCE
+ if the _BitInt is extended.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gimple-lower-bitint.cc (bitint_large_huge::lower_mergeable_stmt):
+ Zero-extend the partial limb of any unsigned _BitInt LHS assigned
+ with a widening sign-extension.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gimple-lower-bitint.cc (bitint_large_huge::limb_access):
+ Add a parameter abi_load_p. If set, load a limb directly
+ in its actual precision without casting from m_limb_type.
+ (struct bitint_large_huge): Same.
+ (bitint_large_huge::handle_load): Use.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gimple-lower-bitint.cc (abi_limb_prec): New variable
+ (bitint_precision_kind): Initialize it.
+ (gimple_lower_bitint): Clear it at the start. For
+ min_prec > limb_prec descreased precision vars for
+ INTEGER_CST PHI arguments ensure min_prec is either
+ prec or multiple of abi_limb_prec.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121127
+ * gimple-lower-bitint.cc (bitint_large_huge::handle_operand_addr): For
+ uninitialized SSA_NAME, set *prec_stored to 0 rather than *prec.
+ Handle that case in narrowing casts. If prec_stored is non-NULL,
+ set *prec_stored to prec_stored_val.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR bootstrap/121386
+ * Makefile.in (gengtype-lex.cc): Append #define FLEX_SCANNER,
+ #include "system.h" and #undef FLEX_SCANNER to the prepended lines.
+ * gengtype-lex.l: Remove inclusion of config.h or bconfig.h, system.h
+ and definition of malloc/realloc from %{} section.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * config/riscv/arch-canonicalize: Read extension data from
+ riscv-ext*.def and adding unittest.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * common/config/riscv/riscv-common.cc (riscv_expand_arch):
+ Ignore `unset`.
+ * config/riscv/riscv.h (OPTION_DEFAULT_SPECS): Handle
+ `-march=unset`.
+ (ARCH_UNSET_CLEANUP_SPECS): New.
+ (DRIVER_SELF_SPECS): Handle -march=unset.
+ * doc/invoke.texi (RISC-V Options): Update documentation for
+ `-march=unset`.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * gimplify.cc (remove_unused_omp_iterator_vars): Display unused
+ variable warning for 'to' and 'from' clauses.
+ (gimplify_scan_omp_clauses): Add argument for iterator loop sequence.
+ Gimplify the clause decl and size into the iterator loop if iterators
+ are used.
+ (gimplify_omp_workshare): Add argument for iterator loops sequence
+ in call to gimplify_scan_omp_clauses.
+ (gimplify_omp_target_update): Call remove_unused_omp_iterator_vars and
+ build_omp_iterators_loops. Add loop sequence as argument when calling
+ gimplify_scan_omp_clauses, gimplify_adjust_omp_clauses and building
+ the Gimple statement.
+ * tree-pretty-print.cc (dump_omp_clause): Call dump_omp_iterators
+ for to/from clauses with iterators.
+ * tree.cc (omp_clause_num_ops): Add extra operand for OMP_CLAUSE_FROM
+ and OMP_CLAUSE_TO.
+ * tree.h (OMP_CLAUSE_HAS_ITERATORS): Add check for OMP_CLAUSE_TO and
+ OMP_CLAUSE_FROM.
+ (OMP_CLAUSE_ITERATORS): Likewise.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * gimple-pretty-print.cc (dump_gimple_omp_target): Print expanded
+ iterator loops.
+ * gimple.cc (gimple_build_omp_target): Add argument for iterator
+ loops sequence. Initialize iterator loops field.
+ * gimple.def (GIMPLE_OMP_TARGET): Set GSS symbol to GSS_OMP_TARGET.
+ * gimple.h (gomp_target): Set GSS symbol to GSS_OMP_TARGET. Add extra
+ field for iterator loops.
+ (gimple_build_omp_target): Add argument for iterator loops sequence.
+ (gimple_omp_target_iterator_loops): New.
+ (gimple_omp_target_iterator_loops_ptr): New.
+ (gimple_omp_target_set_iterator_loops): New.
+ * gimplify.cc (find_var_decl): New.
+ (copy_omp_iterator): New.
+ (remap_omp_iterator_var_1): New.
+ (remap_omp_iterator_var): New.
+ (remove_unused_omp_iterator_vars): New.
+ (struct iterator_loop_info_t): New type.
+ (iterator_loop_info_map_t): New type.
+ (build_omp_iterators_loops): New.
+ (enter_omp_iterator_loop_context_1): New.
+ (enter_omp_iterator_loop_context): New.
+ (enter_omp_iterator_loop_context): New.
+ (exit_omp_iterator_loop_context): New.
+ (gimplify_adjust_omp_clauses): Add argument for iterator loop
+ sequence. Gimplify the clause decl and size into the iterator
+ loop if iterators are used.
+ (gimplify_omp_workshare): Call remove_unused_omp_iterator_vars and
+ build_omp_iterators_loops for OpenMP target expressions. Add
+ loop sequence as argument when calling gimplify_adjust_omp_clauses
+ and building the Gimple statement.
+ * gimplify.h (enter_omp_iterator_loop_context): New prototype.
+ (exit_omp_iterator_loop_context): New prototype.
+ * gsstruct.def (GSS_OMP_TARGET): New.
+ * omp-low.cc (lower_omp_map_iterator_expr): New.
+ (lower_omp_map_iterator_size): New.
+ (finish_omp_map_iterators): New.
+ (lower_omp_target): Add sorry if iterators used with deep mapping.
+ Call lower_omp_map_iterator_expr before assigning to sender ref.
+ Call lower_omp_map_iterator_size before setting the size. Insert
+ iterator loop sequence before the statements for the target clause.
+ * tree-nested.cc (convert_nonlocal_reference_stmt): Walk the iterator
+ loop sequence of OpenMP target statements.
+ (convert_local_reference_stmt): Likewise.
+ (convert_tramp_reference_stmt): Likewise.
+ * tree-pretty-print.cc (dump_omp_iterators): Dump extra iterator
+ information if present.
+ (dump_omp_clause): Call dump_omp_iterators for iterators in map
+ clauses.
+ * tree.cc (omp_clause_num_ops): Add operand for OMP_CLAUSE_MAP.
+ (walk_tree_1): Do not walk last operand of OMP_CLAUSE_MAP.
+ * tree.h (OMP_CLAUSE_HAS_ITERATORS): New.
+ (OMP_CLAUSE_ITERATORS): New.
+
2025-08-05 H.J. Lu <hjl.tools@gmail.com>
PR target/121410
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index cf43af9..d4024d7 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250806
+20250807
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index d7d5cbe..cc79595 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -187,8 +187,6 @@ C_STRICT_WARN = @c_strict_warn@
NOEXCEPTION_FLAGS = @noexception_flags@
-ALIASING_FLAGS = @aliasing_flags@
-
# This is set by --disable-maintainer-mode (default) to "#"
# FIXME: 'MAINT' will always be set to an empty string, no matter if
# --disable-maintainer-mode is used or not. This is because the
@@ -3402,6 +3400,9 @@ gengtype-lex.cc : gengtype-lex.l
echo '#else' >> $@.tmp; \
echo '#include "bconfig.h"' >> $@.tmp; \
echo '#endif' >> $@.tmp; \
+ echo '#define FLEX_SCANNER' >> $@.tmp; \
+ echo '#include "system.h"' >> $@.tmp; \
+ echo '#undef FLEX_SCANNER' >> $@.tmp; \
cat $@ >> $@.tmp; \
mv $@.tmp $@; \
}
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index c9ab153..2abe6df 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-attribs.cc (handle_hardbool_attribute): Create distinct
+ enumeration types, with structural equality. Handle
+ base type qualifiers.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* c-attribs.cc (handle_argspec_attribute): Update.
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index a0d832b..041a004 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -1128,11 +1128,16 @@ handle_hardbool_attribute (tree *node, tree name, tree args,
}
tree orig = *node;
- *node = build_duplicate_type (orig);
+ /* Drop qualifiers from the base type. Keep attributes, so that, in the odd
+ chance attributes are applicable and relevant to the base type, if they
+ are specified first, or through a typedef, they wouldn't be dropped on the
+ floor here. */
+ tree unqual = build_qualified_type (orig, TYPE_UNQUALIFIED);
+ *node = build_distinct_type_copy (unqual);
TREE_SET_CODE (*node, ENUMERAL_TYPE);
- ENUM_UNDERLYING_TYPE (*node) = orig;
- TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig);
+ ENUM_UNDERLYING_TYPE (*node) = unqual;
+ SET_TYPE_STRUCTURAL_EQUALITY (*node);
tree false_value;
if (args)
@@ -1191,7 +1196,13 @@ handle_hardbool_attribute (tree *node, tree name, tree args,
gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node));
TYPE_VALUES (*node) = values;
- TYPE_NAME (*node) = orig;
+ TYPE_NAME (*node) = unqual;
+
+ if (TYPE_QUALS (orig) != TYPE_QUALS (*node))
+ {
+ *node = build_qualified_type (*node, TYPE_QUALS (orig));
+ TYPE_NAME (*node) = orig;
+ }
return NULL_TREE;
}
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 464e5a1..2e5c896 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,45 @@
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * c-tree.h (C_BOOLEAN_TYPE_P): Cover hardbools as well.
+ * c-typeck.cc (convert_lvalue_to_rvalue): New overload and
+ wrapper.
+ (build_atomic_assign, build_modify_expr): Use it.
+ (build_asm_expr, handle_omp-array_sections_1): Simplify with
+ it.
+ (build_unary_op): Handle hardbools.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * c-typeck.cc (composite_type_cond): Renamed from
+ composite_type with argument for condition
+ (composite_type): New function.
+ (composite_type_internal): Implement new logic.
+ (build_conditional_expr): Pass condition.
+ (common_pointer_type): Adapt.
+ (pointer_diff): Adapt.
+ (build_binary_op): Adapt.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * c-typeck.cc (tagged_types_tu_compatible_p): Add check.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-parser.cc (c_parser_omp_variable_list): Use location of the
+ map expression as the clause location.
+ (c_parser_omp_clause_map): Parse 'iterator' modifier.
+ * c-typeck.cc (c_finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
2025-08-02 Martin Uecker <uecker@tugraz.at>
* c-decl.cc (get_parm_array_spec): Remove.
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index 5ddeeb2..814accf 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -20576,8 +20576,11 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
@@ -20588,18 +20591,85 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
if (!parens.require_open (parser))
return list;
+ int pos = 1, colon_pos = 0;
+ int iterator_length = 0;
+
+ while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
+ {
+ const char *identifier =
+ IDENTIFIER_POINTER (c_parser_peek_nth_token_raw (parser, pos)->value);
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type
+ == CPP_OPEN_PAREN)
+ {
+ unsigned int npos = pos + 2;
+ if (c_parser_check_balanced_raw_token_sequence (parser, &npos)
+ && (c_parser_peek_nth_token_raw (parser, npos)->type
+ == CPP_CLOSE_PAREN))
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = npos - pos + 1;
+ pos = npos;
+ }
+ }
+ if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
+ }
+
bool present = false;
- c_token *token = c_parser_peek_token (parser);
+ tree iterators = NULL_TREE;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), "present") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
+ for (int pos = 1; pos < colon_pos; ++pos)
{
- present = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
+ c_token *token = c_parser_peek_token (parser);
+ if (token->type == CPP_COMMA)
+ {
+ c_parser_consume_token (parser);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ c_parser_error (parser, "too many %<present%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ present = true;
+ c_parser_consume_token (parser);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ c_parser_error (parser, "too many %<iterator%> modifiers");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ iterators = c_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> or "
+ "%<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ parens.skip_until_found_close (parser);
+ return list;
+ }
}
+ if (colon_pos)
+ c_parser_require (parser, CPP_COLON, "expected %<:%>");
+
tree nl = c_parser_omp_variable_list (parser, loc, kind, list);
parens.skip_until_found_close (parser);
@@ -20607,6 +20677,19 @@ c_parser_omp_clause_from_to (c_parser *parser, enum omp_clause_code kind,
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = pop_scope ();
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index bb0b113..dba94ab 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -163,7 +163,8 @@ along with GCC; see the file COPYING3. If not see
(TREE_CODE (TYPE) == BOOLEAN_TYPE \
|| (TREE_CODE (TYPE) == ENUMERAL_TYPE \
&& ENUM_UNDERLYING_TYPE (TYPE) != NULL_TREE \
- && TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE))
+ && (TREE_CODE (ENUM_UNDERLYING_TYPE (TYPE)) == BOOLEAN_TYPE \
+ || c_hardbool_type_attr (TYPE))))
/* Record parser information about an expression that is irrelevant
for code generation alongside a tree representing its value. */
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 6c8df7d..7a95f72 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -641,7 +641,8 @@ struct composite_cache {
};
tree
-composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
+composite_type_internal (tree t1, tree t2, tree cond,
+ struct composite_cache* cache)
{
enum tree_code code1;
enum tree_code code2;
@@ -686,8 +687,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type_internal (pointed_to_1,
- pointed_to_2, cache);
+ tree target = composite_type_internal (pointed_to_1, pointed_to_2,
+ cond, cache);
t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
@@ -695,25 +696,20 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
case ARRAY_TYPE:
{
- tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- cache);
- int quals;
- tree unqual_elt;
tree d1 = TYPE_DOMAIN (t1);
tree d2 = TYPE_DOMAIN (t2);
- bool d1_variable, d2_variable;
- bool d1_zero, d2_zero;
- bool t1_complete, t2_complete;
/* We should not have any type quals on arrays at all. */
gcc_assert (!TYPE_QUALS_NO_ADDR_SPACE (t1)
&& !TYPE_QUALS_NO_ADDR_SPACE (t2));
- t1_complete = COMPLETE_TYPE_P (t1);
- t2_complete = COMPLETE_TYPE_P (t2);
+ bool t1_complete = COMPLETE_TYPE_P (t1);
+ bool t2_complete = COMPLETE_TYPE_P (t2);
- d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
- d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+ bool d1_zero = d1 == NULL_TREE || !TYPE_MAX_VALUE (d1);
+ bool d2_zero = d2 == NULL_TREE || !TYPE_MAX_VALUE (d2);
+
+ bool d1_variable, d2_variable;
d1_variable = (!d1_zero
&& (TREE_CODE (TYPE_MIN_VALUE (d1)) != INTEGER_CST
@@ -722,10 +718,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
- bool use1 = TYPE_DOMAIN (t1)
- && (d2_variable || d2_zero || !d1_variable);
- bool use2 = TYPE_DOMAIN (t2)
- && (d1_variable || d1_zero || !d2_variable);
+ bool use1 = d1 && (d2_variable || d2_zero || !d1_variable);
+ bool use2 = d2 && (d1_variable || d1_zero || !d2_variable);
/* If the first is an unspecified size pick the other one. */
if (d2_variable && c_type_unspecified_p (t1))
@@ -734,25 +728,53 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
use1 = false;
}
- /* Save space: see if the result is identical to one of the args. */
- if (elt == TREE_TYPE (t1) && use1)
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && use2)
- return c_build_type_attribute_variant (t2, attributes);
+ /* If both are VLAs but not unspecified and we are in the
+ conditional operator, we create a conditional to select
+ the size of the active branch. */
+ bool use0 = cond && d1_variable && !c_type_unspecified_p (t1)
+ && d2_variable && !c_type_unspecified_p (t2);
+
+ tree td;
+ tree elt = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
+
+ if (!use0)
+ {
+ /* Save space: see if the result is identical to one of the args. */
+ if (elt == TREE_TYPE (t1) && use1)
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && use2)
+ return c_build_type_attribute_variant (t2, attributes);
+
+ if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t1, attributes);
+ if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
+ return c_build_type_attribute_variant (t2, attributes);
+
+ td = TYPE_DOMAIN (use1 ? t1 : t2);
+ }
+ else
+ {
+ /* Not used in C. */
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d1));
+ gcc_assert (size_zero_node == TYPE_MIN_VALUE (d2));
- if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t1, attributes);
- if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return c_build_type_attribute_variant (t2, attributes);
+ tree d = fold_build3_loc (UNKNOWN_LOCATION, COND_EXPR, sizetype,
+ cond, TYPE_MAX_VALUE (d1),
+ TYPE_MAX_VALUE (d2));
+
+ td = build_index_type (d);
+ }
/* Merge the element types, and have a size if either arg has
one. We may have qualifiers on the element types. To set
up TYPE_MAIN_VARIANT correctly, we need to form the
composite of the unqualified types and add the qualifiers
back at the end. */
- quals = TYPE_QUALS (strip_array_types (elt));
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
- t1 = c_build_array_type (unqual_elt, TYPE_DOMAIN (use1 ? t1 : t2));
+ int quals = TYPE_QUALS (strip_array_types (elt));
+ tree unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+ t1 = c_build_array_type (unqual_elt, td);
/* Check that a type which has a varying outermost dimension
got marked has having a variable size. */
@@ -819,7 +841,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
gcc_assert (DECL_NAME (a) == DECL_NAME (b));
gcc_checking_assert (!DECL_NAME (a) || comptypes (ta, tb));
- tree t = composite_type_internal (ta, tb, cache);
+ tree t = composite_type_internal (ta, tb, cond, cache);
tree f = build_decl (input_location, FIELD_DECL, DECL_NAME (a), t);
DECL_PACKED (f) = DECL_PACKED (a);
@@ -876,8 +898,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Function types: prefer the one that specified arg types.
If both do, merge the arg types. Also merge the return types. */
{
- tree valtype = composite_type_internal (TREE_TYPE (t1),
- TREE_TYPE (t2), cache);
+ tree valtype = composite_type_internal (TREE_TYPE (t1), TREE_TYPE (t2),
+ cond, cache);
tree p1 = TYPE_ARG_TYPES (t1);
tree p2 = TYPE_ARG_TYPES (t2);
int len;
@@ -956,7 +978,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
{
TREE_VALUE (n) = composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p2),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
@@ -979,14 +1001,14 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
TREE_VALUE (n)
= composite_type_internal (TREE_TYPE (memb),
TREE_VALUE (p1),
- cache);
+ cond, cache);
pedwarn (input_location, OPT_Wpedantic,
"function types not truly compatible in ISO C");
goto parm_done;
}
}
}
- TREE_VALUE (n) = composite_type_internal (mv1, mv2, cache);
+ TREE_VALUE (n) = composite_type_internal (mv1, mv2, cond, cache);
parm_done: ;
}
@@ -1001,18 +1023,25 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
}
tree
-composite_type (tree t1, tree t2)
+composite_type_cond (tree t1, tree t2, tree cond)
{
gcc_checking_assert (comptypes_check_for_composite (t1, t2));
struct composite_cache cache = { };
- tree n = composite_type_internal (t1, t2, &cache);
+ tree n = composite_type_internal (t1, t2, cond, &cache);
gcc_checking_assert (comptypes_check_for_composite (n, t1));
gcc_checking_assert (comptypes_check_for_composite (n, t2));
return n;
}
+
+tree
+composite_type (tree t1, tree t2)
+{
+ return composite_type_cond (t1, t2, NULL_TREE);
+}
+
/* Return the type of a conditional expression between pointers to
possibly differently qualified versions of compatible types.
@@ -1020,7 +1049,7 @@ composite_type (tree t1, tree t2)
true; if that isn't so, this may crash. */
static tree
-common_pointer_type (tree t1, tree t2)
+common_pointer_type (tree t1, tree t2, tree cond)
{
tree attributes;
unsigned target_quals;
@@ -1047,8 +1076,8 @@ common_pointer_type (tree t1, tree t2)
qualifiers of the two types' targets. */
tree pointed_to_1 = TREE_TYPE (t1);
tree pointed_to_2 = TREE_TYPE (t2);
- tree target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
- TYPE_MAIN_VARIANT (pointed_to_2));
+ tree target = composite_type_cond (TYPE_MAIN_VARIANT (pointed_to_1),
+ TYPE_MAIN_VARIANT (pointed_to_2), cond);
/* Strip array types to get correct qualifier for pointers to arrays */
quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
@@ -1970,6 +1999,9 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
ft2 = DECL_BIT_FIELD_TYPE (s2);
}
+ if (!ft1 || !ft2)
+ return false;
+
if (TREE_CODE (ft1) == ERROR_MARK || TREE_CODE (ft2) == ERROR_MARK)
return false;
@@ -2648,6 +2680,20 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
return exp;
}
+/* Wrapper for the overload above, same arguments but for tree rather than
+ c_expr. This is important for hardbools to decay to bools. */
+
+static inline tree
+convert_lvalue_to_rvalue (location_t loc, tree val,
+ bool convert_p, bool read_p, bool for_init = false)
+{
+ struct c_expr expr;
+ memset (&expr, 0, sizeof (expr));
+ expr.value = val;
+ expr = convert_lvalue_to_rvalue (loc, expr, convert_p, read_p, for_init);
+ return expr.value;
+}
+
/* EXP is an expression of integer type. Apply the integer promotions
to it and return the promoted value. */
@@ -4926,7 +4972,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
if (!addr_space_superset (as0, as1, &as_common))
gcc_unreachable ();
- common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
+ common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1), NULL_TREE);
op0 = convert (common_type, op0);
op1 = convert (common_type, op1);
}
@@ -5271,7 +5317,9 @@ cas_loop:
/* newval = old + val; */
if (rhs_type != rhs_semantic_type)
val = build1 (EXCESS_PRECISION_EXPR, nonatomic_rhs_semantic_type, val);
- rhs = build_binary_op (loc, modifycode, old, val, true);
+ rhs = build_binary_op (loc, modifycode,
+ convert_lvalue_to_rvalue (loc, old, true, true),
+ val, true);
if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
{
tree eptype = TREE_TYPE (rhs);
@@ -5727,7 +5775,48 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
goto return_build_unary_op;
}
- if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
+ tree true_res;
+ if (c_hardbool_type_attr (TREE_TYPE (arg), NULL, &true_res))
+ {
+ tree larg = stabilize_reference (arg);
+ tree sarg = save_expr (larg);
+ switch (code)
+ {
+ case PREINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case POSTINCREMENT_EXPR:
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, true_res);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ break;
+ case PREDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ rarg = convert (TREE_TYPE (sarg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, rarg);
+ }
+ break;
+ case POSTDECREMENT_EXPR:
+ {
+ tree rarg = convert_lvalue_to_rvalue (location, sarg,
+ true, true);
+ rarg = invert_truthvalue_loc (location, rarg);
+ tree iarg = convert (TREE_TYPE (larg), rarg);
+ val = build2 (MODIFY_EXPR, TREE_TYPE (larg), larg, iarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), val, sarg);
+ val = build2 (COMPOUND_EXPR, TREE_TYPE (larg), sarg, val);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ TREE_SIDE_EFFECTS (val) = 1;
+ }
+ else if (C_BOOLEAN_TYPE_P (TREE_TYPE (arg)))
val = boolean_increment (code, arg);
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
@@ -6380,7 +6469,10 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
addr_space_t as_common;
if (comp_target_types (colon_loc, type1, type2))
- result_type = common_pointer_type (type1, type2);
+ {
+ ifexp = save_expr (ifexp);
+ result_type = common_pointer_type (type1, type2, ifexp);
+ }
else if (null_pointer_constant_p (orig_op1))
result_type = type2;
else if (null_pointer_constant_p (orig_op2))
@@ -7337,8 +7429,10 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
clear_decl_read = true;
}
- newrhs = build_binary_op (location,
- modifycode, lhs, newrhs, true);
+ newrhs = build_binary_op (location, modifycode,
+ convert_lvalue_to_rvalue (location, lhs,
+ true, true),
+ newrhs, true);
if (clear_decl_read)
DECL_READ_P (lhs) = 0;
@@ -12730,11 +12824,9 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
}
else
{
- struct c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = input;
- expr = convert_lvalue_to_rvalue (loc, expr, true, false);
- input = c_fully_fold (expr.value, false, NULL);
+ input = c_fully_fold (convert_lvalue_to_rvalue (loc, input,
+ true, false),
+ false, NULL);
if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input)))
{
@@ -14390,7 +14482,7 @@ build_binary_op (location_t location, enum tree_code code,
Otherwise, the targets must be compatible
and both must be object or both incomplete. */
if (comp_target_types (location, type0, type1))
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
else if (!addr_space_superset (as0, as1, &as_common))
{
error_at (location, "comparison of pointers to "
@@ -14529,7 +14621,7 @@ build_binary_op (location_t location, enum tree_code code,
if (comp_target_types (location, type0, type1))
{
- result_type = common_pointer_type (type0, type1);
+ result_type = common_pointer_type (type0, type1, NULL_TREE);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
pedwarn_c99 (location, OPT_Wpedantic,
@@ -15356,12 +15448,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
/* If the array section is pointer based and the pointer
itself is _Atomic qualified, we need to atomically load
the pointer. */
- c_expr expr;
- memset (&expr, 0, sizeof (expr));
- expr.value = ret;
- expr = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
- expr, false, false);
- ret = expr.value;
+ ret = convert_lvalue_to_rvalue (OMP_CLAUSE_LOCATION (c),
+ ret, false, false);
}
return ret;
}
@@ -16966,6 +17054,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
break;
}
+ /* FALLTHRU */
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
if (OMP_CLAUSE_ITERATORS (c)
&& c_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
{
@@ -16973,8 +17064,6 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
/* FALLTHRU */
- case OMP_CLAUSE_TO:
- case OMP_CLAUSE_FROM:
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
diff --git a/gcc/common.opt b/gcc/common.opt
index 70659fa..bf38f60 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1067,6 +1067,8 @@ Driver Undocumented
;
; 21: Fix noexcept lambda capture pruning.
; Fix C++20 layout of base with all explicitly defaulted constructors.
+; Fix mangling of class and array objects with implicitly
+; zero-initialized non-trailing subojects.
; Default in G++ 16.
;
; Additional positive integers will be assigned as new versions of
diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc
index da3cb9f..f2ede07 100644
--- a/gcc/common/config/riscv/riscv-common.cc
+++ b/gcc/common/config/riscv/riscv-common.cc
@@ -1758,6 +1758,11 @@ riscv_expand_arch (int argc,
{
gcc_assert (argc == 1);
location_t loc = UNKNOWN_LOCATION;
+
+ /* Filter out -march=unset, it will expand from -mcpu later. */
+ if (strcmp (argv[0], "unset") == 0)
+ return "";
+
/* Try to interpret the arch as CPU first. */
const char *arch_str = riscv_expand_arch_from_cpu (argc, argv);
if (!strlen (arch_str))
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 791f3b9..49af963 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2477,9 +2477,9 @@ constexpr wide_int_bitmask PTA_DIAMONDRAPIDS = PTA_GRANITERAPIDS_D
| PTA_MOVRS | PTA_AMX_MOVRS | PTA_USER_MSR;
constexpr wide_int_bitmask PTA_BDVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3
- | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4
- | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT
+ | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL
+ | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
constexpr wide_int_bitmask PTA_BDVER2 = PTA_BDVER1 | PTA_BMI | PTA_TBM
| PTA_F16C | PTA_FMA;
constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT
@@ -2487,13 +2487,13 @@ constexpr wide_int_bitmask PTA_BDVER3 = PTA_BDVER2 | PTA_XSAVEOPT
constexpr wide_int_bitmask PTA_BDVER4 = PTA_BDVER3 | PTA_AVX2 | PTA_BMI2
| PTA_RDRND | PTA_MOVBE | PTA_MWAITX;
-constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2
- | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2
- | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT
- | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE | PTA_MWAITX | PTA_ADX | PTA_RDSEED
- | PTA_CLZERO | PTA_CLFLUSHOPT | PTA_XSAVEC | PTA_XSAVES | PTA_SHA | PTA_LZCNT
- | PTA_POPCNT;
+constexpr wide_int_bitmask PTA_ZNVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_POPCNT | PTA_LZCNT
+ | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL
+ | PTA_AVX | PTA_AVX2 | PTA_BMI | PTA_BMI2 | PTA_F16C | PTA_FMA | PTA_PRFCHW
+ | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE
+ | PTA_MWAITX | PTA_ADX | PTA_RDSEED | PTA_CLZERO | PTA_CLFLUSHOPT
+ | PTA_XSAVEC | PTA_XSAVES | PTA_SHA;
constexpr wide_int_bitmask PTA_ZNVER2 = PTA_ZNVER1 | PTA_CLWB | PTA_RDPID
| PTA_WBNOINVD;
constexpr wide_int_bitmask PTA_ZNVER3 = PTA_ZNVER2 | PTA_VAES | PTA_VPCLMULQDQ
@@ -2506,19 +2506,19 @@ constexpr wide_int_bitmask PTA_ZNVER5 = PTA_ZNVER4 | PTA_AVXVNNI
| PTA_MOVDIRI | PTA_MOVDIR64B | PTA_AVX512VP2INTERSECT | PTA_PREFETCHI;
constexpr wide_int_bitmask PTA_BTVER1 = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_ABM | PTA_CX16
- | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
+ | PTA_SSE2 | PTA_SSE3 | PTA_SSSE3 | PTA_SSE4A | PTA_LZCNT | PTA_POPCNT
+ | PTA_ABM | PTA_CX16 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE;
constexpr wide_int_bitmask PTA_BTVER2 = PTA_BTVER1 | PTA_SSE4_1 | PTA_SSE4_2
| PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_BMI | PTA_F16C | PTA_MOVBE
| PTA_XSAVEOPT;
constexpr wide_int_bitmask PTA_LUJIAZUI = PTA_64BIT | PTA_MMX | PTA_SSE
- | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1
- | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI | PTA_BMI2 | PTA_PRFCHW
- | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE
- | PTA_ADX | PTA_RDSEED | PTA_POPCNT;
+ | PTA_SSE2 | PTA_SSE3 | PTA_CX16 | PTA_LZCNT | PTA_POPCNT | PTA_ABM
+ | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_BMI
+ | PTA_BMI2 | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE
+ | PTA_RDRND | PTA_MOVBE | PTA_ADX | PTA_RDSEED;
constexpr wide_int_bitmask PTA_YONGFENG = PTA_LUJIAZUI | PTA_AVX | PTA_AVX2
- | PTA_F16C | PTA_FMA | PTA_SHA | PTA_LZCNT;
+ | PTA_F16C | PTA_FMA | PTA_SHA;
#ifndef GENERATOR_FILE
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 2b0dd66..6686f10 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -18298,17 +18298,17 @@
(any_rotate:SWI
(match_operand:SWI 1 "const_int_operand")
(subreg:QI
- (and
- (match_operand 2 "int248_register_operand")
- (match_operand 3 "const_int_operand")) 0)))]
+ (match_operator 4 "and_operator"
+ [(match_operand 2 "int248_register_operand")
+ (match_operand 3 "const_int_operand")]) 0)))]
"(INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode) - 1))
== GET_MODE_BITSIZE (<MODE>mode) - 1"
- [(set (match_dup 4) (match_dup 1))
+ [(set (match_dup 5) (match_dup 1))
(set (match_dup 0)
- (any_rotate:SWI (match_dup 4)
+ (any_rotate:SWI (match_dup 5)
(subreg:QI
- (and:SI (match_dup 2) (match_dup 3)) 0)))]
- "operands[4] = gen_reg_rtx (<MODE>mode);")
+ (match_op_dup 4 [(match_dup 2) (match_dup 3)]) 0)))]
+ "operands[5] = gen_reg_rtx (<MODE>mode);")
(define_insn_and_split "*<insn><mode>3_mask_1"
[(set (match_operand:SWI 0 "nonimmediate_operand")
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 0f31090..175798c 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -1714,10 +1714,14 @@
(define_predicate "div_operator"
(match_code "div"))
-;; Return true if this is a and, ior or xor operation.
+;; Return true if this is an and, ior or xor operation.
(define_predicate "logic_operator"
(match_code "and,ior,xor"))
+;; Return true if this is an and operation.
+(define_predicate "and_operator"
+ (match_code "and"))
+
;; Return true if this is a plus, minus, and, ior or xor operation.
(define_predicate "plusminuslogic_operator"
(match_code "plus,minus,and,ior,xor"))
diff --git a/gcc/config/riscv/arch-canonicalize b/gcc/config/riscv/arch-canonicalize
index 34dad45..5d24f5ed 100755
--- a/gcc/config/riscv/arch-canonicalize
+++ b/gcc/config/riscv/arch-canonicalize
@@ -20,77 +20,314 @@
# along with GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
-# TODO: Extract riscv_subset_t from riscv-common.cc and make it can be compiled
-# standalone to replace this script, that also prevents us implementing
-# that twice and keep sync again and again.
-
from __future__ import print_function
import sys
import argparse
import collections
import itertools
+import re
+import os
from functools import reduce
SUPPORTED_ISA_SPEC = ["2.2", "20190608", "20191213"]
CANONICAL_ORDER = "imafdqlcbkjtpvnh"
LONG_EXT_PREFIXES = ['z', 's', 'h', 'x']
+def parse_define_riscv_ext(content):
+ """Parse DEFINE_RISCV_EXT macros using position-based parsing."""
+ extensions = []
+
+ # Find all DEFINE_RISCV_EXT blocks
+ pattern = r'DEFINE_RISCV_EXT\s*\('
+ matches = []
+
+ pos = 0
+ while True:
+ match = re.search(pattern, content[pos:])
+ if not match:
+ break
+
+ start_pos = pos + match.start()
+ paren_count = 0
+ current_pos = pos + match.end() - 1 # Start at the opening parenthesis
+
+ # Find the matching closing parenthesis
+ while current_pos < len(content):
+ if content[current_pos] == '(':
+ paren_count += 1
+ elif content[current_pos] == ')':
+ paren_count -= 1
+ if paren_count == 0:
+ break
+ current_pos += 1
+
+ if paren_count == 0:
+ # Extract the content inside parentheses
+ macro_content = content[pos + match.end():current_pos]
+ ext_data = parse_macro_arguments(macro_content)
+ if ext_data:
+ extensions.append(ext_data)
+
+ pos = current_pos + 1
+
+ return extensions
+
+def parse_macro_arguments(macro_content):
+ """Parse the arguments of a DEFINE_RISCV_EXT macro."""
+ # Remove comments /* ... */
+ cleaned_content = re.sub(r'/\*[^*]*\*/', '', macro_content)
+
+ # Split arguments by comma, but respect nested structures
+ args = []
+ current_arg = ""
+ paren_count = 0
+ brace_count = 0
+ in_string = False
+ escape_next = False
+
+ for char in cleaned_content:
+ if escape_next:
+ current_arg += char
+ escape_next = False
+ continue
+
+ if char == '\\':
+ escape_next = True
+ current_arg += char
+ continue
+
+ if char == '"' and not escape_next:
+ in_string = not in_string
+ current_arg += char
+ continue
+
+ if in_string:
+ current_arg += char
+ continue
+
+ if char == '(':
+ paren_count += 1
+ elif char == ')':
+ paren_count -= 1
+ elif char == '{':
+ brace_count += 1
+ elif char == '}':
+ brace_count -= 1
+ elif char == ',' and paren_count == 0 and brace_count == 0:
+ args.append(current_arg.strip())
+ current_arg = ""
+ continue
+
+ current_arg += char
+
+ # Add the last argument
+ if current_arg.strip():
+ args.append(current_arg.strip())
+
+ # We need at least 6 arguments to get DEP_EXTS (position 5)
+ if len(args) < 6:
+ return None
+
+ ext_name = args[0].strip()
+ dep_exts_arg = args[5].strip() # DEP_EXTS is at position 5
+
+ # Parse dependency extensions from the DEP_EXTS argument
+ deps = parse_dep_exts(dep_exts_arg)
+
+ return {
+ 'name': ext_name,
+ 'dep_exts': deps
+ }
+
+def parse_dep_exts(dep_exts_str):
+ """Parse the DEP_EXTS argument to extract dependency list with conditions."""
+ # Remove outer parentheses if present
+ dep_exts_str = dep_exts_str.strip()
+ if dep_exts_str.startswith('(') and dep_exts_str.endswith(')'):
+ dep_exts_str = dep_exts_str[1:-1].strip()
+
+ # Remove outer braces if present
+ if dep_exts_str.startswith('{') and dep_exts_str.endswith('}'):
+ dep_exts_str = dep_exts_str[1:-1].strip()
+
+ if not dep_exts_str:
+ return []
+
+ deps = []
+
+ # First, find and process conditional dependencies
+ conditional_pattern = r'\{\s*"([^"]+)"\s*,\s*(\[.*?\]\s*\([^)]*\)\s*->\s*bool.*?)\}'
+ conditional_matches = []
+
+ for match in re.finditer(conditional_pattern, dep_exts_str, re.DOTALL):
+ ext_name = match.group(1)
+ condition_code = match.group(2)
+ deps.append({'ext': ext_name, 'type': 'conditional', 'condition': condition_code})
+ conditional_matches.append((match.start(), match.end()))
+
+ # Remove conditional dependency blocks from the string
+ remaining_str = dep_exts_str
+ for start, end in reversed(conditional_matches): # Reverse order to maintain indices
+ remaining_str = remaining_str[:start] + remaining_str[end:]
+
+ # Now handle simple quoted strings in the remaining text
+ for match in re.finditer(r'"([^"]+)"', remaining_str):
+ deps.append({'ext': match.group(1), 'type': 'simple'})
+
+ # Remove duplicates while preserving order
+ seen = set()
+ unique_deps = []
+ for dep in deps:
+ key = (dep['ext'], dep['type'])
+ if key not in seen:
+ seen.add(key)
+ unique_deps.append(dep)
+
+ return unique_deps
+
+def evaluate_conditional_dependency(ext, dep, xlen, current_exts):
+ """Evaluate whether a conditional dependency should be included."""
+ ext_name = dep['ext']
+ condition = dep['condition']
+ # Parse the condition based on known patterns
+ if ext_name == 'zcf' and ext in ['zca', 'c', 'zce']:
+ # zcf depends on RV32 and F extension
+ return xlen == 32 and 'f' in current_exts
+ elif ext_name == 'zcd' and ext in ['zca', 'c']:
+ # zcd depends on D extension
+ return 'd' in current_exts
+ elif ext_name == 'c' and ext in ['zca']:
+ # Special case for zca -> c conditional dependency
+ if xlen == 32:
+ if 'd' in current_exts:
+ return 'zcf' in current_exts and 'zcd' in current_exts
+ elif 'f' in current_exts:
+ return 'zcf' in current_exts
+ else:
+ return True
+ elif xlen == 64:
+ if 'd' in current_exts:
+ return 'zcd' in current_exts
+ else:
+ return True
+ return False
+ else:
+ # Report error for unhandled conditional dependencies
+ import sys
+ print(f"ERROR: Unhandled conditional dependency: '{ext_name}' with condition:", file=sys.stderr)
+ print(f" Condition code: {condition[:100]}...", file=sys.stderr)
+ print(f" Current context: xlen={xlen}, exts={sorted(current_exts)}", file=sys.stderr)
+ # For now, return False to be safe
+ return False
+
+def resolve_dependencies(arch_parts, xlen):
+ """Resolve all dependencies including conditional ones."""
+ current_exts = set(arch_parts)
+ implied_deps = set()
+
+ # Keep resolving until no new dependencies are found
+ changed = True
+ while changed:
+ changed = False
+ new_deps = set()
+
+ for ext in current_exts | implied_deps:
+ if ext in IMPLIED_EXT:
+ for dep in IMPLIED_EXT[ext]:
+ if dep['type'] == 'simple':
+ if dep['ext'] not in current_exts and dep['ext'] not in implied_deps:
+ new_deps.add(dep['ext'])
+ changed = True
+ elif dep['type'] == 'conditional':
+ should_include = evaluate_conditional_dependency(ext, dep, xlen, current_exts | implied_deps)
+ if should_include:
+ if dep['ext'] not in current_exts and dep['ext'] not in implied_deps:
+ new_deps.add(dep['ext'])
+ changed = True
+
+ implied_deps.update(new_deps)
+
+ return implied_deps
+
+def parse_def_file(file_path, script_dir, processed_files=None, collect_all=False):
+ """Parse a single .def file and recursively process #include directives."""
+ if processed_files is None:
+ processed_files = set()
+
+ # Avoid infinite recursion
+ if file_path in processed_files:
+ return ({}, set()) if collect_all else {}
+ processed_files.add(file_path)
+
+ implied_ext = {}
+ all_extensions = set() if collect_all else None
+
+ if not os.path.exists(file_path):
+ return (implied_ext, all_extensions) if collect_all else implied_ext
+
+ with open(file_path, 'r') as f:
+ content = f.read()
+
+ # Process #include directives first
+ include_pattern = r'#include\s+"([^"]+)"'
+ includes = re.findall(include_pattern, content)
+
+ for include_file in includes:
+ include_path = os.path.join(script_dir, include_file)
+ if collect_all:
+ included_ext, included_all = parse_def_file(include_path, script_dir, processed_files, collect_all)
+ implied_ext.update(included_ext)
+ all_extensions.update(included_all)
+ else:
+ included_ext = parse_def_file(include_path, script_dir, processed_files, collect_all)
+ implied_ext.update(included_ext)
+
+ # Parse DEFINE_RISCV_EXT blocks using position-based parsing
+ parsed_exts = parse_define_riscv_ext(content)
+
+ for ext_data in parsed_exts:
+ ext_name = ext_data['name']
+ deps = ext_data['dep_exts']
+
+ if collect_all:
+ all_extensions.add(ext_name)
+
+ if deps:
+ implied_ext[ext_name] = deps
+
+ return (implied_ext, all_extensions) if collect_all else implied_ext
+
+def parse_def_files():
+ """Parse RISC-V extension definition files starting from riscv-ext.def."""
+ # Get directory containing this script
+ try:
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ except NameError:
+ # When __file__ is not defined (e.g., interactive mode)
+ script_dir = os.getcwd()
+
+ # Start with the main definition file
+ main_def_file = os.path.join(script_dir, 'riscv-ext.def')
+ return parse_def_file(main_def_file, script_dir)
+
+def get_all_extensions():
+ """Get all supported extensions and their implied extensions."""
+ # Get directory containing this script
+ try:
+ script_dir = os.path.dirname(os.path.abspath(__file__))
+ except NameError:
+ # When __file__ is not defined (e.g., interactive mode)
+ script_dir = os.getcwd()
+
+ # Start with the main definition file
+ main_def_file = os.path.join(script_dir, 'riscv-ext.def')
+ return parse_def_file(main_def_file, script_dir, collect_all=True)
+
#
# IMPLIED_EXT(ext) -> implied extension list.
+# This is loaded dynamically from .def files
#
-IMPLIED_EXT = {
- "d" : ["f", "zicsr"],
-
- "a" : ["zaamo", "zalrsc"],
- "zabha" : ["zaamo"],
- "zacas" : ["zaamo"],
-
- "f" : ["zicsr"],
- "b" : ["zba", "zbb", "zbs"],
- "zdinx" : ["zfinx", "zicsr"],
- "zfinx" : ["zicsr"],
- "zhinx" : ["zhinxmin", "zfinx", "zicsr"],
- "zhinxmin" : ["zfinx", "zicsr"],
-
- "zk" : ["zkn", "zkr", "zkt"],
- "zkn" : ["zbkb", "zbkc", "zbkx", "zkne", "zknd", "zknh"],
- "zks" : ["zbkb", "zbkc", "zbkx", "zksed", "zksh"],
-
- "v" : ["zvl128b", "zve64d"],
- "zve32x" : ["zvl32b"],
- "zve64x" : ["zve32x", "zvl64b"],
- "zve32f" : ["f", "zve32x"],
- "zve64f" : ["f", "zve32f", "zve64x"],
- "zve64d" : ["d", "zve64f"],
-
- "zvl64b" : ["zvl32b"],
- "zvl128b" : ["zvl64b"],
- "zvl256b" : ["zvl128b"],
- "zvl512b" : ["zvl256b"],
- "zvl1024b" : ["zvl512b"],
- "zvl2048b" : ["zvl1024b"],
- "zvl4096b" : ["zvl2048b"],
- "zvl8192b" : ["zvl4096b"],
- "zvl16384b" : ["zvl8192b"],
- "zvl32768b" : ["zvl16384b"],
- "zvl65536b" : ["zvl32768b"],
-
- "zvkn" : ["zvkned", "zvknhb", "zvkb", "zvkt"],
- "zvknc" : ["zvkn", "zvbc"],
- "zvkng" : ["zvkn", "zvkg"],
- "zvks" : ["zvksed", "zvksh", "zvkb", "zvkt"],
- "zvksc" : ["zvks", "zvbc"],
- "zvksg" : ["zvks", "zvkg"],
- "zvbb" : ["zvkb"],
- "zvbc" : ["zve64x"],
- "zvkb" : ["zve32x"],
- "zvkg" : ["zve32x"],
- "zvkned" : ["zve32x"],
- "zvknha" : ["zve32x"],
- "zvknhb" : ["zve64x"],
- "zvksed" : ["zve32x"],
- "zvksh" : ["zve32x"],
-}
+IMPLIED_EXT = parse_def_files()
def arch_canonicalize(arch, isa_spec):
# TODO: Support extension version.
@@ -123,21 +360,31 @@ def arch_canonicalize(arch, isa_spec):
long_exts += extra_long_ext
#
- # Handle implied extensions.
+ # Handle implied extensions using new conditional logic.
#
- any_change = True
- while any_change:
- any_change = False
- for ext in std_exts + long_exts:
- if ext in IMPLIED_EXT:
- implied_exts = IMPLIED_EXT[ext]
- for implied_ext in implied_exts:
- if implied_ext == 'zicsr' and is_isa_spec_2p2:
- continue
+ # Extract xlen from architecture string
+ # TODO: We should support profile here.
+ if arch.startswith('rv32'):
+ xlen = 32
+ elif arch.startswith('rv64'):
+ xlen = 64
+ else:
+ raise Exception("Unsupported prefix `%s`" % arch)
- if implied_ext not in std_exts + long_exts:
- long_exts.append(implied_ext)
- any_change = True
+ # Get all current extensions
+ current_exts = std_exts + long_exts
+
+ # Resolve dependencies
+ implied_deps = resolve_dependencies(current_exts, xlen)
+
+ # Filter out zicsr for ISA spec 2.2
+ if is_isa_spec_2p2:
+ implied_deps.discard('zicsr')
+
+ # Add implied dependencies to long_exts
+ for dep in implied_deps:
+ if dep not in current_exts:
+ long_exts.append(dep)
# Single letter extension might appear in the long_exts list,
# because we just append extensions list to the arch string.
@@ -179,17 +426,171 @@ def arch_canonicalize(arch, isa_spec):
return new_arch
-if len(sys.argv) < 2:
- print ("Usage: %s <arch_str> [<arch_str>*]" % sys.argv)
- sys.exit(1)
+def dump_all_extensions():
+ """Dump all extensions and their implied extensions."""
+ implied_ext, all_extensions = get_all_extensions()
-parser = argparse.ArgumentParser()
-parser.add_argument('-misa-spec', type=str,
- default='20191213',
- choices=SUPPORTED_ISA_SPEC)
-parser.add_argument('arch_strs', nargs=argparse.REMAINDER)
+ print("All supported RISC-V extensions:")
+ print("=" * 60)
-args = parser.parse_args()
+ if not all_extensions:
+ print("No extensions found.")
+ return
-for arch in args.arch_strs:
- print (arch_canonicalize(arch, args.misa_spec))
+ # Sort all extensions for consistent output
+ sorted_all = sorted(all_extensions)
+
+ # Print all extensions with their dependencies (if any)
+ for ext_name in sorted_all:
+ if ext_name in implied_ext:
+ deps = implied_ext[ext_name]
+ dep_strs = []
+ for dep in deps:
+ if dep['type'] == 'simple':
+ dep_strs.append(dep['ext'])
+ else:
+ dep_strs.append(f"{dep['ext']}*") # Mark conditional deps with *
+ print(f"{ext_name:15} -> {', '.join(dep_strs)}")
+ else:
+ print(f"{ext_name:15} -> (no dependencies)")
+
+ print(f"\nTotal extensions: {len(all_extensions)}")
+ print(f"Extensions with dependencies: {len(implied_ext)}")
+ print(f"Extensions without dependencies: {len(all_extensions) - len(implied_ext)}")
+
+def run_unit_tests():
+ """Run unit tests using pytest dynamically imported."""
+ try:
+ import pytest
+ except ImportError:
+ print("Error: pytest is required for running unit tests.")
+ print("Please install pytest: pip install pytest")
+ return 1
+
+ # Define test functions
+ def test_basic_arch_parsing():
+ """Test basic architecture string parsing."""
+ result = arch_canonicalize("rv64i", "20191213")
+ assert result == "rv64i"
+
+ def test_simple_extensions():
+ """Test simple extension handling."""
+ result = arch_canonicalize("rv64im", "20191213")
+ assert "zmmul" in result
+
+ def test_implied_extensions():
+ """Test implied extension resolution."""
+ result = arch_canonicalize("rv64imaf", "20191213")
+ assert "zicsr" in result
+
+ def test_conditional_dependencies():
+ """Test conditional dependency evaluation."""
+ # Test RV32 with F extension should include zcf when c is present
+ result = arch_canonicalize("rv32ifc", "20191213")
+ parts = result.split("_")
+ if "c" in parts:
+ assert "zca" in parts
+ if "f" in parts:
+ assert "zcf" in parts
+
+ def test_parse_dep_exts():
+ """Test dependency parsing function."""
+ # Test simple dependency
+ deps = parse_dep_exts('{"ext1", "ext2"}')
+ assert len(deps) == 2
+ assert deps[0]['ext'] == 'ext1'
+ assert deps[0]['type'] == 'simple'
+
+ def test_evaluate_conditional_dependency():
+ """Test conditional dependency evaluation."""
+ # Test zcf condition for RV32 with F
+ dep = {'ext': 'zcf', 'type': 'conditional', 'condition': 'test'}
+ result = evaluate_conditional_dependency('zce', dep, 32, {'f'})
+ assert result == True
+
+ # Test zcf condition for RV64 with F (should be False)
+ result = evaluate_conditional_dependency('zce', dep, 64, {'f'})
+ assert result == False
+
+ def test_parse_define_riscv_ext():
+ """Test DEFINE_RISCV_EXT parsing."""
+ content = '''
+ DEFINE_RISCV_EXT(
+ /* NAME */ test,
+ /* UPPERCASE_NAME */ TEST,
+ /* FULL_NAME */ "Test extension",
+ /* DESC */ "",
+ /* URL */ ,
+ /* DEP_EXTS */ ({"dep1", "dep2"}),
+ /* SUPPORTED_VERSIONS */ ({{1, 0}}),
+ /* FLAG_GROUP */ test,
+ /* BITMASK_GROUP_ID */ 0,
+ /* BITMASK_BIT_POSITION*/ 0,
+ /* EXTRA_EXTENSION_FLAGS */ 0)
+ '''
+
+ extensions = parse_define_riscv_ext(content)
+ assert len(extensions) == 1
+ assert extensions[0]['name'] == 'test'
+ assert len(extensions[0]['dep_exts']) == 2
+
+ # Collect test functions
+ test_functions = [
+ test_basic_arch_parsing,
+ test_simple_extensions,
+ test_implied_extensions,
+ test_conditional_dependencies,
+ test_parse_dep_exts,
+ test_evaluate_conditional_dependency,
+ test_parse_define_riscv_ext
+ ]
+
+ # Run tests manually first, then optionally with pytest
+ print("Running unit tests...")
+
+ passed = 0
+ failed = 0
+
+ for i, test_func in enumerate(test_functions):
+ try:
+ print(f" Running {test_func.__name__}...", end=" ")
+ test_func()
+ print("PASSED")
+ passed += 1
+ except Exception as e:
+ print(f"FAILED: {e}")
+ failed += 1
+
+ print(f"\nTest Summary: {passed} passed, {failed} failed")
+
+ if failed == 0:
+ print("\nAll tests passed!")
+ return 0
+ else:
+ print(f"\n{failed} test(s) failed!")
+ return 1
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser()
+ parser.add_argument('-misa-spec', type=str,
+ default='20191213',
+ choices=SUPPORTED_ISA_SPEC)
+ parser.add_argument('--dump-all', action='store_true',
+ help='Dump all extensions and their implied extensions')
+ parser.add_argument('--selftest', action='store_true',
+ help='Run unit tests using pytest')
+ parser.add_argument('arch_strs', nargs='*',
+ help='Architecture strings to canonicalize')
+
+ args = parser.parse_args()
+
+ if args.dump_all:
+ dump_all_extensions()
+ elif args.selftest:
+ sys.exit(run_unit_tests())
+ elif args.arch_strs:
+ for arch in args.arch_strs:
+ print (arch_canonicalize(arch, args.misa_spec))
+ else:
+ parser.print_help()
+ sys.exit(1)
diff --git a/gcc/config/riscv/riscv.h b/gcc/config/riscv/riscv.h
index 45fa521..29342d8 100644
--- a/gcc/config/riscv/riscv.h
+++ b/gcc/config/riscv/riscv.h
@@ -71,7 +71,7 @@ extern const char *riscv_arch_help (int argc, const char **argv);
{"tune", "%{!mtune=*:" \
" %{!mcpu=*:-mtune=%(VALUE)}" \
" %{mcpu=*:-mtune=%:riscv_default_mtune(%* %(VALUE))}}" }, \
- {"arch", "%{!march=*:" \
+ {"arch", "%{!march=*|march=unset:" \
" %{!mcpu=*:-march=%(VALUE)}" \
" %{mcpu=*:%:riscv_expand_arch_from_cpu(%* %(VALUE))}}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
@@ -111,13 +111,19 @@ extern const char *riscv_arch_help (int argc, const char **argv);
%(subtarget_asm_spec)" \
ASM_MISA_SPEC
+/* Drop all -march=* options before -march=unset. */
+#define ARCH_UNSET_CLEANUP_SPECS \
+ "%{march=unset:%<march=*} " \
+
#undef DRIVER_SELF_SPECS
#define DRIVER_SELF_SPECS \
+ARCH_UNSET_CLEANUP_SPECS \
"%{march=help:%:riscv_arch_help()} " \
"%{print-supported-extensions:%:riscv_arch_help()} " \
"%{-print-supported-extensions:%:riscv_arch_help()} " \
"%{march=*:%:riscv_expand_arch(%*)} " \
-"%{!march=*:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} "
+"%{!march=*|march=unset:%{mcpu=*:%:riscv_expand_arch_from_cpu(%*)}} " \
+"%{march=unset:%{!mcpu=*:%eAt least one valid -mcpu option must be given after -march=unset}} "
#define LOCAL_LABEL_PREFIX "."
#define USER_LABEL_PREFIX ""
diff --git a/gcc/configure b/gcc/configure
index bacdd29..cab9c75 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -872,7 +872,6 @@ c_strict_warn
strict_warn
c_loose_warn
loose_warn
-aliasing_flags
CPP
EGREP
GREP
@@ -7126,45 +7125,6 @@ $as_echo "#define HAVE_SWAP_IN_UTILITY 1" >>confdefs.h
fi
-# Check whether compiler is affected by placement new aliasing bug (PR 29286).
-# If the host compiler is affected by the bug, and we build with optimization
-# enabled (which happens e.g. when cross-compiling), the pool allocator may
-# get miscompiled. Use -fno-strict-aliasing to work around this problem.
-# Since there is no reliable feature check for the presence of this bug,
-# we simply use a GCC version number check. (This should never trigger for
-# stages 2 or 3 of a native bootstrap.)
-aliasing_flags=
-if test "$GCC" = yes; then
- saved_CXXFLAGS="$CXXFLAGS"
-
- # The following test compilation will succeed if and only if $CXX accepts
- # -fno-strict-aliasing *and* is older than GCC 4.3.
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX is affected by placement new aliasing bug" >&5
-$as_echo_n "checking whether $CXX is affected by placement new aliasing bug... " >&6; }
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-
-#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#error compiler not affected by placement new aliasing bug
-#endif
-
-_ACEOF
-if ac_fn_cxx_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }; aliasing_flags='-fno-strict-aliasing'
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
- CXXFLAGS="$saved_CXXFLAGS"
-fi
-
-
-
-
# ---------------------
# Warnings and checking
# ---------------------
@@ -21522,7 +21482,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21525 "configure"
+#line 21485 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -21628,7 +21588,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 21631 "configure"
+#line 21591 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 2c43b38..ac1f0e9 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -563,35 +563,6 @@ if test $ac_cv_std_swap_in_utility = yes; then
[Define if <utility> defines std::swap.])
fi
-# Check whether compiler is affected by placement new aliasing bug (PR 29286).
-# If the host compiler is affected by the bug, and we build with optimization
-# enabled (which happens e.g. when cross-compiling), the pool allocator may
-# get miscompiled. Use -fno-strict-aliasing to work around this problem.
-# Since there is no reliable feature check for the presence of this bug,
-# we simply use a GCC version number check. (This should never trigger for
-# stages 2 or 3 of a native bootstrap.)
-aliasing_flags=
-if test "$GCC" = yes; then
- saved_CXXFLAGS="$CXXFLAGS"
-
- # The following test compilation will succeed if and only if $CXX accepts
- # -fno-strict-aliasing *and* is older than GCC 4.3.
- CXXFLAGS="$CXXFLAGS -fno-strict-aliasing"
- AC_MSG_CHECKING([whether $CXX is affected by placement new aliasing bug])
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([
-#if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
-#error compiler not affected by placement new aliasing bug
-#endif
-])],
- [AC_MSG_RESULT([yes]); aliasing_flags='-fno-strict-aliasing'],
- [AC_MSG_RESULT([no])])
-
- CXXFLAGS="$saved_CXXFLAGS"
-fi
-AC_SUBST(aliasing_flags)
-
-
-
# ---------------------
# Warnings and checking
# ---------------------
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cb4ff09..8e9b8ea 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,28 @@
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * mangle.cc (write_expression): Write out implicit non-trailing
+ zeroes of a CONSTRUCTOR when the ABI version is at least 21.
+
+2025-08-06 Jason Merrill <jason@redhat.com>
+
+ * constexpr.cc (cxx_eval_indirect_ref): Improve diagnostic.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * parser.cc (cp_parser_omp_clause_from_to): Parse 'iterator' modifier.
+ * semantics.cc (finish_omp_clauses): Finish iterators for to/from
+ clauses.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * parser.cc (cp_parser_omp_clause_map): Parse 'iterator' modifier.
+ * semantics.cc (finish_omp_clauses): Finish iterators. Apply
+ iterators to generated clauses.
+
2025-08-05 Jason Merrill <jason@redhat.com>
PR c++/121068
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 65b91ec..b8ac454 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -7179,10 +7179,23 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
(TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
/* DR 1188 says we don't have to deal with this. */
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
- "accessing value of %qE through a %qT glvalue in a "
- "constant expression", build_fold_indirect_ref (sub),
- TREE_TYPE (t));
+ {
+ auto_diagnostic_group d;
+ error_at (cp_expr_loc_or_input_loc (t),
+ "accessing value of %qT object through a %qT "
+ "glvalue in a constant expression",
+ TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t));
+ tree ob = build_fold_indirect_ref (sub);
+ if (DECL_P (ob))
+ {
+ if (DECL_ARTIFICIAL (ob))
+ inform (DECL_SOURCE_LOCATION (ob),
+ "%qT object created here", TREE_TYPE (ob));
+ else
+ inform (DECL_SOURCE_LOCATION (ob),
+ "%q#D declared here", ob);
+ }
+ }
*non_constant_p = true;
return t;
}
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 13d5ded..fd69099 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -3745,11 +3745,59 @@ write_expression (tree expr)
|| !zero_init_expr_p (ce->value))
last_nonzero = i;
+ tree prev_field = NULL_TREE;
if (undigested || last_nonzero != UINT_MAX)
for (HOST_WIDE_INT i = 0; vec_safe_iterate (elts, i, &ce); ++i)
{
if (i > last_nonzero)
break;
+ if (!undigested && !CONSTRUCTOR_NO_CLEARING (expr)
+ && (TREE_CODE (etype) == RECORD_TYPE
+ || TREE_CODE (etype) == ARRAY_TYPE))
+ {
+ /* Write out any implicit non-trailing zeros
+ (which we neglected to do before v21). */
+ if (TREE_CODE (etype) == RECORD_TYPE)
+ {
+ tree field;
+ if (i == 0)
+ field = first_field (etype);
+ else
+ field = DECL_CHAIN (prev_field);
+ for (;;)
+ {
+ field = next_subobject_field (field);
+ if (field == ce->index)
+ break;
+ if (abi_check (21))
+ write_expression (build_zero_cst
+ (TREE_TYPE (field)));
+ field = DECL_CHAIN (field);
+ }
+ }
+ else if (TREE_CODE (etype) == ARRAY_TYPE)
+ {
+ unsigned HOST_WIDE_INT j;
+ if (i == 0)
+ j = 0;
+ else
+ j = 1 + tree_to_uhwi (prev_field);
+ unsigned HOST_WIDE_INT k;
+ if (TREE_CODE (ce->index) == RANGE_EXPR)
+ k = tree_to_uhwi (TREE_OPERAND (ce->index, 0));
+ else
+ k = tree_to_uhwi (ce->index);
+ tree zero = NULL_TREE;
+ for (; j < k; ++j)
+ if (abi_check (21))
+ {
+ if (!zero)
+ zero = build_zero_cst (TREE_TYPE (etype));
+ write_expression (zero);
+ }
+ }
+ }
+
if (!undigested && TREE_CODE (etype) == UNION_TYPE)
{
/* Express the active member as a designator. */
@@ -3794,6 +3842,9 @@ write_expression (tree expr)
else
for (unsigned j = 0; j < reps; ++j)
write_expression (ce->value);
+ prev_field = ce->index;
+ if (prev_field && TREE_CODE (prev_field) == RANGE_EXPR)
+ prev_field = TREE_OPERAND (prev_field, 1);
}
}
else
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 759442ad..a8c54c7 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -42636,8 +42636,11 @@ cp_parser_omp_clause_doacross (cp_parser *parser, tree list, location_t loc)
to ( variable-list )
OpenMP 5.1:
- from ( [present :] variable-list )
- to ( [present :] variable-list ) */
+ from ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+ to ( [motion-modifier[,] [motion-modifier[,]...]:] variable-list )
+
+ motion-modifier:
+ present | iterator (iterators-definition) */
static tree
cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
@@ -42646,23 +42649,113 @@ cp_parser_omp_clause_from_to (cp_parser *parser, enum omp_clause_code kind,
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return list;
- bool present = false;
- cp_token *token = cp_lexer_peek_token (parser->lexer);
+ int pos = 1;
+ int colon_pos = 0;
+ int iterator_length = 0;
- if (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->u.value), "present") == 0
- && cp_lexer_nth_token_is (parser->lexer, 2, CPP_COLON))
+ while (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_NAME)
{
- present = true;
- cp_lexer_consume_token (parser->lexer);
- cp_lexer_consume_token (parser->lexer);
+ const char *identifier =
+ IDENTIFIER_POINTER (cp_lexer_peek_nth_token (parser->lexer,
+ pos)->u.value);
+ if (cp_lexer_nth_token_is (parser->lexer, pos + 1, CPP_OPEN_PAREN))
+ {
+ int n = cp_parser_skip_balanced_tokens (parser, pos + 1);
+ if (n != pos + 1)
+ {
+ if (strcmp (identifier, "iterator") == 0)
+ iterator_length = n - pos;
+ pos = n - 1;
+ }
+ }
+ if (cp_lexer_peek_nth_token (parser->lexer, pos + 1)->type == CPP_COMMA)
+ pos += 2;
+ else
+ pos++;
+ if (cp_lexer_peek_nth_token (parser->lexer, pos)->type == CPP_COLON)
+ {
+ colon_pos = pos;
+ break;
+ }
}
+ bool present = false;
+ tree iterators = NULL_TREE;
+
+ for (int pos = 1; pos < colon_pos; ++pos)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_COMMA)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ continue;
+ }
+ const char *p = IDENTIFIER_POINTER (token->u.value);
+ if (strcmp ("present", p) == 0)
+ {
+ if (present)
+ {
+ cp_parser_error (parser, "too many %<present%> modifiers");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ present = true;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else if (strcmp ("iterator", p) == 0)
+ {
+ if (iterators)
+ {
+ cp_parser_error (parser, "too many %<iterator%> modifiers");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ begin_scope (sk_omp, NULL);
+ iterators = cp_parser_omp_iterators (parser);
+ pos += iterator_length - 1;
+ }
+
+ else
+ {
+ error_at (token->location,
+ "%qs clause with modifier other than %<iterator%> "
+ "or %<present%>",
+ kind == OMP_CLAUSE_TO ? "to" : "from");
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+ return list;
+ }
+ }
+
+ if (colon_pos)
+ cp_parser_require (parser, CPP_COLON, RT_COLON);
+
tree nl = cp_parser_omp_var_list_no_open (parser, kind, list, NULL, true);
if (present)
for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
OMP_CLAUSE_MOTION_PRESENT (c) = 1;
+ if (iterators)
+ {
+ tree block = poplevel (1, 1, 0);
+ if (iterators == error_mark_node)
+ iterators = NULL_TREE;
+ else
+ TREE_VEC_ELT (iterators, 5) = block;
+ }
+
+ if (iterators)
+ for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ITERATORS (c) = iterators;
+
return nl;
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 256ac3f..0c7788d 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -9007,6 +9007,9 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
break;
}
+ /* FALLTHRU */
+ case OMP_CLAUSE_TO:
+ case OMP_CLAUSE_FROM:
if (OMP_CLAUSE_ITERATORS (c)
&& cp_omp_finish_iterators (OMP_CLAUSE_ITERATORS (c)))
{
@@ -9014,8 +9017,6 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
}
/* FALLTHRU */
- case OMP_CLAUSE_TO:
- case OMP_CLAUSE_FROM:
case OMP_CLAUSE__CACHE_:
{
using namespace omp_addr_tokenizer;
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index 4fe6418..1217b5d 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,7 @@
+2025-08-06 Sam James <sam@gentoo.org>
+
+ * Make-lang.in (ALL_DFLAGS): Don't use ALIASING_FLAGS.
+
2025-07-25 David Malcolm <dmalcolm@redhat.com>
* d-diagnostic.cc: Likewise.
diff --git a/gcc/d/Make-lang.in b/gcc/d/Make-lang.in
index 2d444c9..0ddd524 100644
--- a/gcc/d/Make-lang.in
+++ b/gcc/d/Make-lang.in
@@ -61,7 +61,7 @@ WARN_DFLAGS = -Wall -Wdeprecated
NOEXCEPTION_DFLAGS = $(filter-out -fno-rtti, $(NOEXCEPTION_FLAGS))
ALL_DFLAGS = $(DFLAGS-$@) $(GDCFLAGS) -fversion=IN_GCC $(CHECKING_DFLAGS) \
- $(PICFLAG) $(ALIASING_FLAGS) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \
+ $(PICFLAG) $(NOEXCEPTION_DFLAGS) $(COVERAGE_FLAGS) \
$(WARN_DFLAGS)
DCOMPILE.base = $(GDC) -c $(ALL_DFLAGS) -o $@
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 64c1217..7423224 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -393,7 +393,7 @@ Note binutils 2.35 or newer is required for LTO to work correctly
with GNU libtool that includes doing a bootstrap with LTO enabled.
@item gzip version 1.2.4 (or later) or
-@itemx bzip2 version 1.0.2 (or later)
+@itemx xz version 5.0 (or later)
Necessary to uncompress GCC @command{tar} files when source code is
obtained via HTTPS mirror sites.
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 105a60d..00468a7 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -3016,8 +3016,9 @@ Version 20, which first appeared in G++ 15, fixes manglings of lambdas
in static data member initializers.
Version 21, which first appeared in G++ 16, fixes unnecessary captures
-in noexcept lambdas (c++/119764) and layout of a base class
-with all explicitly defaulted constructors (c++/120012).
+in noexcept lambdas (c++/119764), layout of a base class with all explicitly
+defaulted constructors (c++/120012), and mangling of class and array
+objects with implicitly zero-initialized non-trailing subobjects (c++/121231).
See also @option{-Wabi}.
@@ -31336,7 +31337,7 @@ The default is @option{-misa-spec=20191213} unless GCC has been configured
with @option{--with-isa-spec=} specifying a different default version.
@opindex march
-@item -march=@var{ISA-string|Profiles|Profile_ISA-string}
+@item -march=@var{ISA-string|Profiles|Profile_ISA-string|help|unset}
Generate code for given RISC-V ISA or Profiles or a combination of them
(e.g.@: @samp{rv64im} @samp{rvi20u64} @samp{rvi20u64_zbb}). ISA strings and
Profiles must be lower-case. Examples include @samp{rv64i}, @samp{rv32g},
@@ -31347,6 +31348,12 @@ at the beginning of the option, then use underline connect ISA-string (e.g.@:
@option{help} (@option{-march=help}) is accepted to list all supported
extensions.
+@samp{-march=unset} causes the compiler to ignore any @samp{-march=@dots{}} options
+that appear earlier on the command line, behaving as if the option was never
+passed. This is useful for ensuring that the architecture is taken from the
+@samp{-mcpu} option, and it will result in an error if no @samp{-mcpu} option
+is given when @samp{-march=unset} is used.
+
The syntax of the ISA string is defined as follows:
@table @code
diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l
index e36ca5b..37e4eb0 100644
--- a/gcc/gengtype-lex.l
+++ b/gcc/gengtype-lex.l
@@ -21,17 +21,6 @@ along with GCC; see the file COPYING3. If not see
%option noinput
%{
-#ifdef HOST_GENERATOR_FILE
-#include "config.h"
-#define GENERATOR_FILE 1
-#else
-#include "bconfig.h"
-#endif
-#include "system.h"
-
-#define malloc xmalloc
-#define realloc xrealloc
-
#include "gengtype.h"
#define YY_DECL int yylex (const char **yylval)
diff --git a/gcc/gimple-lower-bitint.cc b/gcc/gimple-lower-bitint.cc
index 8fb7a60..1e434ce 100644
--- a/gcc/gimple-lower-bitint.cc
+++ b/gcc/gimple-lower-bitint.cc
@@ -76,7 +76,7 @@ enum bitint_prec_kind {
/* Caches to speed up bitint_precision_kind. */
static int small_max_prec, mid_min_prec, large_min_prec, huge_min_prec;
-static int limb_prec;
+static int limb_prec, abi_limb_prec;
static bool bitint_big_endian, bitint_extended;
/* Categorize _BitInt(PREC) as small, middle, large or huge. */
@@ -109,6 +109,9 @@ bitint_precision_kind (int prec)
large_min_prec = MAX_FIXED_MODE_SIZE + 1;
if (!limb_prec)
limb_prec = GET_MODE_PRECISION (limb_mode);
+ if (!abi_limb_prec)
+ abi_limb_prec
+ = GET_MODE_PRECISION (as_a <scalar_int_mode> (info.abi_limb_mode));
if (!huge_min_prec)
{
if (4 * limb_prec >= MAX_FIXED_MODE_SIZE)
@@ -429,7 +432,7 @@ struct bitint_large_huge
void insert_before (gimple *);
tree limb_access_type (tree, tree);
- tree limb_access (tree, tree, tree, bool);
+ tree limb_access (tree, tree, tree, bool, bool = false);
tree build_bit_field_ref (tree, tree, unsigned HOST_WIDE_INT,
unsigned HOST_WIDE_INT);
void if_then (gimple *, profile_probability, edge &, edge &);
@@ -610,11 +613,14 @@ bitint_large_huge::limb_access_type (tree type, tree idx)
TYPE. If WRITE_P is true, it will be a store, otherwise a read. */
tree
-bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p)
+bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p,
+ bool abi_load_p)
{
tree atype = (tree_fits_uhwi_p (idx)
? limb_access_type (type, idx) : m_limb_type);
- tree ltype = m_limb_type;
+
+ tree ltype = (bitint_extended && abi_load_p) ? atype : m_limb_type;
+
addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (var));
if (as != TYPE_ADDR_SPACE (ltype))
ltype = build_qualified_type (ltype, TYPE_QUALS (ltype)
@@ -651,12 +657,21 @@ bitint_large_huge::limb_access (tree type, tree var, tree idx, bool write_p)
{
unsigned HOST_WIDE_INT nelts
= CEIL (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (var))), limb_prec);
- tree atype = build_array_type_nelts (ltype, nelts);
+
+ /* Build the array type with m_limb_type from the right address
+ space. */
+ tree limb_type_a = m_limb_type;
+ if (as != TYPE_ADDR_SPACE (m_limb_type))
+ limb_type_a = build_qualified_type (m_limb_type,
+ TYPE_QUALS (m_limb_type)
+ | ENCODE_QUAL_ADDR_SPACE (as));
+
+ tree atype = build_array_type_nelts (limb_type_a, nelts);
var = build1 (VIEW_CONVERT_EXPR, atype, var);
}
ret = build4 (ARRAY_REF, ltype, var, idx, NULL_TREE, NULL_TREE);
}
- if (!write_p && !useless_type_conversion_p (atype, m_limb_type))
+ if (!write_p && !useless_type_conversion_p (atype, ltype))
{
gimple *g = gimple_build_assign (make_ssa_name (m_limb_type), ret);
insert_before (g);
@@ -1964,6 +1979,7 @@ bitint_large_huge::handle_load (gimple *stmt, tree idx)
tree rhs1 = gimple_assign_rhs1 (stmt);
tree rhs_type = TREE_TYPE (rhs1);
bool eh = stmt_ends_bb_p (stmt);
+ bool load_bitfield_p = false;
edge eh_edge = NULL;
gimple *g;
@@ -1987,12 +2003,18 @@ bitint_large_huge::handle_load (gimple *stmt, tree idx)
if (!bitint_big_endian
&& DECL_OFFSET_ALIGN (fld) >= TYPE_ALIGN (TREE_TYPE (rhs1))
&& (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (fld)) % limb_prec) == 0)
- goto normal_load;
+ {
+ load_bitfield_p = true;
+ goto normal_load;
+ }
/* Even if DECL_FIELD_BIT_OFFSET (fld) is a multiple of BITS_PER_UNIT,
handle it normally for now. */
if (!bitint_big_endian
&& (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (fld)) % BITS_PER_UNIT) == 0)
- goto normal_load;
+ {
+ load_bitfield_p = true;
+ goto normal_load;
+ }
tree repr = DECL_BIT_FIELD_REPRESENTATIVE (fld);
poly_int64 bitoffset;
poly_uint64 field_offset, repr_offset;
@@ -2241,7 +2263,7 @@ normal_load:
/* Use write_p = true for loads with EH edges to make
sure limb_access doesn't add a cast as separate
statement after it. */
- rhs1 = limb_access (rhs_type, rhs1, idx, eh);
+ rhs1 = limb_access (rhs_type, rhs1, idx, eh, !load_bitfield_p);
tree ret = make_ssa_name (TREE_TYPE (rhs1));
g = gimple_build_assign (ret, rhs1);
insert_before (g);
@@ -2373,7 +2395,7 @@ range_to_prec (tree op, gimple *stmt)
from that precision, if it is negative, the operand is sign-extended
from -*PREC. If PREC_STORED is NULL, it is the toplevel call,
otherwise *PREC_STORED is prec from the innermost call without
- range optimizations. */
+ range optimizations (0 for uninitialized SSA_NAME). */
tree
bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
@@ -2481,7 +2503,7 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
*prec = TYPE_UNSIGNED (TREE_TYPE (op)) ? limb_prec : -limb_prec;
precs = *prec;
if (prec_stored)
- *prec_stored = precs;
+ *prec_stored = 0;
tree var = create_tmp_var (m_limb_type);
TREE_ADDRESSABLE (var) = 1;
ret = build_fold_addr_expr (var);
@@ -2510,6 +2532,13 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
int prec_stored_val = 0;
ret = handle_operand_addr (rhs1, g, &prec_stored_val, prec);
precs = prec_stored_val;
+ if (prec_stored)
+ *prec_stored = prec_stored_val;
+ if (precs == 0)
+ {
+ gcc_assert (*prec == limb_prec || *prec == -limb_prec);
+ precs = *prec;
+ }
if (TYPE_PRECISION (lhs_type) > TYPE_PRECISION (rhs_type))
{
if (TYPE_UNSIGNED (lhs_type)
@@ -2518,7 +2547,9 @@ bitint_large_huge::handle_operand_addr (tree op, gimple *stmt,
}
else
{
- if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type))
+ if (prec_stored_val == 0)
+ /* Non-widening cast of uninitialized value. */;
+ else if (*prec > 0 && *prec < TYPE_PRECISION (lhs_type))
;
else if (TYPE_UNSIGNED (lhs_type))
{
@@ -3150,6 +3181,17 @@ bitint_large_huge::lower_mergeable_stmt (gimple *stmt, tree_code &cmp_code,
{
tree l = limb_access (nlhs ? NULL_TREE : lhs_type,
nlhs ? nlhs : lhs, idx, true);
+
+ if (bitint_extended
+ && sext
+ && TYPE_UNSIGNED (lhs_type)
+ && tree_fits_uhwi_p (idx)
+ && !nlhs)
+ {
+ rhs1 = add_cast (limb_access_type (lhs_type, idx), rhs1);
+ rhs1 = add_cast (TREE_TYPE (l), rhs1);
+ }
+
g = gimple_build_assign (l, rhs1);
}
insert_before (g);
@@ -6669,7 +6711,7 @@ static unsigned int
gimple_lower_bitint (void)
{
small_max_prec = mid_min_prec = large_min_prec = huge_min_prec = 0;
- limb_prec = 0;
+ limb_prec = abi_limb_prec = 0;
bitint_big_endian = false;
unsigned int i;
@@ -7631,7 +7673,20 @@ gimple_lower_bitint (void)
from smaller number. */
min_prec = prec;
else
- min_prec = CEIL (min_prec, limb_prec) * limb_prec;
+ {
+ min_prec = CEIL (min_prec, limb_prec) * limb_prec;
+ if (min_prec > (unsigned) limb_prec
+ && abi_limb_prec > limb_prec)
+ {
+ /* For targets with ABI limb precision higher than
+ limb precision round to ABI limb precision,
+ otherwise c can contain padding bits. */
+ min_prec
+ = CEIL (min_prec, abi_limb_prec) * abi_limb_prec;
+ if (min_prec > prec - rem - 2 * limb_prec)
+ min_prec = prec;
+ }
+ }
if (min_prec == 0)
c = NULL_TREE;
else if (min_prec == prec)
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index e178519..ca1fa21 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -9966,9 +9966,11 @@ remove_unused_omp_iterator_vars (tree *list_p)
if (t == NULL_TREE)
{
need_new_iterators = true;
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
- && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
- || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM))
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_TO
+ || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FROM))
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)
warning_at (OMP_CLAUSE_LOCATION (c), OPT_Wopenmp,
"iterator variable %qE not used in clause "
"expression", DECL_NAME (var));
@@ -13582,7 +13584,8 @@ omp_instantiate_implicit_mappers (splay_tree_node n, void *data)
static void
gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
enum omp_region_type region_type,
- enum tree_code code)
+ enum tree_code code,
+ gimple_seq *loops_seq_p = NULL)
{
using namespace omp_addr_tokenizer;
struct gimplify_omp_ctx *ctx, *outer_ctx;
@@ -14353,23 +14356,24 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
if (OMP_CLAUSE_SIZE (c) == NULL_TREE)
OMP_CLAUSE_SIZE (c) = DECL_P (decl) ? DECL_SIZE_UNIT (decl)
: TYPE_SIZE_UNIT (TREE_TYPE (decl));
- if (gimplify_expr (&OMP_CLAUSE_SIZE (c), pre_p,
- NULL, is_gimple_val, fb_rvalue) == GS_ERROR)
+ gimple_seq *seq_p;
+ seq_p = enter_omp_iterator_loop_context (c, loops_seq_p, pre_p);
+ if (gimplify_expr (&OMP_CLAUSE_SIZE (c), seq_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
{
remove = true;
+ exit_omp_iterator_loop_context (c);
break;
}
if (!DECL_P (decl))
{
- if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p,
- NULL, is_gimple_lvalue, fb_lvalue)
- == GS_ERROR)
- {
- remove = true;
- break;
- }
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), seq_p, NULL,
+ is_gimple_lvalue, fb_lvalue) == GS_ERROR)
+ remove = true;
+ exit_omp_iterator_loop_context (c);
break;
}
+ exit_omp_iterator_loop_context (c);
goto do_notice;
case OMP_CLAUSE__MAPPER_BINDING_:
@@ -18728,7 +18732,7 @@ gimplify_omp_workshare (tree *expr_p, gimple_seq *pre_p)
if ((ort & ORT_ACC) == 0)
in_omp_construct = false;
gimplify_scan_omp_clauses (&OMP_CLAUSES (expr), pre_p, ort,
- TREE_CODE (expr));
+ TREE_CODE (expr), &iterator_loops_seq);
if (TREE_CODE (expr) == OMP_TARGET)
optimize_target_teams (expr, pre_p);
if ((ort & (ORT_TARGET | ORT_TARGET_DATA)) != 0
@@ -18885,10 +18889,16 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
default:
gcc_unreachable ();
}
+
+ gimple_seq iterator_loops_seq = NULL;
+ remove_unused_omp_iterator_vars (&OMP_STANDALONE_CLAUSES (expr));
+ build_omp_iterators_loops (&OMP_STANDALONE_CLAUSES (expr),
+ &iterator_loops_seq);
+
gimplify_scan_omp_clauses (&OMP_STANDALONE_CLAUSES (expr), pre_p,
- ort, TREE_CODE (expr));
+ ort, TREE_CODE (expr), &iterator_loops_seq);
gimplify_adjust_omp_clauses (pre_p, NULL, &OMP_STANDALONE_CLAUSES (expr),
- TREE_CODE (expr));
+ TREE_CODE (expr), &iterator_loops_seq);
if (TREE_CODE (expr) == OACC_UPDATE
&& omp_find_clause (OMP_STANDALONE_CLAUSES (expr),
OMP_CLAUSE_IF_PRESENT))
@@ -18952,7 +18962,8 @@ gimplify_omp_target_update (tree *expr_p, gimple_seq *pre_p)
gcc_unreachable ();
}
}
- stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr));
+ stmt = gimple_build_omp_target (NULL, kind, OMP_STANDALONE_CLAUSES (expr),
+ iterator_loops_seq);
gimplify_seq_add_stmt (pre_p, stmt);
*expr_p = NULL_TREE;
diff --git a/gcc/match.pd b/gcc/match.pd
index 82e6e29..06a4a91 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -5508,16 +5508,31 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(convert @0)))
/* Strip inner integral conversions that do not change precision or size, or
- zero-extend while keeping the same size (for bool-to-char). */
+ zero-extend while keeping the same size (for bool-to-char).
+ However, keep this conversion if the result is an extended _BitInt,
+ since it may rely on this conversion to extend properly. */
+
(simplify
(view_convert (convert@0 @1))
+ (with {
+ bool extended_bitint = false;
+ if (BITINT_TYPE_P (TREE_TYPE (@0)))
+ {
+ struct bitint_info info;
+ extended_bitint
+ = targetm.c.bitint_type_info (TYPE_PRECISION (TREE_TYPE (@0)),
+ &info);
+ extended_bitint = extended_bitint && info.extended;
+ }
+ }
(if ((INTEGRAL_TYPE_P (TREE_TYPE (@0)) || POINTER_TYPE_P (TREE_TYPE (@0)))
&& (INTEGRAL_TYPE_P (TREE_TYPE (@1)) || POINTER_TYPE_P (TREE_TYPE (@1)))
+ && !extended_bitint
&& TYPE_SIZE (TREE_TYPE (@0)) == TYPE_SIZE (TREE_TYPE (@1))
&& (TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1))
|| (TYPE_PRECISION (TREE_TYPE (@0)) > TYPE_PRECISION (TREE_TYPE (@1))
&& TYPE_UNSIGNED (TREE_TYPE (@1)))))
- (view_convert @1)))
+ (view_convert @1))))
/* Simplify a view-converted empty or single-element constructor. */
(simplify
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1ac6084..df2c843 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,112 @@
+2025-08-06 Sam James <sam@gentoo.org>
+
+ * g++.dg/cpp26/constexpr-new3.C: Escape '[' and ']'.
+
+2025-08-06 Alexandre Oliva <oliva@adacore.com>
+
+ * gcc.dg/torture/hardbool-ai.c: New.
+ * gcc.dg/torture/hardbool-vi.c: New.
+ * gcc.dg/torture/hardbool.c: Handle NO_BITFIELDS.
+ (add1, preinc, postinc, sub1, predec, postdec): New.
+ (main): Exercise them.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/108931
+ * gcc.dg/vla-tert-1.c: New test.
+
+2025-08-06 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/121231
+ PR c++/119688
+ PR c++/94511
+ * g++.dg/abi/mangle82.C: New test.
+ * g++.dg/cpp2a/nontype-class73.C: New test.
+
+2025-08-06 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp26/constexpr-new3.C: Tweak diagnostic.
+
+2025-08-06 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/vect-gather-1.c: Adjust to hide N.
+
+2025-08-06 Tejas Belagod <tejas.belagod@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general/cops.c: Fix test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/torture/bitint-84.c: New test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/torture/bitint-83.c: New test.
+
+2025-08-06 Yang Yujie <yangyujie@loongson.cn>
+
+ * gcc.dg/bitintext.h (BEXTC1): Define. Convert the copied
+ object back to the original type before comparison.
+ (BEXTC): Use BEXTC1 for both the signed and the unsigned case.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121413
+ * gcc.dg/torture/bitint-85.c: New test.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/121127
+ * gcc.dg/bitint-125.c: New test.
+
+2025-08-06 Yuao Ma <c8ef@outlook.com>
+
+ * gfortran.dg/c_f_pointer_shape_tests_2.f03: Use the new driver.
+ * gfortran.dg/c_f_pointer_shape_tests_4.f03: Ditto.
+ * gfortran.dg/c_f_pointer_shape_tests_4_driver.c: Removed.
+ * gfortran.dg/c_f_pointer_shape_tests_2_driver.c: Renamed to ...
+ * gfortran.dg/c_f_pointer_shape_tests_driver.c: ... this; format
+ with gcc style.
+
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/120778
+ * c-c++-common/cpp/comment-ff-1.c: New test.
+ * c-c++-common/cpp/comment-vtab-1.c: New test.
+
+2025-08-06 Martin Uecker <uecker@tugraz.at>
+
+ PR c/121217
+ * gcc.dg/pr121217.c: New test.
+
+2025-08-06 Kito Cheng <kito.cheng@sifive.com>
+
+ * gcc.target/riscv/arch-unset-1.c: New test.
+ * gcc.target/riscv/arch-unset-2.c: New test.
+ * gcc.target/riscv/arch-unset-3.c: New test.
+ * gcc.target/riscv/arch-unset-4.c: New test.
+ * gcc.target/riscv/arch-unset-5.c: New test.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * c-c++-common/gomp/target-update-iterators-1.c: New.
+ * c-c++-common/gomp/target-update-iterators-2.c: New.
+ * c-c++-common/gomp/target-update-iterators-3.c: New.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * c-c++-common/gomp/map-6.c (foo): Amend expected error message.
+ * c-c++-common/gomp/target-map-iterators-1.c: New.
+ * c-c++-common/gomp/target-map-iterators-2.c: New.
+ * c-c++-common/gomp/target-map-iterators-3.c: New.
+ * c-c++-common/gomp/target-map-iterators-4.c: New.
+
+2025-08-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/121234
+ * gfortran.dg/pr121234.f90: New test.
+
2025-08-05 Jason Merrill <jason@redhat.com>
PR c++/121068
diff --git a/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c b/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c
new file mode 100644
index 0000000..0d071b1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/comment-ff-1.c
@@ -0,0 +1,12 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// Test that form-feed followed by non-whitespace
+// in line comments are accepted.
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wall -W" }
+
+//
+int a;
+//
+int b;
+// comment
+int c;
diff --git a/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c b/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c
new file mode 100644
index 0000000..03feb73
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/comment-vtab-1.c
@@ -0,0 +1,12 @@
+// C++26 P2843R3 - Preprocessing is never undefined
+// Test that vertical tab followed by non-whitespace
+// in line comments are accepted.
+// { dg-do compile }
+// { dg-options "-pedantic-errors -Wall -W" }
+
+//
+int a;
+//
+int b;
+// comment
+int c;
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c
new file mode 100644
index 0000000..53b22f0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-1.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+#define DIM1 17
+#define DIM2 39
+
+void f (int **x, float **y)
+{
+ #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1): x[i][:DIM2], y[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1), present: x[i][:DIM2])
+
+ #pragma omp target update to (iterator(i=0:DIM1), iterator(j=0:DIM2): x[i][j]) /* { dg-error "too many 'iterator' modifiers" } */
+ /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-1 } */
+
+ #pragma omp target update from (iterator(i=0:DIM1), something: x[i][j]) /* { dg-error "'from' clause with modifier other than 'iterator' or 'present'" } */
+ /* { dg-error "expected '\\)' before 'something'" "" { target c } .-1 } */
+ /* { dg-error "'#pragma omp target update' must contain at least one 'from' or 'to' clauses" "" { target *-*-* } .-2 } */
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c
new file mode 100644
index 0000000..dbd43e0
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-2.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+void f (int *x, float *y, double *z)
+{
+ #pragma omp target update to(iterator(i=0:10): x) /* { dg-warning "iterator variable 'i' not used in clause expression" }*/
+ ;
+
+ #pragma omp target update from(iterator(i2=0:10, j2=0:20): x[i2]) /* { dg-warning "iterator variable 'j2' not used in clause expression" }*/
+ ;
+
+ #pragma omp target update to(iterator(i3=0:10, j3=0:20, k3=0:30): x[i3+j3], y[j3+k3], z[k3+i3])
+ /* { dg-warning "iterator variable 'i3' not used in clause expression" "" { target *-*-* } .-1 } */
+ /* { dg-warning "iterator variable 'j3' not used in clause expression" "" { target *-*-* } .-2 } */
+ /* { dg-warning "iterator variable 'k3' not used in clause expression" "" { target *-*-* } .-3 } */
+ ;
+}
+
+/* { dg-final { scan-tree-dump "update to\\\(x " "gimple" } } */
+/* { dg-final { scan-tree-dump "update from\\\(iterator\\\(int i2=0:10:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int k3=0:30:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int j3=0:20:1, int k3=0:30:1, loop_label=" "gimple" } } */
+/* { dg-final { scan-tree-dump "to\\\(iterator\\\(int i3=0:10:1, int j3=0:20:1, loop_label=" "gimple" } } */
diff --git a/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c
new file mode 100644
index 0000000..ef55216
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/target-update-iterators-3.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp -fdump-tree-gimple" } */
+
+#define DIM1 10
+#define DIM2 20
+#define DIM3 30
+
+void f (int ***x, float ***y, double **z)
+{
+ #pragma omp target update to (iterator(i=0:DIM1, j=0:DIM2): x[i][j][:DIM3], y[i][j][:DIM3])
+ #pragma omp target update from (iterator(i=0:DIM1): z[i][:DIM2])
+}
+
+/* { dg-final { scan-tree-dump-times "if \\(i <= 9\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "if \\(j <= 19\\) goto <D\.\[0-9\]+>; else goto <D\.\[0-9\]+>;" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "to\\(iterator\\(int i=0:10:1, int j=0:20:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "from\\(iterator\\(int i=0:10:1, loop_label=<D\.\[0-9\]+>, elems=omp_iter_data\.\[0-9\]+, index=D\.\[0-9\]+\\):\\*D\.\[0-9\]+" 1 "gimple" } } */
diff --git a/gcc/testsuite/g++.dg/abi/mangle82.C b/gcc/testsuite/g++.dg/abi/mangle82.C
new file mode 100644
index 0000000..39dd581
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle82.C
@@ -0,0 +1,85 @@
+// Test mangling of C++20 class NTTP objects with implicitly zeroed
+// non-trailing subojects.
+// PR c++/121231
+// { dg-do compile { target c++20 } }
+
+struct A {
+ int x, y, z;
+
+ static constexpr A make(int x, int y, int z) {
+ A a{};
+ if (x != 0)
+ a.x = x;
+ if (y != 0)
+ a.y = y;
+ if (z != 0)
+ a.z = z;
+ return a;
+ }
+};
+
+struct B : A {
+ int w;
+
+ static constexpr B make(int x, int y, int z, int w) {
+ B b{};
+ if (x != 0 || y != 0 || z != 0)
+ static_cast<A&>(b) = A::make(x, y, z);
+ if (w != 0)
+ b.w = w;
+ return b;
+ }
+};
+
+struct C {
+ int xyz[3];
+
+ static constexpr C make(int x, int y, int z) {
+ C c{};
+ if (x != 0)
+ c.xyz[0] = x;
+ if (y != 0)
+ c.xyz[1] = y;
+ if (z != 0)
+ c.xyz[2] = z;
+ return c;
+ }
+};
+
+template<int N, A a> void f();
+template<int N, B b> void g();
+template<int N, C c> void h();
+
+int main() {
+ f<0, A::make(0, 0, 1)>(); // void f<0, A{0, 0, 1}>()
+ f<1, A::make(0, 1, 0)>(); // void f<1, A{0, 1}>()
+ f<2, A::make(0, 0, 0)>(); // void f<2, A{}>()
+ f<3, A::make(1, 0, 1)>(); // void f<3, A{1, 0, 1}>()
+
+ g<0, B::make(0, 0, 0, 1)>(); // void g<0, B{A{}, 1}>()
+ g<1, B::make(0, 0, 1, 0)>(); // void g<1, B{A{0, 0, 1}}>()
+ g<2, B::make(0, 1, 0, 0)>(); // void g<2, B{A{0, 1}}>()
+ g<3, B::make(0, 0, 0, 0)>(); // void g<3, B{}>()
+ g<4, B::make(1, 0, 1, 0)>(); // void g<4, B{A{1, 0, 1}}>()
+
+ h<0, C::make(0, 0, 1)>(); // void h<0, C{int [3]{0, 0, 1}}>()
+ h<1, C::make(0, 1, 0)>(); // void h<1, C{int [3]{0, 1}}>()
+ h<2, C::make(0, 0, 0)>(); // void h<2, C{}>()
+ h<3, C::make(1, 0, 1)>(); // void h<3, C{int [3]{1, 0, 1}}>()
+}
+
+// { dg-final { scan-assembler "_Z1fILi0EXtl1ALi0ELi0ELi1EEEEvv" } }
+// { dg-final { scan-assembler "_Z1fILi1EXtl1ALi0ELi1EEEEvv" } }
+// { dg-final { scan-assembler "_Z1fILi2EXtl1AEEEvv" } }
+// { dg-final { scan-assembler "_Z1fILi3EXtl1ALi1ELi0ELi1EEEEvv" } }
+
+// { dg-final { scan-assembler "_Z1gILi0EXtl1Btl1AELi1EEEEvv" } }
+// { dg-final { scan-assembler "_Z1gILi1EXtl1Btl1ALi0ELi0ELi1EEEEEvv" } }
+// { dg-final { scan-assembler "_Z1gILi2EXtl1Btl1ALi0ELi1EEEEEvv" } }
+// { dg-final { scan-assembler "_Z1gILi3EXtl1BEEEvv" } }
+// { dg-final { scan-assembler "_Z1gILi4EXtl1Btl1ALi1ELi0ELi1EEEEEvv" } }
+
+// { dg-final { scan-assembler "_Z1hILi0EXtl1CtlA3_iLi0ELi0ELi1EEEEEvv" } }
+// { dg-final { scan-assembler "_Z1hILi1EXtl1CtlA3_iLi0ELi1EEEEEvv" } }
+// { dg-final { scan-assembler "_Z1hILi2EXtl1CEEEvv" } }
+// { dg-final { scan-assembler "_Z1hILi3EXtl1CtlA3_iLi1ELi0ELi1EEEEEvv" } }
diff --git a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
index 6a06a6e..c79060f 100644
--- a/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
+++ b/gcc/testsuite/g++.dg/cpp26/constexpr-new3.C
@@ -37,7 +37,7 @@ baz ()
{
std::allocator<int> a;
auto b = a.allocate (2);
- new (b) long (42); // { dg-error "accessing value of 'heap ' through a 'long int' glvalue in a constant expression" }
+ new (b) long (42); // { dg-error "accessing value of 'int \\\[2\\\]' object through a 'long int' glvalue in a constant expression" }
a.deallocate (b, 2);
return true;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C
new file mode 100644
index 0000000..7f27cad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class73.C
@@ -0,0 +1,30 @@
+// PR c++/119688
+// { dg-do compile { target c++20 } }
+
+template<int N>
+struct builder {
+ bool value[256]{};
+ constexpr builder(char const (&s)[N]) {
+ for(int i = 0 ; i < N; ++i)
+ value[static_cast<unsigned char>(s[i])] = true;
+ }
+};
+
+template<builder A>
+constexpr auto operator""_ar() {
+ return A.value;
+}
+
+constexpr auto first = "ab"_ar;
+static_assert( first['a']);
+static_assert( first['b']);
+static_assert(!first['c']);
+static_assert(!first['d']);
+static_assert(!first['z']);
+
+constexpr auto second = "cd"_ar;
+static_assert(!second['a']);
+static_assert(!second['b']);
+static_assert(!second['z']);
+static_assert( second['c']);
+static_assert( second['d']);
diff --git a/gcc/testsuite/gcc.dg/bitint-125.c b/gcc/testsuite/gcc.dg/bitint-125.c
new file mode 100644
index 0000000..5ef0e32
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/bitint-125.c
@@ -0,0 +1,15 @@
+/* PR tree-optimization/121127 */
+/* { dg-do compile { target bitint } } */
+/* { dg-options "-O2 -w" } */
+
+#if __BITINT_MAXWIDTH__ >= 576
+_BitInt(575)
+foo (void)
+{
+ _BitInt(576) d;
+ _BitInt(575) e = d * 42wb;
+ return e;
+}
+#else
+int i;
+#endif
diff --git a/gcc/testsuite/gcc.dg/bitintext.h b/gcc/testsuite/gcc.dg/bitintext.h
index d5f2689d..f61cf9a 100644
--- a/gcc/testsuite/gcc.dg/bitintext.h
+++ b/gcc/testsuite/gcc.dg/bitintext.h
@@ -25,22 +25,20 @@ do_copy (void *p, const void *q, __SIZE_TYPE__ r)
/* Macro to test whether (on targets where psABI requires it) _BitInt
with padding bits have those filled with sign or zero extension. */
#if defined(__s390x__) || defined(__arm__) || defined(__loongarch__)
+#define BEXTC1(x, uns) \
+ do { \
+ uns _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
+ do_copy (&__x, &(x), sizeof (__x)); \
+ if (__x != (typeof (x)) __x) \
+ __builtin_abort (); \
+ } while (0)
+
#define BEXTC(x) \
- do { \
- if ((typeof (x)) -1 < 0) \
- { \
- _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
- do_copy (&__x, &(x), sizeof (__x)); \
- if (__x != (x)) \
- __builtin_abort (); \
- } \
- else \
- { \
- unsigned _BitInt(PROMOTED_SIZE (x) * __CHAR_BIT__) __x; \
- do_copy (&__x, &(x), sizeof (__x)); \
- if (__x != (x)) \
- __builtin_abort (); \
- } \
+ do { \
+ if ((typeof (x)) -1 < 0) \
+ BEXTC1 ((x), signed); \
+ else \
+ BEXTC1 ((x), unsigned); \
} while (0)
#else
#define BEXTC(x) do { (void) (x); } while (0)
diff --git a/gcc/testsuite/gcc.dg/pr121217.c b/gcc/testsuite/gcc.dg/pr121217.c
new file mode 100644
index 0000000..313f1e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr121217.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu17" } */
+
+typedef union{
+ char *nordic_ref;
+ unsigned long long int bit_number;
+ enum PinMode mode : 2; /* { dg-warning "narrower" } */
+ /* { dg-error "field 'mode'" "" { target *-*-* } .-1 } */
+ unsigned char value;
+ } s; typedef struct{
+ union{
+ char *nordic_ref;
+ unsigned long long int bit_number;
+ enum PinMode mode : 2; /* { dg-warning "narrower" } */
+ /* { dg-error "field 'mode'" "" { target *-*-* } .-1 } */
+ unsigned char value;
+ } s;
+} /* { dg-error "expected identifier" } */
+
diff --git a/gcc/testsuite/gcc.dg/torture/bitint-83.c b/gcc/testsuite/gcc.dg/torture/bitint-83.c
new file mode 100644
index 0000000..8a9df44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bitint-83.c
@@ -0,0 +1,48 @@
+/* Derived from a test in gcc.dg/torture/bitint-16.c */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#include "../bitintext.h"
+
+#define BASIC_TESTS \
+ TEST(8) \
+ TEST(16) \
+ TEST(32)
+
+#if __BITINT_MAXWIDTH__ >= 519
+#define ALL_TESTS \
+ BASIC_TESTS \
+ TEST(64) \
+ TEST(128) \
+ TEST(256) \
+ TEST(512)
+#else
+#define ALL_TESTS BASIC_TESTS
+#endif
+
+#define TEST(N) \
+void \
+test##N (unsigned _BitInt(N + 7) *t, _BitInt(N) x) \
+{ \
+ *t = -x; \
+}
+ALL_TESTS
+#undef TEST
+
+volatile int y = 0;
+
+int
+main (void)
+{
+#define TEST(N) \
+ { \
+ unsigned _BitInt(N + 7) t; \
+ _BitInt(N) x = y + N; \
+ test##N (&t, x); \
+ BEXTC (t); \
+ }
+ ALL_TESTS
+#undef TEST
+}
diff --git a/gcc/testsuite/gcc.dg/torture/bitint-84.c b/gcc/testsuite/gcc.dg/torture/bitint-84.c
new file mode 100644
index 0000000..b3ecbef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bitint-84.c
@@ -0,0 +1,18 @@
+/* A simple variant of gcc.dg/torture/bitint-64.c */
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#include "../bitintext.h"
+
+enum E : char { E22 = 22 } e = E22;
+
+int
+main ()
+{
+ _Atomic _BitInt (5) b = 0;
+ b += e;
+ BEXTC (b);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/bitint-85.c b/gcc/testsuite/gcc.dg/torture/bitint-85.c
new file mode 100644
index 0000000..43eb6ff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/bitint-85.c
@@ -0,0 +1,34 @@
+/* { dg-do run { target bitint } } */
+/* { dg-options "-std=c23 -pedantic-errors" } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */
+/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */
+
+#if __BITINT_MAXWIDTH__ >= 1024
+constexpr _BitInt(1024) d = -541140097068598424394740839221562143161511518875518765552323978870598341733206554363735813878577506997168480201818027232521wb;
+int c;
+
+static inline void
+foo (_BitInt(1024) b, _BitInt(1024) *r)
+{
+ if (c)
+ b = 0;
+ *r = b;
+}
+
+[[gnu::noipa]] void
+bar (_BitInt(1024) y)
+{
+ if (y != d)
+ __builtin_abort ();
+}
+#endif
+
+int
+main ()
+{
+#if __BITINT_MAXWIDTH__ >= 1024
+ _BitInt(1024) x;
+ foo (d, &x);
+ bar (x);
+#endif
+}
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-ai.c b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c
new file mode 100644
index 0000000..97569a6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/hardbool-ai.c
@@ -0,0 +1,7 @@
+/* { dg-do run } */
+
+#define basetype _Atomic int
+
+#define NO_BITFIELDS 1
+
+#include "hardbool.c"
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool-vi.c b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c
new file mode 100644
index 0000000..898d395
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/hardbool-vi.c
@@ -0,0 +1,5 @@
+/* { dg-do run } */
+
+#define basetype volatile int
+
+#include "hardbool.c"
diff --git a/gcc/testsuite/gcc.dg/torture/hardbool.c b/gcc/testsuite/gcc.dg/torture/hardbool.c
index 0168495..ed0c598 100644
--- a/gcc/testsuite/gcc.dg/torture/hardbool.c
+++ b/gcc/testsuite/gcc.dg/torture/hardbool.c
@@ -21,8 +21,12 @@ typedef unsigned char __attribute__ ((__hardbool__ (1, 0))) zbool;
struct hs {
hbool a[2];
+#ifndef NO_BITFIELDS
hbool x:2;
hbool y:5;
+#else
+ hbool x, y;
+#endif
zbool z:1;
};
@@ -57,6 +61,30 @@ int ghs(hbool s) {
int t = (hbool)2;
+hbool add1(hbool *s) {
+ return *s += 1;
+}
+
+hbool preinc(hbool *s) {
+ return ++*s;
+}
+
+hbool postinc(hbool *s) {
+ return (*s)++;
+}
+
+hbool sub1(hbool *s) {
+ return *s -= 1;
+}
+
+hbool predec(hbool *s) {
+ return --*s;
+}
+
+hbool postdec(hbool *s) {
+ return (*s)--;
+}
+
void check_pfalse (hbool *p)
{
assert (!*p);
@@ -114,5 +142,43 @@ int main () {
check_vtrue (h2 (2));
check_vtrue (h2 (1));
check_vfalse (h2 (0));
-}
+ hbool v;
+ v = 0;
+ check_vtrue (add1 (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (preinc (&v));
+ assert (v);
+ v = 0;
+ check_vfalse (postinc (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (sub1 (&v));
+ assert (v);
+ v = 0;
+ check_vtrue (predec (&v));
+ assert (v);
+ v = 0;
+ check_vfalse (postdec (&v));
+ assert (v);
+
+ v = 1;
+ check_vtrue (add1 (&v));
+ assert (v);
+ v = 1;
+ check_vtrue (preinc (&v));
+ assert (v);
+ v = 1;
+ check_vtrue (postinc (&v));
+ assert (v);
+ v = 1;
+ check_vfalse (sub1 (&v));
+ assert (!v);
+ v = 1;
+ check_vfalse (predec (&v));
+ assert (!v);
+ v = 1;
+ check_vtrue (postdec (&v));
+ assert (!v);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/vect-gather-1.c b/gcc/testsuite/gcc.dg/vect/vect-gather-1.c
index 5f6640d..6497ab4 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-gather-1.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-gather-1.c
@@ -3,9 +3,9 @@
#define N 16
void __attribute__((noipa))
-f (int *restrict y, int *restrict x, int *restrict indices)
+f (int *restrict y, int *restrict x, int *restrict indices, int n)
{
- for (int i = 0; i < N; ++i)
+ for (int i = 0; i < n; ++i)
{
y[i * 2] = x[indices[i * 2]] + 1;
y[i * 2 + 1] = x[indices[i * 2 + 1]] + 2;
@@ -49,7 +49,7 @@ main (void)
{
check_vect ();
- f (y, x, indices);
+ f (y, x, indices, N);
#pragma GCC novector
for (int i = 0; i < 32; ++i)
if (y[i] != expected[i])
diff --git a/gcc/testsuite/gcc.dg/vla-tert-1.c b/gcc/testsuite/gcc.dg/vla-tert-1.c
new file mode 100644
index 0000000..dfbb2e6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-tert-1.c
@@ -0,0 +1,293 @@
+/* { dg-do run }
+ * { dg-options "-std=c99" }
+ * */
+
+
+// For the conditional operator and variably modified types,
+// verify that the size expression on the selected branch
+// is evaluated and the correct result is returned.
+
+
+// keep track which side was evaluated.
+static int fc[2] = { 0 };
+
+static int f(int s, int c)
+{
+ fc[c]++;
+ return s;
+}
+
+
+int main()
+{
+ // two VLAs, constant condition
+
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(1 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(0 ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort(); // fails
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort(); // fails
+
+ // two VLAs
+
+ int c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort(); // fails
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of unknown size, VLA side is evaluated, defined
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of unknown size, VLA side is not evaluated
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ sizeof(*(c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0));
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ ])0 : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0));
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+
+ // VLA + array of known size, VLA side is evaluated
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ // sizeof is not evaluated because not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ // without sizeof
+
+ (c ? (char(*)[3])0 : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (char(*)[5])0)))
+ __builtin_abort();
+
+ // sizeof is not evaluated because not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // without sizeof
+
+ fc[0] = fc[1] = 0;
+
+ (c ? (char(*)[ f(5, 0) ])0 : (char(*)[ 5 ])0);
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + array of known size, VLA side is not evaluated
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (char(*)[ f(3, 0) ])0 : (char(*)[ 3 ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ 5 ])0 : (char(*)[ f(5, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VM type on one side, null pointer on the other side
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+#if 0
+ // these cases are not fixable
+ // VM types on one side, null pointer on the other side
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (3 != sizeof(*(c ? (void*)0 : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (5 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : (void*)0)))
+ __builtin_abort();
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+#endif
+
+ // VLA + void*
+ void* p = 0;
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ // not a VLA or evaluated
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? p : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (1 != fc[1]))
+ __builtin_abort();
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p)))
+ __builtin_abort();
+
+ // not a VLA
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? (char(*)[ f(5, 0) ])0 : p);
+
+ if ((1 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // VLA + void*, VLA side not evaluated
+
+ c = 1;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? p : (char(*)[ f(3, 1) ])0)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? p : (char(*)[ f(3, 1) ])0);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ c = 0;
+ fc[0] = fc[1] = 0;
+
+ if (1 != sizeof(*(c ? (char(*)[ f(5, 0) ])0 : p)))
+ __builtin_abort();
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ // .. without sizeof
+
+ (c ? (char(*)[ f(5, 0) ])0 : p);
+
+ if ((0 != fc[0]) || (0 != fc[1]))
+ __builtin_abort();
+
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c
index f0dc9a9..1201ca0 100644
--- a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cops.c
@@ -212,22 +212,22 @@
type init4 = svld1_ ## su ## sz (cmp ## sz, mem); \
\
type res_init1 = func_ ## type ## _init1 (); \
- svbool_t cmp = svcmpne_ ## su ## sz (all_true, init1, res_init1); \
+ svbool_t cmp = svcmpne_ ## su ## sz (cmp ## sz, init1, res_init1); \
if (svptest_any (all_true, cmp)) \
__builtin_abort (); \
\
type res_init2 = func_ ## type ## _init2 (); \
- cmp = svcmpne_ ## su ## sz (all_true, init2, res_init2); \
+ cmp = svcmpne_ ## su ## sz (cmp ## sz, init2, res_init2); \
if (svptest_any (all_true, cmp)) \
__builtin_abort (); \
\
type res_init3 = func_ ## type ## _init3 (); \
- cmp = svcmpne_ ## su ## sz (all_true, init3, res_init3); \
+ cmp = svcmpne_ ## su ## sz (cmp ## sz, init3, res_init3); \
if (svptest_any (all_true, cmp)) \
__builtin_abort (); \
\
type res_init4 = func_ ## type ## _init4 (); \
- cmp = svcmpne_ ## su ## sz (all_true, init4, res_init4); \
+ cmp = svcmpne_ ## su ## sz (cmp ## sz, init4, res_init4); \
if (svptest_any (all_true, cmp)) \
__builtin_abort (); \
}
diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-1.c b/gcc/testsuite/gcc.target/riscv/arch-unset-1.c
new file mode 100644
index 0000000..971b936
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-unset-1.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -mabi=lp64 -misa-spec=20191213" } */
+int foo()
+{
+}
+
+/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zfh1p0_zfhmin1p0_zca1p0_zcd1p0_zba1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvfh1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-2.c b/gcc/testsuite/gcc.target/riscv/arch-unset-2.c
new file mode 100644
index 0000000..9840658
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-unset-2.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=rv64i -mabi=lp64 -misa-spec=20191213" } */
+int foo()
+{
+}
+
+/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-3.c b/gcc/testsuite/gcc.target/riscv/arch-unset-3.c
new file mode 100644
index 0000000..5ddc224
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-unset-3.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=rv64i -march=unset -mabi=lp64 -misa-spec=20191213" } */
+int foo()
+{
+}
+
+/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zmmul1p0_zaamo1p0_zalrsc1p0_zfh1p0_zfhmin1p0_zca1p0_zcd1p0_zba1p0_zbb1p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvfh1p0_zvl128b1p0_zvl256b1p0_zvl32b1p0_zvl512b1p0_zvl64b1p0\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-4.c b/gcc/testsuite/gcc.target/riscv/arch-unset-4.c
new file mode 100644
index 0000000..c16821d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-unset-4.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -march=unset -mcpu=sifive-x280 -march=unset -march=rv64i -march=unset -march=rv64i -mabi=lp64 -misa-spec=20191213" } */
+int foo()
+{
+}
+
+/* { dg-final { scan-assembler "\.attribute arch, \"rv64i2p1\"" } } */
diff --git a/gcc/testsuite/gcc.target/riscv/arch-unset-5.c b/gcc/testsuite/gcc.target/riscv/arch-unset-5.c
new file mode 100644
index 0000000..368c129
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/arch-unset-5.c
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64i -march=unset -mabi=lp64 -misa-spec=20191213" } */
+int foo()
+{
+}
+
+/* { dg-error "At least one valid -mcpu option must be given after -march=unset" "" { target { "riscv*-*-*" } } 0 } */
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03 b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03
index 79cf2c1..da20835 100644
--- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2.f03
@@ -1,5 +1,5 @@
! { dg-do run }
-! { dg-additional-sources c_f_pointer_shape_tests_2_driver.c }
+! { dg-additional-sources c_f_pointer_shape_tests_driver.c }
! Verify that the optional SHAPE parameter to c_f_pointer can be of any
! valid integer kind. We don't test all kinds here since it would be
! difficult to know what kinds are valid for the architecture we're running on.
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c
deleted file mode 100644
index 1282beb..0000000
--- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_2_driver.c
+++ /dev/null
@@ -1,46 +0,0 @@
-#define NUM_ELEMS 10
-#define NUM_ROWS 2
-#define NUM_COLS 3
-
-void test_long_long_1d(int *array, int num_elems);
-void test_long_long_2d(int *array, int num_rows, int num_cols);
-void test_long_1d(int *array, int num_elems);
-void test_int_1d(int *array, int num_elems);
-void test_short_1d(int *array, int num_elems);
-void test_mixed(int *array, int num_elems);
-
-int main(int argc, char **argv)
-{
- int my_array[NUM_ELEMS];
- int my_2d_array[NUM_ROWS][NUM_COLS];
- int i, j;
-
- for(i = 0; i < NUM_ELEMS; i++)
- my_array[i] = i;
-
- for(i = 0; i < NUM_ROWS; i++)
- for(j = 0; j < NUM_COLS; j++)
- my_2d_array[i][j] = (i*NUM_COLS) + j;
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */
- test_long_long_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long.
- The indices are transposed for Fortran. */
- test_long_long_2d(my_2d_array[0], NUM_COLS, NUM_ROWS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */
- test_long_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */
- test_int_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */
- test_short_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and
- kind=c_long_long. */
- test_mixed(my_array, NUM_ELEMS);
-
- return 0;
-}
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03
index 3f60f17..519087a 100644
--- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03
@@ -1,5 +1,5 @@
! { dg-do run }
-! { dg-additional-sources c_f_pointer_shape_tests_2_driver.c }
+! { dg-additional-sources c_f_pointer_shape_tests_driver.c }
! Verify that the optional SHAPE parameter to c_f_pointer can be of any
! valid integer kind. We don't test all kinds here since it would be
! difficult to know what kinds are valid for the architecture we're running on.
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c
deleted file mode 100644
index 1282beb..0000000
--- a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c
+++ /dev/null
@@ -1,46 +0,0 @@
-#define NUM_ELEMS 10
-#define NUM_ROWS 2
-#define NUM_COLS 3
-
-void test_long_long_1d(int *array, int num_elems);
-void test_long_long_2d(int *array, int num_rows, int num_cols);
-void test_long_1d(int *array, int num_elems);
-void test_int_1d(int *array, int num_elems);
-void test_short_1d(int *array, int num_elems);
-void test_mixed(int *array, int num_elems);
-
-int main(int argc, char **argv)
-{
- int my_array[NUM_ELEMS];
- int my_2d_array[NUM_ROWS][NUM_COLS];
- int i, j;
-
- for(i = 0; i < NUM_ELEMS; i++)
- my_array[i] = i;
-
- for(i = 0; i < NUM_ROWS; i++)
- for(j = 0; j < NUM_COLS; j++)
- my_2d_array[i][j] = (i*NUM_COLS) + j;
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */
- test_long_long_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long.
- The indices are transposed for Fortran. */
- test_long_long_2d(my_2d_array[0], NUM_COLS, NUM_ROWS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */
- test_long_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */
- test_int_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */
- test_short_1d(my_array, NUM_ELEMS);
-
- /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and
- kind=c_long_long. */
- test_mixed(my_array, NUM_ELEMS);
-
- return 0;
-}
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c
new file mode 100644
index 0000000..70e7d56
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_driver.c
@@ -0,0 +1,47 @@
+#define NUM_ELEMS 10
+#define NUM_ROWS 2
+#define NUM_COLS 3
+
+void test_long_long_1d (int *array, int num_elems);
+void test_long_long_2d (int *array, int num_rows, int num_cols);
+void test_long_1d (int *array, int num_elems);
+void test_int_1d (int *array, int num_elems);
+void test_short_1d (int *array, int num_elems);
+void test_mixed (int *array, int num_elems);
+
+int
+main (int argc, char **argv)
+{
+ int my_array[NUM_ELEMS];
+ int my_2d_array[NUM_ROWS][NUM_COLS];
+ int i, j;
+
+ for (i = 0; i < NUM_ELEMS; i++)
+ my_array[i] = i;
+
+ for (i = 0; i < NUM_ROWS; i++)
+ for (j = 0; j < NUM_COLS; j++)
+ my_2d_array[i][j] = (i * NUM_COLS) + j;
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */
+ test_long_long_1d (my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long.
+ The indices are transposed for Fortran. */
+ test_long_long_2d (my_2d_array[0], NUM_COLS, NUM_ROWS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */
+ test_long_1d (my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */
+ test_int_1d (my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */
+ test_short_1d (my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and
+ kind=c_long_long. */
+ test_mixed (my_array, NUM_ELEMS);
+
+ return 0;
+}
diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index 663a821..c19baba 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -1199,6 +1199,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "from(");
if (OMP_CLAUSE_MOTION_PRESENT (clause))
pp_string (pp, "present:");
+ if (OMP_CLAUSE_ITERATORS (clause))
+ {
+ dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags);
+ pp_colon (pp);
+ }
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
goto print_clause_size;
@@ -1207,6 +1212,11 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, "to(");
if (OMP_CLAUSE_MOTION_PRESENT (clause))
pp_string (pp, "present:");
+ if (OMP_CLAUSE_ITERATORS (clause))
+ {
+ dump_omp_iterators (pp, OMP_CLAUSE_ITERATORS (clause), spc, flags);
+ pp_colon (pp);
+ }
dump_generic_node (pp, OMP_CLAUSE_DECL (clause),
spc, flags, false);
goto print_clause_size;
diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index dc82bf6..a9d4aae 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -4423,8 +4423,9 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
MASKED_P is true if the load or store is conditional. MEMORY_TYPE is
the type of the memory elements being loaded or stored. OFFSET_TYPE
is the type of the offset that is being applied to the invariant
- base address. SCALE is the amount by which the offset should
- be multiplied *after* it has been converted to address width.
+ base address. If OFFSET_TYPE is scalar the function chooses an
+ appropriate vector type for it. SCALE is the amount by which the
+ offset should be multiplied *after* it has been converted to address width.
Return true if the function is supported, storing the function id in
*IFN_OUT and the vector type for the offset in *OFFSET_VECTYPE_OUT.
@@ -4467,9 +4468,15 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
for (;;)
{
- tree offset_vectype = get_vectype_for_scalar_type (vinfo, offset_type);
- if (!offset_vectype)
- return false;
+ tree offset_vectype;
+ if (VECTOR_TYPE_P (offset_type))
+ offset_vectype = offset_type;
+ else
+ {
+ offset_vectype = get_vectype_for_scalar_type (vinfo, offset_type);
+ if (!offset_vectype)
+ return false;
+ }
/* Test whether the target supports this combination. */
if (internal_gather_scatter_fn_supported_p (ifn, vectype, memory_type,
@@ -4500,10 +4507,15 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
return true;
}
+ /* For fixed offset vector type we're done. */
+ if (VECTOR_TYPE_P (offset_type))
+ return false;
+
if (TYPE_PRECISION (offset_type) >= POINTER_SIZE
&& TYPE_PRECISION (offset_type) >= element_bits)
return false;
+ /* Try a larger offset vector type. */
offset_type = build_nonstandard_integer_type
(TYPE_PRECISION (offset_type) * 2, TYPE_UNSIGNED (offset_type));
}
@@ -4512,7 +4524,7 @@ vect_gather_scatter_fn_p (vec_info *vinfo, bool read_p, bool masked_p,
/* STMT_INFO is a call to an internal gather load or scatter store function.
Describe the operation in INFO. */
-static void
+void
vect_describe_gather_scatter_call (stmt_vec_info stmt_info,
gather_scatter_info *info)
{
@@ -6524,7 +6536,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
tree vectype, int misalignment,
gather_scatter_info *gs_info)
{
- data_reference *dr = dr_info ? dr_info->dr : nullptr;
+ data_reference *dr = dr_info->dr;
stmt_vec_info stmt_info = dr_info->stmt;
machine_mode mode = TYPE_MODE (vectype);
loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
@@ -6605,7 +6617,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
}
} */
- if (dr && DR_IS_READ (dr))
+ if (DR_IS_READ (dr))
{
if (can_implement_p (vec_realign_load_optab, mode)
&& (!targetm.vectorize.builtin_mask_for_load
@@ -6635,38 +6647,7 @@ vect_supportable_dr_alignment (vec_info *vinfo, dr_vec_info *dr_info,
tree type = TREE_TYPE (DR_REF (dr));
bool is_gather_scatter = gs_info != nullptr;
if (misalignment == DR_MISALIGNMENT_UNKNOWN)
- {
- if (!is_gather_scatter || dr != nullptr)
- is_packed = not_size_aligned (DR_REF (dr));
- else
- {
- /* Gather-scatter accesses normally perform only component accesses
- so alignment is irrelevant for them. Targets like riscv do care
- about scalar alignment in vector accesses, though, so check scalar
- alignment here. We determined the alias pointer as well as the
- base alignment during pattern recognition and can re-use it here.
-
- As we do not have an analyzed dataref we only know the alignment
- of the reference itself and nothing about init, steps, etc.
- For now don't try harder to determine misalignment and
- just assume it is unknown. We consider the type packed if its
- scalar alignment is lower than the natural alignment of a vector
- element's type. */
-
- gcc_assert (!GATHER_SCATTER_LEGACY_P (*gs_info));
- gcc_assert (dr == nullptr);
-
- tree inner_vectype = TREE_TYPE (vectype);
-
- unsigned HOST_WIDE_INT scalar_align
- = tree_to_uhwi (gs_info->alias_ptr);
- unsigned HOST_WIDE_INT inner_vectype_sz
- = tree_to_uhwi (TYPE_SIZE (inner_vectype));
-
- bool is_misaligned = scalar_align < inner_vectype_sz;
- is_packed = scalar_align > 1 && is_misaligned;
- }
- }
+ is_packed = not_size_aligned (DR_REF (dr));
if (targetm.vectorize.support_vector_misalignment (mode, type, misalignment,
is_packed,
is_gather_scatter))
diff --git a/gcc/tree-vect-slp.cc b/gcc/tree-vect-slp.cc
index 794a073..59acbc1 100644
--- a/gcc/tree-vect-slp.cc
+++ b/gcc/tree-vect-slp.cc
@@ -120,6 +120,8 @@ _slp_tree::_slp_tree ()
SLP_TREE_LANE_PERMUTATION (this) = vNULL;
SLP_TREE_DEF_TYPE (this) = vect_uninitialized_def;
SLP_TREE_CODE (this) = ERROR_MARK;
+ SLP_TREE_GS_SCALE (this) = 0;
+ SLP_TREE_GS_BASE (this) = NULL_TREE;
this->ldst_lanes = false;
this->avoid_stlf_fail = false;
SLP_TREE_VECTYPE (this) = NULL_TREE;
@@ -680,6 +682,15 @@ vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char swap,
{
internal_fn ifn = gimple_call_internal_fn (stmt);
commutative_op = first_commutative_argument (ifn);
+ if (internal_gather_scatter_fn_p (ifn))
+ {
+ vect_describe_gather_scatter_call
+ (stmt_info,
+ first ? &(*oprnds_info)[0]->first_gs_info : &gs_info);
+ if (first)
+ (*oprnds_info)[0]->first_gs_p = true;
+ gs_op = 0;
+ }
}
}
else if (gassign *stmt = dyn_cast <gassign *> (stmt_info->stmt))
@@ -2720,6 +2731,9 @@ out:
stmt_info = stmts[0];
+ int gs_scale = 0;
+ tree gs_base = NULL_TREE;
+
/* Create SLP_TREE nodes for the definition node/s. */
FOR_EACH_VEC_ELT (oprnds_info, i, oprnd_info)
{
@@ -2742,6 +2756,12 @@ out:
continue;
}
+ if (oprnd_info->first_gs_p)
+ {
+ gs_scale = oprnd_info->first_gs_info.scale;
+ gs_base = oprnd_info->first_gs_info.base;
+ }
+
if (is_a <bb_vec_info> (vinfo)
&& oprnd_info->first_dt == vect_internal_def
&& !oprnd_info->any_pattern)
@@ -3131,6 +3151,8 @@ fail:
node = vect_create_new_slp_node (node, stmts, nops);
SLP_TREE_VECTYPE (node) = vectype;
SLP_TREE_CHILDREN (node).splice (children);
+ SLP_TREE_GS_SCALE (node) = gs_scale;
+ SLP_TREE_GS_BASE (node) = gs_base;
return node;
}
diff --git a/gcc/tree-vect-stmts.cc b/gcc/tree-vect-stmts.cc
index f7a052b..a6f4db4 100644
--- a/gcc/tree-vect-stmts.cc
+++ b/gcc/tree-vect-stmts.cc
@@ -1497,7 +1497,8 @@ check_load_store_for_partial_vectors (loop_vec_info loop_vinfo, tree vectype,
gs_info->memory_type,
gs_info->offset_vectype,
gs_info->scale,
- elsvals))
+ elsvals)
+ || gs_info->decl != NULL_TREE)
vect_record_loop_mask (loop_vinfo, masks, nvectors, vectype,
scalar_mask);
else
@@ -2018,31 +2019,40 @@ get_load_store_type (vec_info *vinfo, stmt_vec_info stmt_info,
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
{
*memory_access_type = VMAT_GATHER_SCATTER;
- if (!vect_check_gather_scatter (stmt_info, loop_vinfo, gs_info,
- elsvals))
- gcc_unreachable ();
slp_tree offset_node = SLP_TREE_CHILDREN (slp_node)[0];
tree offset_vectype = SLP_TREE_VECTYPE (offset_node);
+ memset (gs_info, 0, sizeof (gather_scatter_info));
gs_info->offset_vectype = offset_vectype;
- /* When using internal functions, we rely on pattern recognition
- to convert the type of the offset to the type that the target
- requires, with the result being a call to an internal function.
- If that failed for some reason (e.g. because another pattern
- took priority), just handle cases in which the offset already
- has the right type. */
- if (GATHER_SCATTER_IFN_P (*gs_info)
- && !is_gimple_call (stmt_info->stmt)
- && !tree_nop_conversion_p (TREE_TYPE (gs_info->offset),
- TREE_TYPE (offset_vectype)))
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "%s offset requires a conversion\n",
- vls_type == VLS_LOAD ? "gather" : "scatter");
- return false;
- }
- else if (GATHER_SCATTER_EMULATED_P (*gs_info))
+ gs_info->scale = SLP_TREE_GS_SCALE (slp_node);
+ gs_info->base = SLP_TREE_GS_BASE (slp_node);
+ gs_info->memory_type = TREE_TYPE (DR_REF (first_dr_info->dr));
+ gs_info->decl = NULL_TREE;
+ gs_info->ifn = IFN_LAST;
+ tree tem;
+ if (vect_gather_scatter_fn_p (loop_vinfo, vls_type == VLS_LOAD,
+ masked_p, vectype,
+ gs_info->memory_type,
+ offset_vectype, gs_info->scale,
+ &gs_info->ifn, &tem,
+ elsvals))
+ /* GATHER_SCATTER_IFN_P. */;
+ else if (vls_type == VLS_LOAD
+ ? (targetm.vectorize.builtin_gather
+ && (gs_info->decl
+ = targetm.vectorize.builtin_gather (vectype,
+ TREE_TYPE
+ (offset_vectype),
+ gs_info->scale)))
+ : (targetm.vectorize.builtin_scatter
+ && (gs_info->decl
+ = targetm.vectorize.builtin_scatter (vectype,
+ TREE_TYPE
+ (offset_vectype),
+ gs_info->scale))))
+ /* GATHER_SCATTER_LEGACY_P. */;
+ else
{
+ /* GATHER_SCATTER_EMULATED_P. */
if (!TYPE_VECTOR_SUBPARTS (vectype).is_constant ()
|| !TYPE_VECTOR_SUBPARTS (offset_vectype).is_constant ()
|| VECTOR_BOOLEAN_TYPE_P (offset_vectype)
@@ -8529,7 +8539,6 @@ vectorizable_store (vec_info *vinfo,
gcc_assert (useless_type_conversion_p (vectype,
TREE_TYPE (vec_oprnd)));
}
- unsigned HOST_WIDE_INT align;
tree final_mask = NULL_TREE;
tree final_len = NULL_TREE;
tree bias = NULL_TREE;
@@ -8544,6 +8553,8 @@ vectorizable_store (vec_info *vinfo,
final_mask, vec_mask, gsi);
}
+ unsigned align = get_object_alignment (DR_REF (first_dr_info->dr));
+ tree alias_align_ptr = build_int_cst (ref_type, align);
if (GATHER_SCATTER_IFN_P (gs_info))
{
if (costing_p)
@@ -8585,7 +8596,7 @@ vectorizable_store (vec_info *vinfo,
if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
call = gimple_build_call_internal (
IFN_MASK_LEN_SCATTER_STORE, 8, dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset, scale, vec_oprnd, final_mask, final_len,
bias);
else
@@ -8602,12 +8613,12 @@ vectorizable_store (vec_info *vinfo,
else if (final_mask)
call = gimple_build_call_internal
(IFN_MASK_SCATTER_STORE, 6, dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset, scale, vec_oprnd, final_mask);
else
call = gimple_build_call_internal (IFN_SCATTER_STORE, 5,
dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset,
scale, vec_oprnd);
gimple_call_set_nothrow (call, true);
@@ -8763,7 +8774,6 @@ vectorizable_store (vec_info *vinfo,
= (j % factor) * const_nunits;
tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset));
tree scale = size_int (gs_info.scale);
- align = get_object_alignment (DR_REF (first_dr_info->dr));
tree ltype = build_aligned_type (TREE_TYPE (vectype), align);
for (unsigned k = 0; k < const_nunits; ++k)
{
@@ -10392,7 +10402,8 @@ vectorizable_load (vec_info *vinfo,
}
/* 2. Create the vector-load in the loop. */
- unsigned HOST_WIDE_INT align;
+ unsigned align = get_object_alignment (DR_REF (first_dr_info->dr));
+ tree alias_align_ptr = build_int_cst (ref_type, align);
if (GATHER_SCATTER_IFN_P (gs_info))
{
if (costing_p)
@@ -10440,7 +10451,7 @@ vectorizable_load (vec_info *vinfo,
if (VECTOR_TYPE_P (TREE_TYPE (vec_offset)))
call = gimple_build_call_internal (IFN_MASK_LEN_GATHER_LOAD,
9, dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset, scale, zero,
final_mask, vec_els,
final_len, bias);
@@ -10456,13 +10467,13 @@ vectorizable_load (vec_info *vinfo,
else if (final_mask)
call = gimple_build_call_internal (IFN_MASK_GATHER_LOAD,
7, dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset, scale,
zero, final_mask, vec_els);
else
call = gimple_build_call_internal (IFN_GATHER_LOAD, 5,
dataref_ptr,
- gs_info.alias_ptr,
+ alias_align_ptr,
vec_offset, scale, zero);
gimple_call_set_nothrow (call, true);
new_stmt = call;
@@ -10620,7 +10631,6 @@ vectorizable_load (vec_info *vinfo,
unsigned elt_offset = (i % factor) * const_nunits;
tree idx_type = TREE_TYPE (TREE_TYPE (vec_offset));
tree scale = size_int (gs_info.scale);
- align = get_object_alignment (DR_REF (first_dr_info->dr));
tree ltype = build_aligned_type (TREE_TYPE (vectype), align);
for (unsigned k = 0; k < const_nunits; ++k)
{
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 52e1075..9653496 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -306,6 +306,11 @@ struct _slp_tree {
unsigned int lanes;
/* The operation of this node. */
enum tree_code code;
+ /* For gather/scatter memory operations the scale each offset element
+ should be multiplied by before being added to the base. */
+ int gs_scale;
+ /* For gather/scatter memory operations the loop-invariant base value. */
+ tree gs_base;
/* Whether uses of this load or feeders of this store are suitable
for load/store-lanes. */
bool ldst_lanes;
@@ -412,6 +417,8 @@ public:
#define SLP_TREE_CODE(S) (S)->code
#define SLP_TREE_MEMORY_ACCESS_TYPE(S) (S)->memory_access_type
#define SLP_TREE_TYPE(S) (S)->type
+#define SLP_TREE_GS_SCALE(S) (S)->gs_scale
+#define SLP_TREE_GS_BASE(S) (S)->gs_base
enum vect_partial_vector_style {
vect_partial_vectors_none,
@@ -2550,6 +2557,8 @@ extern bool vect_gather_scatter_fn_p (vec_info *, bool, bool, tree, tree,
extern bool vect_check_gather_scatter (stmt_vec_info, loop_vec_info,
gather_scatter_info *,
vec<int> * = nullptr);
+extern void vect_describe_gather_scatter_call (stmt_vec_info,
+ gather_scatter_info *);
extern opt_result vect_find_stmt_data_reference (loop_p, gimple *,
vec<data_reference_p> *,
vec<int> *, int);
diff --git a/gcc/tree.cc b/gcc/tree.cc
index 203cc1c..dcc1abd 100644
--- a/gcc/tree.cc
+++ b/gcc/tree.cc
@@ -323,8 +323,8 @@ unsigned const char omp_clause_num_ops[] =
1, /* OMP_CLAUSE_IS_DEVICE_PTR */
1, /* OMP_CLAUSE_INCLUSIVE */
1, /* OMP_CLAUSE_EXCLUSIVE */
- 2, /* OMP_CLAUSE_FROM */
- 2, /* OMP_CLAUSE_TO */
+ 3, /* OMP_CLAUSE_FROM */
+ 3, /* OMP_CLAUSE_TO */
3, /* OMP_CLAUSE_MAP (update walk_tree_1 if this is changed) */
1, /* OMP_CLAUSE_HAS_DEVICE_ADDR */
1, /* OMP_CLAUSE_DOACROSS */
diff --git a/gcc/tree.h b/gcc/tree.h
index 4380657..f1aacb31b 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1660,11 +1660,13 @@ class auto_suppress_location_wrappers
#define OMP_CLAUSE_LOCATION(NODE) (OMP_CLAUSE_CHECK (NODE))->omp_clause.locus
#define OMP_CLAUSE_HAS_ITERATORS(NODE) \
- (OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP \
+ ((OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_FROM \
+ || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_TO \
+ || OMP_CLAUSE_CODE (NODE) == OMP_CLAUSE_MAP) \
&& OMP_CLAUSE_ITERATORS (NODE))
#define OMP_CLAUSE_ITERATORS(NODE) \
OMP_CLAUSE_OPERAND (OMP_CLAUSE_RANGE_CHECK (OMP_CLAUSE_CHECK (NODE), \
- OMP_CLAUSE_MAP, \
+ OMP_CLAUSE_FROM, \
OMP_CLAUSE_MAP), 2)
/* True on OMP_FOR and other OpenMP/OpenACC looping constructs if the loop nest
diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog
index 0962ddf..882117d 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -1,3 +1,9 @@
+2025-08-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR libgcc/121397
+ * enable-execute-stack-mprotect.c (check_enabling): Remove useless
+ forward declaration.
+
2025-07-31 Wilco Dijkstra <wilco.dijkstra@arm.com>
* config/aarch64/cpuinfo.c (__init_cpu_features_constructor):
diff --git a/libgcc/enable-execute-stack-mprotect.c b/libgcc/enable-execute-stack-mprotect.c
index 08a0d72..7971efb 100644
--- a/libgcc/enable-execute-stack-mprotect.c
+++ b/libgcc/enable-execute-stack-mprotect.c
@@ -30,7 +30,6 @@
static int need_enable_exec_stack;
-static void check_enabling (void) __attribute__ ((unused));
extern void __enable_execute_stack (void *);
#if defined __sun__ && defined __svr4__
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index ea41616..440a32a 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,10 @@
+2025-08-06 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR libfortran/121234
+ * io/list_read.c (read_character): Add checks to bypass eating
+ semicolons when reading strings with decimal mode 'point'
+ (list_formatted_read_scalar): Likewise.
+
2025-07-30 Yuao Ma <c8ef@outlook.com>
* gfortran.map: Add split symbol.
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 2689f3e..722da76 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,23 @@
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+
+ * target.c (gomp_update): Call gomp_merge_iterator_maps. Free
+ allocated variables.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-1.c: New.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-2.c: New.
+ * testsuite/libgomp.c-c++-common/target-update-iterators-3.c: New.
+
+2025-08-06 Kwok Cheung Yeung <kcyeung@baylibre.com>
+ Andrew Stubbs <ams@baylibre.com>
+
+ * target.c (kind_to_name): New.
+ (gomp_merge_iterator_maps): New.
+ (gomp_map_vars_internal): Call gomp_merge_iterator_maps. Copy
+ address of only the first iteration to target vars. Free allocated
+ variables.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-1.c: New.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-2.c: New.
+ * testsuite/libgomp.c-c++-common/target-map-iterators-3.c: New.
+
2025-07-21 Thomas Schwinge <tschwinge@baylibre.com>
PR target/119853
diff --git a/libgomp/target.c b/libgomp/target.c
index 43976f0..c89c82c 100644
--- a/libgomp/target.c
+++ b/libgomp/target.c
@@ -2372,6 +2372,8 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs,
size_t i;
struct splay_tree_key_s cur_node;
const int typemask = short_mapkind ? 0xff : 0x7;
+ bool iterators_p = false;
+ size_t *iterator_count = NULL;
if (!devicep)
return;
@@ -2379,6 +2381,10 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs,
if (mapnum == 0)
return;
+ if (short_mapkind) /* OpenMP */
+ iterators_p = gomp_merge_iterator_maps (&mapnum, &hostaddrs, &sizes,
+ &kinds, &iterator_count);
+
gomp_mutex_lock (&devicep->lock);
if (devicep->state == GOMP_DEVICE_FINALIZED)
{
@@ -2472,6 +2478,14 @@ gomp_update (struct gomp_device_descr *devicep, size_t mapnum, void **hostaddrs,
}
}
gomp_mutex_unlock (&devicep->lock);
+
+ if (iterators_p)
+ {
+ free (hostaddrs);
+ free (sizes);
+ free (kinds);
+ free (iterator_count);
+ }
}
static struct gomp_offload_icv_list *
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c
new file mode 100644
index 0000000..5a4cad5
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-1.c
@@ -0,0 +1,65 @@
+/* { dg-do run } */
+
+/* Test target enter data and target update to the target using map
+ iterators. */
+
+#include <stdlib.h>
+
+#define DIM1 8
+#define DIM2 15
+
+int mkarray (int *x[])
+{
+ int expected = 0;
+ for (int i = 0; i < DIM1; i++)
+ {
+ x[i] = (int *) malloc (DIM2 * sizeof (int));
+ for (int j = 0; j < DIM2; j++)
+ {
+ x[i][j] = rand ();
+ expected += x[i][j];
+ }
+ }
+
+ return expected;
+}
+
+int main (void)
+{
+ int *x[DIM1];
+ int sum;
+ int expected = mkarray (x);
+
+ #pragma omp target enter data map(to: x[:DIM1])
+ #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2])
+ #pragma omp target map(from: sum)
+ {
+ sum = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ sum += x[i][j];
+ }
+
+ if (sum != expected)
+ return 1;
+
+ expected = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ {
+ x[i][j] *= rand ();
+ expected += x[i][j];
+ }
+
+ #pragma omp target update to(iterator(i=0:DIM1): x[i][:DIM2])
+
+ #pragma omp target map(from: sum)
+ {
+ sum = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ sum += x[i][j];
+ }
+
+ return sum != expected;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c
new file mode 100644
index 0000000..93438d0
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-2.c
@@ -0,0 +1,58 @@
+/* { dg-do run } */
+/* { dg-require-effective-target offload_device_nonshared_as } */
+
+/* Test target enter data and target update from the target using map
+ iterators. */
+
+#include <stdlib.h>
+
+#define DIM1 8
+#define DIM2 15
+
+void mkarray (int *x[])
+{
+ for (int i = 0; i < DIM1; i++)
+ {
+ x[i] = (int *) malloc (DIM2 * sizeof (int));
+ for (int j = 0; j < DIM2; j++)
+ x[i][j] = 0;
+ }
+}
+
+int main (void)
+{
+ int *x[DIM1];
+ int sum, expected;
+
+ mkarray (x);
+
+ #pragma omp target enter data map(alloc: x[:DIM1])
+ #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2])
+ #pragma omp target map(from: expected)
+ {
+ expected = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ {
+ x[i][j] = (i + 1) * (j + 2);
+ expected += x[i][j];
+ }
+ }
+
+ /* Host copy of x should remain unchanged. */
+ sum = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ sum += x[i][j];
+ if (sum != 0)
+ return 1;
+
+ #pragma omp target update from(iterator(i=0:DIM1): x[i][:DIM2])
+
+ /* Host copy should now be updated. */
+ sum = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ sum += x[i][j];
+ return sum - expected;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c
new file mode 100644
index 0000000..a70b21c
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/target-update-iterators-3.c
@@ -0,0 +1,67 @@
+/* { dg-do run } */
+/* { dg-require-effective-target offload_device_nonshared_as } */
+
+/* Test target enter data and target update to the target using map
+ iterators with a function. */
+
+#include <stdlib.h>
+
+#define DIM1 8
+#define DIM2 15
+
+void mkarray (int *x[])
+{
+ for (int i = 0; i < DIM1; i++)
+ {
+ x[i] = (int *) malloc (DIM2 * sizeof (int));
+ for (int j = 0; j < DIM2; j++)
+ x[i][j] = rand ();
+ }
+}
+
+int f (int i)
+{
+ return i * 2;
+}
+
+int main (void)
+{
+ int *x[DIM1], x_new[DIM1][DIM2];
+ int sum, expected;
+
+ mkarray (x);
+
+ #pragma omp target enter data map(alloc: x[:DIM1])
+ #pragma omp target enter data map(iterator(i=0:DIM1), to: x[i][:DIM2])
+
+ /* Update x on host. */
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ {
+ x_new[i][j] = x[i][j];
+ x[i][j] = (i + 1) * (j + 2);
+ }
+
+ /* Update a subset of x on target. */
+ #pragma omp target update to(iterator(i=0:DIM1/2): x[f (i)][:DIM2])
+
+ #pragma omp target map(from: sum)
+ {
+ sum = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ sum += x[i][j];
+ }
+
+ /* Calculate expected value on host. */
+ for (int i = 0; i < DIM1/2; i++)
+ for (int j = 0; j < DIM2; j++)
+ x_new[f (i)][j] = x[f (i)][j];
+
+ expected = 0;
+ for (int i = 0; i < DIM1; i++)
+ for (int j = 0; j < DIM2; j++)
+ expected += x_new[i][j];
+
+ return sum - expected;
+}
diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog
index cf90917..b072d0b 100644
--- a/libiberty/ChangeLog
+++ b/libiberty/ChangeLog
@@ -1,3 +1,8 @@
+2025-08-06 Matthieu Longo <matthieu.longo@arm.com>
+
+ * testsuite/test-doubly-linked-list.c: disable debug logging on
+ stdout.
+
2025-07-09 Matthieu Longo <matthieu.longo@arm.com>
* Makefile.in: Add new header.
diff --git a/libiberty/testsuite/test-doubly-linked-list.c b/libiberty/testsuite/test-doubly-linked-list.c
index 1e1fc63..93fe19a 100644
--- a/libiberty/testsuite/test-doubly-linked-list.c
+++ b/libiberty/testsuite/test-doubly-linked-list.c
@@ -155,19 +155,26 @@ bool check(const char *op,
bool success = true;
bool res;
- l_print (wrapper->first);
+#define DUMP_LIST 0
+
+ if (DUMP_LIST)
+ l_print (wrapper->first);
+
res = run_test (expect, wrapper, false);
printf ("%s: test-linked-list::%s: check forward conformity\n",
res ? "PASS": "FAIL", op);
success &= res;
- l_reverse_print (wrapper->last);
+ if (DUMP_LIST)
+ l_reverse_print (wrapper->last);
+
res = run_test (expect, wrapper, true);
printf ("%s: test-linked-list::%s: check backward conformity\n",
res ? "PASS": "FAIL", op);
success &= res;
- printf("\n");
+ if (DUMP_LIST)
+ printf("\n");
return success;
}