aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog138
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/cobol/ChangeLog17
-rw-r--r--gcc/cobol/genapi.cc99
-rw-r--r--gcc/cobol/genutil.cc779
-rw-r--r--gcc/common.opt5
-rw-r--r--gcc/config/aarch64/aarch64.cc66
-rw-r--r--gcc/config/i386/i386.cc43
-rw-r--r--gcc/config/s390/s390.cc21
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/contracts.cc3
-rw-r--r--gcc/dwarf2out.cc46
-rw-r--r--gcc/dwarf2out.h29
-rw-r--r--gcc/flag-types.h3
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/ipa-cp.cc8
-rw-r--r--gcc/m2/ChangeLog36
-rw-r--r--gcc/m2/gm2-libs/FormatStrings.mod4
-rw-r--r--gcc/opts.cc6
-rw-r--r--gcc/po/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog94
-rw-r--r--gcc/testsuite/cobol.dg/group1/declarative_1.cob6
-rw-r--r--gcc/testsuite/g++.dg/torture/pr119610.C18
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/pr119610-sve.C20
-rw-r--r--gcc/testsuite/gcc.dg/completion-2.c1
-rw-r--r--gcc/testsuite/gcc.dg/raw-string-1.c25
-rw-r--r--gcc/testsuite/gcc.target/i386/pr119919.c13
-rw-r--r--gcc/testsuite/gcc.target/s390/pr119873-1.c11
-rw-r--r--gcc/testsuite/gcc.target/s390/pr119873-2.c17
-rw-r--r--gcc/testsuite/gcc.target/s390/pr119873-3.c27
-rw-r--r--gcc/testsuite/gcc.target/s390/pr119873-4.c27
-rw-r--r--gcc/testsuite/gm2/pimlib/run/pass/format2.mod63
-rw-r--r--libcpp/ChangeLog6
-rw-r--r--libcpp/lex.cc5
-rw-r--r--libgm2/ChangeLog41
-rw-r--r--libgm2/config.h.in53
-rwxr-xr-xlibgm2/configure371
-rw-r--r--libgm2/configure.ac44
-rw-r--r--libgm2/libm2iso/wraptime.cc60
-rw-r--r--libgomp/ChangeLog50
-rw-r--r--libgomp/testsuite/lib/libgomp.exp133
-rw-r--r--libgomp/testsuite/libgomp.c-c++-common/interop-2.c129
-rw-r--r--libgomp/testsuite/libgomp.c/interop-cublas-full.c176
-rw-r--r--libgomp/testsuite/libgomp.c/interop-cublas-libonly.c7
-rw-r--r--libgomp/testsuite/libgomp.c/interop-cuda-full.c159
-rw-r--r--libgomp/testsuite/libgomp.c/interop-cuda-libonly.c8
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip-amd-full.c7
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip-amd-no-hip-header.c8
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip-nvidia-full.c8
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-headers.c10
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-hip-header.c9
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hip.h234
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas-amd-full.c7
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas-amd-no-hip-header.c8
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-full.c7
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-headers.c9
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-hip-header.c8
-rw-r--r--libgomp/testsuite/libgomp.c/interop-hipblas.h240
-rw-r--r--libgomp/testsuite/libgomp.fortran/interop-hip-amd-full.F907
-rw-r--r--libgomp/testsuite/libgomp.fortran/interop-hip-amd-no-module.F906
-rw-r--r--libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-full.F909
-rw-r--r--libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-no-module.F908
-rw-r--r--libgomp/testsuite/libgomp.fortran/interop-hip.h214
-rw-r--r--libstdc++-v3/ChangeLog33
-rw-r--r--libstdc++-v3/include/std/generator10
-rw-r--r--libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc38
-rw-r--r--libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/list/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/23_containers/set/48101_neg.cc1
-rw-r--r--libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc57
-rw-r--r--libstdc++-v3/testsuite/util/replacement_memory_operators.h8
72 files changed, 3093 insertions, 749 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c838fcd..8d412b6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,141 @@
+2025-04-24 Jakub Jelinek <jakub@redhat.com>
+ Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
+
+ PR target/119873
+ * config/s390/s390.cc (s390_call_saved_register_used): Don't return
+ true if default definition of PARM_DECL SSA_NAME of the same register
+ is passed in call saved register.
+ (s390_function_ok_for_sibcall): Adjust comment.
+
+2025-04-24 Jan Hubicka <hubicka@ucw.cz>
+
+ PR target/119919
+ * config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Account
+ correctly cond_expr and min/max when one of operands is 0 or -1.
+
+2025-04-24 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/119924
+ * ipa-cp.cc (update_counts_for_self_gen_clones): Use nonzero_p.
+ (update_profiling_info): Likewise.
+ (update_specialized_profile): Likewise.
+
+2025-04-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/119610
+ * config/aarch64/aarch64.cc (aarch64_allocate_and_probe_stack_space):
+ Add a bytes_below_sp parameter and use it to calculate the CFA
+ offsets. Attach the first SVE CFA note to the move into the
+ associated temporary register.
+ (aarch64_allocate_and_probe_stack_space): Update calls accordingly.
+ Start out with bytes_per_sp set to the frame size and decrement
+ it after each allocation.
+
+2025-04-24 Kyrylo Tkachov <ktkachov@nvidia.com>
+
+ * opts.cc (validate_ipa_reorder_locality_lto_partition): Check opts
+ instead of opts_set for x_flag_ipa_reorder_for_locality.
+ (finish_options): Update call site.
+
+2025-04-24 Kyrylo Tkachov <ktkachov@nvidia.com>
+
+ * common.opt (LTO_PARTITION_DEFAULT): Delete.
+ (flto-partition=): Change default back to balanced.
+ * flag-types.h (lto_partition_model): Remove LTO_PARTITION_DEFAULT.
+ * opts.cc (validate_ipa_reorder_locality_lto_partition):
+ Check opts_set->x_flag_lto_partition instead of LTO_PARTITION_DEFAULT.
+ (finish_options): Remove handling of LTO_PARTITION_DEFAULT.
+
+2025-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/119711
+ * dwarf2out.h (struct dw_val_node): Add u member.
+ (struct dw_loc_descr_node): Remove dw_loc_opc, dtprel,
+ frame_offset_rel and dw_loc_addr members.
+ (dw_loc_opc, dw_loc_dtprel, dw_loc_frame_offset_rel, dw_loc_addr):
+ Define.
+ (struct dw_attr_struct): Remove dw_attr member.
+ (dw_attr): Define.
+ * dwarf2out.cc (loc_descr_equal_p_1): Use dw_loc_dtprel instead of
+ dtprel.
+ (output_loc_operands, new_addr_loc_descr, loc_checksum,
+ loc_checksum_ordered): Likewise.
+ (resolve_args_picking_1): Use dw_loc_frame_offset_rel instead of
+ frame_offset_rel.
+ (loc_list_from_tree_1): Likewise.
+ (resolve_addr_in_expr): Use dw_loc_dtprel instead of dtprel.
+ (copy_deref_exprloc): Copy val_class, val_entry and v members
+ instead of whole dw_loc_oprnd1 and dw_loc_oprnd2.
+ (optimize_string_length): Copy val_class, val_entry and v members
+ instead of whole dw_attr_val.
+ (hash_loc_operands): Use dw_loc_dtprel instead of dtprel.
+ (compare_loc_operands, compare_locs): Likewise.
+
+2025-04-24 liuhongt <hongtao.liu@intel.com>
+
+ PR target/103750
+ * config/i386/sse.md (*<avx512>_cmp<mode>3_and15): New define_insn.
+ (*<avx512>_ucmp<mode>3_and15): Ditto.
+ (*<avx512>_cmp<mode>3_and3): Ditto.
+ (*avx512vl_ucmpv2di3_and3): Ditto.
+ (*<avx512>_cmp<V48H_AVX512VL:mode>3_zero_extend<SWI248x:mode>):
+ Change operands[3] predicate to <cmp_imm_predicate>.
+ (*<avx512>_cmp<V48H_AVX512VL:mode>3_zero_extend<SWI248x:mode>_2):
+ Ditto.
+ (*<avx512>_cmp<mode>3): Add GET_MODE_NUNITS (<MODE>mode) >= 8
+ to the condition.
+ (*<avx512>_ucmp<mode>3): Ditto.
+ (V48_AVX512VL_4): New mode iterator.
+ (VI48_AVX512VL_4): Ditto.
+ (V8_AVX512VL_2): Ditto.
+
+2025-04-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-cp.cc (base_count): Remove.
+ (struct caller_statistics): Rename n_hot_calls to n_interesting_calls;
+ add called_without_ipa_profile.
+ (init_caller_stats): Update.
+ (cs_interesting_for_ipcp_p): New function.
+ (gather_caller_stats): collect n_interesting_calls and
+ called_without_profile.
+ (ipcp_cloning_candidate_p): Use n_interesting-calls rather then hot.
+ (good_cloning_opportunity_p): Rewrite heuristics when IPA profile is
+ present
+ (estimate_local_effects): Update.
+ (value_topo_info::propagate_effects): Update.
+ (compare_edge_profile_counts): Remove.
+ (ipcp_propagate_stage): Do not collect base_count.
+ (get_info_about_necessary_edges): Record whether function is called
+ without profile.
+ (decide_about_value): Update.
+ (ipa_cp_cc_finalize): Do not initialie base_count.
+ * profile-count.cc (profile_count::operator*): New.
+ (profile_count::operator*=): New.
+ * profile-count.h (profile_count::operator*): Declare
+ (profile_count::operator*=): Declare.
+ * params.opt: Remove ipa-cp-profile-count-base.
+ * doc/invoke.texi: Likewise.
+
+2025-04-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Cost truth_value
+ exprs.
+
+2025-04-23 liuhongt <hongtao.liu@intel.com>
+
+ * config/i386/predicates.md (vector_or_0_or_1s_operand): New predicate.
+ (nonimm_or_0_or_1s_operand): Ditto.
+ * config/i386/sse.md (vcond_mask_<mode><sseintvecmodelower>):
+ Extend the predicate of operands1 to accept 0 or allones
+ operands.
+ (vcond_mask_<mode><sseintvecmodelower>): Ditto.
+ (vcond_mask_v1tiv1ti): Ditto.
+ (vcond_mask_<mode><sseintvecmodelower>): Ditto.
+ * config/i386/i386.md (mov<mode>cc): Ditto for operands[2] and
+ operands[3].
+ * config/i386/i386-expand.cc (ix86_expand_sse_fp_minmax):
+ Force immediate_operand to register.
+
2025-04-22 Jan Hubicka <hubicka@ucw.cz>
* config/i386/i386.cc (ix86_vector_costs::add_stmt_cost): Add special cases
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 1041049..c872ff4 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20250423
+20250425
diff --git a/gcc/cobol/ChangeLog b/gcc/cobol/ChangeLog
index 27c31c1..d7d8596 100644
--- a/gcc/cobol/ChangeLog
+++ b/gcc/cobol/ChangeLog
@@ -1,3 +1,20 @@
+2025-04-24 Robert Dubner <rdubner@symas.com>
+
+ * genapi.cc: (initialize_variable_internal): Change TRACE1 formatting.
+ (create_and_call): Repair RETURN-CODE processing.
+ (mh_source_is_group): Repair run-time IF type comparison.
+ (psa_FldLiteralA): Change TRACE1 formatting.
+ (parser_symbol_add): Eliminate unnecessary code.
+ * genutil.cc: Eliminate SET_EXCEPTION_CODE macro.
+ (get_data_offset_dest): Repair set_exception_code logic.
+ (get_data_offset_source): Likewise.
+ (get_binary_value): Likewise.
+ (refer_refmod_length): Likewise.
+ (refer_fill_depends): Likewise.
+ (refer_offset_dest): Likewise.
+ (refer_size_dest): Likewise.
+ (refer_offset_source): Likewise.
+
2025-04-16 Bob Dubner <rdubner@symas.com>
PR cobol/119759
diff --git a/gcc/cobol/genapi.cc b/gcc/cobol/genapi.cc
index c8911f9..e44364a 100644
--- a/gcc/cobol/genapi.cc
+++ b/gcc/cobol/genapi.cc
@@ -1229,7 +1229,40 @@ initialize_variable_internal( cbl_refer_t refer,
}
else
{
- TRACE1_FIELD_VALUE("", parsed_var, "")
+ // Convert strings of spaces to "<SPACES>"
+ tree spaces = gg_define_int(0);
+ if( parsed_var->type == FldGroup
+ || parsed_var->type == FldAlphanumeric
+ || parsed_var->type == FldAlphaEdited
+ || parsed_var->type == FldLiteralA )
+ {
+ gg_assign(spaces, integer_one_node);
+ tree counter = gg_define_int(parsed_var->data.capacity);
+ WHILE(counter, gt_op, integer_zero_node)
+ {
+ gg_decrement(counter);
+ IF( gg_indirect(member(parsed_var->var_decl_node, "data"), counter),
+ ne_op,
+ build_int_cst_type(UCHAR, ' ') )
+ {
+ gg_assign(spaces, integer_zero_node);
+ }
+ ELSE
+ {
+ }
+ ENDIF
+ }
+ WEND
+ }
+ IF(spaces, eq_op, integer_one_node)
+ {
+ TRACE1_TEXT(" <SPACES>")
+ }
+ ELSE
+ {
+ TRACE1_FIELD_VALUE("", parsed_var, "")
+ }
+ ENDIF
}
TRACE1_END
}
@@ -12341,7 +12374,7 @@ create_and_call(size_t narg,
// Because the CALL had a RETURNING clause, RETURN-CODE doesn't return a
// value. So, we make sure it is zero
- gg_assign(var_decl_return_code, build_int_cst_type(SHORT, 0));
+//// gg_assign(var_decl_return_code, build_int_cst_type(SHORT, 0));
if( returned_value_type == CHAR_P )
{
@@ -12352,7 +12385,7 @@ create_and_call(size_t narg,
gg_add( member(returned.field->var_decl_node, "data"),
refer_offset_dest(returned)));
gg_assign(returned_length,
- refer_size_dest(returned));
+ gg_cast(TREE_TYPE(returned_length), refer_size_dest(returned)));
// The returned value is a string of nbytes, which by specification
// has to be at least as long as the returned_length of the target:
@@ -12442,28 +12475,9 @@ create_and_call(size_t narg,
}
else
{
- // Because no explicit returning value is expected, we switch to
- // the IBM default behavior, where the returned INT value is assigned
- // to our RETURN-CODE:
- returned_value = gg_define_variable(SHORT);
-
- // Before doing the call, we save the COBOL program_state:
- push_program_state();
- gg_assign(returned_value, gg_cast(SHORT, call_expr));
- // And after the call, we restore it:
- pop_program_state();
-
- // We know that the returned value is a 2-byte little-endian INT:
- gg_assign( var_decl_return_code,
- returned_value);
- TRACE1
- {
- TRACE1_HEADER
- gg_printf("returned value: %d",
- gg_cast(INT, var_decl_return_code),
- NULL_TREE);
- TRACE1_END
- }
+ // Because no explicit returning value is expected, we just call it. We
+ // expect COBOL routines to set RETURN-CODE when they think it necessary.
+ gg_append_statement(call_expr);
}
for( size_t i=0; i<narg; i++ )
@@ -14810,7 +14824,7 @@ mh_source_is_group( cbl_refer_t &destref,
tree dbytes = refer_size_dest(destref);
tree sbytes = tsrc.length;
- IF( sbytes, ge_op, dbytes )
+ IF( sbytes, ge_op, gg_cast(TREE_TYPE(sbytes), dbytes) )
{
// There are too many source bytes
gg_memcpy(tdest, tsource, dbytes);
@@ -16140,12 +16154,12 @@ psa_FldLiteralA(struct cbl_field_t *field )
DECL_PRESERVE_P (field->var_decl_node) = 1;
nvar += 1;
}
- TRACE1
- {
- TRACE1_INDENT
- TRACE1_TEXT("Finished")
- TRACE1_END
- }
+// TRACE1
+// {
+// TRACE1_INDENT
+// TRACE1_TEXT("Finished")
+// TRACE1_END
+// }
}
#endif
@@ -16535,24 +16549,15 @@ parser_symbol_add(struct cbl_field_t *new_var )
size_t our_index = new_var->our_index;
- // During the early stages of implementing cbl_field_t::our_index, there
- // were execution paths in parse.y and parser.cc that resulted in our_index
- // not being set. I hereby try to use field_index() to find the index
- // of this field to resolve those. I note that field_index does a linear
- // search of the symbols[] table to find that index. That's why I don't
- // use it routinely; it results in O(N^squared) computational complexity
- // to do a linear search of the symbol table for each symbol
-
if( !our_index
&& new_var->type != FldLiteralN
&& !(new_var->attr & intermediate_e))
{
- our_index = field_index(new_var);
- if( our_index == (size_t)-1 )
- {
- // Hmm. Couldn't find it. Seems odd.
- our_index = 0;
- }
+ // During the early stages of implementing cbl_field_t::our_index, there
+ // were execution paths in parse.y and parser.cc that resulted in
+ // our_index not being set. Those should be gone.
+ fprintf(stderr, "our_index is NULL under unanticipated circumstances");
+ gcc_assert(false);
}
// When we create the cblc_field_t structure, we need a data pointer
@@ -16561,7 +16566,7 @@ parser_symbol_add(struct cbl_field_t *new_var )
// we calculate data as the pointer to our parent's data plus our
// offset.
- // declare and define the structure. This code *must* match
+ // Declare and define the structure. This code *must* match
// the C structure declared in libgcobol.c. Towards that end, the
// variables are declared in descending order of size in order to
// make the packing match up.
diff --git a/gcc/cobol/genutil.cc b/gcc/cobol/genutil.cc
index d11e464..0322833 100644
--- a/gcc/cobol/genutil.cc
+++ b/gcc/cobol/genutil.cc
@@ -54,8 +54,6 @@ bool skip_exception_processing = true;
bool suppress_dest_depends = false;
-#define SET_EXCEPTION_CODE(a) do{set_exception_code((a));}while(0);
-
std::vector<std::string>current_filename;
tree var_decl_exception_code; // int __gg__exception_code;
@@ -266,6 +264,20 @@ get_integer_value(tree value,
gg_assign(value, gg_cast(TREE_TYPE(value), temp));
}
+static
+tree
+get_any_capacity(cbl_field_t *field)
+ {
+ if( field->attr & (any_length_e | intermediate_e) )
+ {
+ return member(field->var_decl_node, "capacity");
+ }
+ else
+ {
+ return build_int_cst_type(LONG, field->data.capacity);
+ }
+ }
+
static tree
get_data_offset_dest(cbl_refer_t &refer,
int *pflags = NULL)
@@ -324,45 +336,27 @@ get_data_offset_dest(cbl_refer_t &refer,
// Pick up the integer value of the subscript:
static tree subscript = gg_define_variable(LONG, "..gdod_subscript", vs_file_static);
- if( process_this_exception(ec_bound_subscript_e) )
+ get_integer_value(subscript,
+ refer.subscripts[i].field,
+ refer_offset_dest(refer.subscripts[i]),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- get_integer_value(value64,
- refer.subscripts[i].field,
- refer_offset_dest(refer.subscripts[i]),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- if( enabled_exceptions.match(ec_bound_subscript_e) )
- {
- // The subscript isn't an integer
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
- }
- else
- {
- rt_error("error: a table subscript is not an integer");
- }
- }
- ELSE
- {
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), value64));
- }
- ENDIF
+ // The subscript isn't an integer
+ set_exception_code(ec_bound_subscript_e);
}
- else
+ ELSE
{
- get_integer_value(subscript,
- refer.subscripts[i].field,
- refer_offset_dest(refer.subscripts[i]));
}
+ ENDIF
- // gg_printf("%s(): We have a subscript of %d from %s\n",
- // gg_string_literal(__func__),
- // subscript,
- // gg_string_literal(refer.subscripts[i].field->name),
- // NULL_TREE);
+// gg_printf("%s(): We have a subscript of %d from %s\n",
+// gg_string_literal(__func__),
+// subscript,
+// gg_string_literal(refer.subscripts[i].field->name),
+// NULL_TREE);
if( (refer.subscripts[i].field->attr & FIGCONST_MASK) == zero_value_e )
{
@@ -381,74 +375,46 @@ get_data_offset_dest(cbl_refer_t &refer,
// Make it zero-based:
gg_decrement(subscript);
- if( process_this_exception(ec_bound_subscript_e) )
+
+ IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), integer_zero_node) )
+ {
+ // The subscript is too small
+ set_exception_code(ec_bound_subscript_e);
+ gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 0));
+ }
+ ELSE
{
- // gg_printf("process_this_exception is true\n", NULL_TREE);
- IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), integer_zero_node) )
+ // gg_printf("parent->occurs.ntimes() is %d\n", build_int_cst_type(INT, parent->occurs.ntimes()), NULL_TREE);
+ IF( subscript,
+ ge_op,
+ build_int_cst_type(TREE_TYPE(subscript), parent->occurs.ntimes()) )
{
- // The subscript is too small
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
+ // The subscript is too large
+ set_exception_code(ec_bound_subscript_e);
+ gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 0));
}
ELSE
{
- // gg_printf("parent->occurs.ntimes() is %d\n", build_int_cst_type(INT, parent->occurs.ntimes()), NULL_TREE);
- IF( subscript,
- ge_op,
- build_int_cst_type(TREE_TYPE(subscript), parent->occurs.ntimes()) )
+ // We have a good subscript:
+ // Check for an ODO violation:
+ if( parent->occurs.depending_on )
{
- // The subscript is too large
- if( enabled_exceptions.match(ec_bound_subscript_e) )
+ cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
+ get_integer_value(value64, depending_on);
+ IF( subscript, ge_op, value64 )
{
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
- }
- else
- {
- rt_error("error: table subscript is too large");
+ gg_assign(var_decl_odo_violation, integer_one_node);
}
+ ELSE
+ ENDIF
}
- ELSE
- {
- // We have a good subscript:
- // Check for an ODO violation:
- if( parent->occurs.depending_on )
- {
- cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
- get_integer_value(value64, depending_on);
- IF( subscript, ge_op, value64 )
- {
- gg_assign(var_decl_odo_violation, integer_one_node);
- }
- ELSE
- ENDIF
- }
- tree augment = gg_multiply(subscript, build_int_cst_type(INT, parent->data.capacity));
- gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
- }
- ENDIF
+ tree augment = gg_multiply(subscript, get_any_capacity(parent));
+ gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
}
ENDIF
}
- else
- {
- // Assume a good subscript:
- // Check for an ODO violation:
- if( parent->occurs.depending_on )
- {
- cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
- get_integer_value(value64, depending_on);
- IF( subscript, ge_op, value64 )
- {
- gg_assign(var_decl_odo_violation, integer_one_node);
- }
- ELSE
- ENDIF
- }
- tree augment = gg_multiply(subscript, build_int_cst_type(INT, parent->data.capacity));
- gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
- }
+ ENDIF
parent = parent_of(parent);
}
}
@@ -458,76 +424,40 @@ get_data_offset_dest(cbl_refer_t &refer,
// We have a refmod to deal with
static tree refstart = gg_define_variable(LONG, "..gdos_refstart", vs_file_static);
- if( process_this_exception(ec_bound_ref_mod_e) )
- {
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- // refmod offset is not an integer, and has to be
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("error: a refmod FROM is not an integer");
- }
- }
- ELSE
- gg_assign(refstart, value64);
- ENDIF
- }
- else
+ get_integer_value(refstart,
+ refer.refmod.from->field,
+ refer_offset_source(*refer.refmod.from),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from)
- );
- gg_assign(refstart, value64);
+ // refmod offset is not an integer, and has to be
+ set_exception_code(ec_bound_ref_mod_e);
}
+ ELSE
+ ENDIF
// Make refstart zero-based:
gg_decrement(refstart);
- if( process_this_exception(ec_bound_ref_mod_e) )
+ IF( refstart, lt_op, gg_cast(LONG, integer_zero_node) )
+ {
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, build_int_cst_type(TREE_TYPE(refstart), 0));
+ }
+ ELSE
{
- IF( refstart, lt_op, gg_cast(LONG, integer_zero_node) )
+ tree capacity = get_any_capacity(refer.field);
+ IF( refstart, gt_op, gg_cast(LONG, capacity) )
{
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- }
- else
- {
- rt_error("error: refmod FROM is less than one");
- }
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, build_int_cst_type(TREE_TYPE(refstart), 0));
}
ELSE
- {
- IF( refstart, gt_op, build_int_cst_type(LONG, refer.field->data.capacity) )
- {
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- }
- else
- {
- rt_error("error: refmod FROM is too large");
- }
- }
- ELSE
- ENDIF
- }
ENDIF
}
+ ENDIF
// We have a good refstart
gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, refstart)));
@@ -601,42 +531,23 @@ get_data_offset_source(cbl_refer_t &refer,
cbl_internal_error("Too many subscripts");
}
// Pick up the integer value of the subscript:
-// static tree subscript = gg_define_variable(LONG, "..gdos_subscript", vs_file_static);
tree subscript = gg_define_variable(LONG);
- if( process_this_exception(ec_bound_subscript_e) )
+ get_integer_value(subscript,
+ refer.subscripts[i].field,
+ refer_offset_source(refer.subscripts[i]),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- get_integer_value(value64,
- refer.subscripts[i].field,
- refer_offset_source(refer.subscripts[i]),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- if( enabled_exceptions.match(ec_bound_subscript_e) )
- {
- // The subscript isn't an integer
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
- }
- else
- {
- rt_error("error: a table subscript is not an integer");
- }
- }
- ELSE
- {
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), value64));
- }
- ENDIF
+ // The subscript isn't an integer
+ set_exception_code(ec_bound_subscript_e);
}
- else
+ ELSE
{
- get_integer_value(subscript,
- refer.subscripts[i].field,
- refer_offset_source(refer.subscripts[i]));
}
+ ENDIF
// gg_printf("%s(): We have a subscript of %d from %s\n",
// gg_string_literal(__func__),
@@ -661,74 +572,46 @@ get_data_offset_source(cbl_refer_t &refer,
// Make it zero-based:
gg_decrement(subscript);
- if( process_this_exception(ec_bound_subscript_e) )
+ // gg_printf("process_this_exception is true\n", NULL_TREE);
+ IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), integer_zero_node) )
+ {
+ // The subscript is too small
+ set_exception_code(ec_bound_subscript_e);
+ gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 0));
+ }
+ ELSE
{
- // gg_printf("process_this_exception is true\n", NULL_TREE);
- IF( subscript, lt_op, gg_cast(TREE_TYPE(subscript), integer_zero_node) )
+ // gg_printf("parent->occurs.ntimes() is %d\n", build_int_cst_type(INT, parent->occurs.ntimes()), NULL_TREE);
+ IF( subscript,
+ ge_op,
+ build_int_cst_type(TREE_TYPE(subscript), parent->occurs.ntimes()) )
{
- // The subscript is too small
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
+ // The subscript is too large
+ set_exception_code(ec_bound_subscript_e);
+ gg_assign(subscript, build_int_cst_type(TREE_TYPE(subscript), 0));
}
ELSE
{
- // gg_printf("parent->occurs.ntimes() is %d\n", build_int_cst_type(INT, parent->occurs.ntimes()), NULL_TREE);
- IF( subscript,
- ge_op,
- build_int_cst_type(TREE_TYPE(subscript), parent->occurs.ntimes()) )
+ // We have a good subscript:
+ // Check for an ODO violation:
+ if( parent->occurs.depending_on )
{
- // The subscript is too large
- if( enabled_exceptions.match(ec_bound_subscript_e) )
+ cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
+ get_integer_value(value64, depending_on);
+ IF( subscript, ge_op, value64 )
{
- SET_EXCEPTION_CODE(ec_bound_subscript_e);
- gg_assign(subscript, gg_cast(TREE_TYPE(subscript), integer_zero_node));
- }
- else
- {
- rt_error("error: table subscript is too large");
+ gg_assign(var_decl_odo_violation, integer_one_node);
}
+ ELSE
+ ENDIF
}
- ELSE
- {
- // We have a good subscript:
- // Check for an ODO violation:
- if( parent->occurs.depending_on )
- {
- cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
- get_integer_value(value64, depending_on);
- IF( subscript, ge_op, value64 )
- {
- gg_assign(var_decl_odo_violation, integer_one_node);
- }
- ELSE
- ENDIF
- }
- tree augment = gg_multiply(subscript, build_int_cst_type(INT, parent->data.capacity));
- gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
- }
- ENDIF
+ tree augment = gg_multiply(subscript, get_any_capacity(parent));
+ gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
}
ENDIF
}
- else
- {
- // Assume a good subscript:
- // Check for an ODO violation:
- if( parent->occurs.depending_on )
- {
- cbl_field_t *depending_on = cbl_field_of(symbol_at(parent->occurs.depending_on));
- get_integer_value(value64, depending_on);
- IF( subscript, ge_op, value64 )
- {
- gg_assign(var_decl_odo_violation, integer_one_node);
- }
- ELSE
- ENDIF
- }
- tree augment = gg_multiply(subscript, build_int_cst_type(INT, parent->data.capacity));
- gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, augment)));
- }
+ ENDIF
parent = parent_of(parent);
}
}
@@ -738,76 +621,40 @@ get_data_offset_source(cbl_refer_t &refer,
// We have a refmod to deal with
static tree refstart = gg_define_variable(LONG, "..gdo_refstart", vs_file_static);
- if( process_this_exception(ec_bound_ref_mod_e) )
- {
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- // refmod offset is not an integer, and has to be
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("error: a refmod FROM is not an integer");
- }
- }
- ELSE
- gg_assign(refstart, value64);
- ENDIF
- }
- else
+ get_integer_value(refstart,
+ refer.refmod.from->field,
+ refer_offset_source(*refer.refmod.from),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from)
- );
- gg_assign(refstart, value64);
+ // refmod offset is not an integer, and has to be
+ set_exception_code(ec_bound_ref_mod_e);
}
+ ELSE
+ ENDIF
// Make refstart zero-based:
gg_decrement(refstart);
- if( process_this_exception(ec_bound_ref_mod_e) )
+ IF( refstart, lt_op, gg_cast(LONG, integer_zero_node) )
{
- IF( refstart, lt_op, gg_cast(LONG, integer_zero_node) )
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, gg_cast(LONG, integer_zero_node));
+ }
+ ELSE
+ {
+ tree capacity = get_any_capacity(refer.field);
+ IF( refstart, gt_op, gg_cast(LONG, capacity) )
{
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- }
- else
- {
- rt_error("error: refmod FROM is less than one");
- }
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, build_int_cst_type(TREE_TYPE(refstart), 0));
}
ELSE
- {
- IF( refstart, gt_op, build_int_cst_type(LONG, refer.field->data.capacity) )
- {
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- }
- else
- {
- rt_error("error: refmod FROM is too large");
- }
- }
- ELSE
- ENDIF
- }
ENDIF
}
+ ENDIF
// We have a good refstart
gg_assign(retval, gg_add(retval, gg_cast(SIZE_T, refstart)));
@@ -933,7 +780,7 @@ get_binary_value( tree value,
// This is the we-are-done pointer
gg_assign(pend, gg_add( pointer,
- build_int_cst_type(SIZE_T, field->data.capacity)));
+ get_any_capacity(field)));
static tree signbyte = gg_define_variable(UCHAR, "..gbv_signbyte", vs_file_static);
@@ -2123,193 +1970,105 @@ refer_refmod_length(cbl_refer_t &refer)
if( refer.refmod.from || refer.refmod.len )
{
// First, check for compile-time errors
- bool any_length = !!(refer.field->attr & any_length_e);
- tree rt_capacity;
- static tree value64 = gg_define_variable(LONG, "..rrl_value64", vs_file_static);
static tree refstart = gg_define_variable(LONG, "..rrl_refstart", vs_file_static);
static tree reflen = gg_define_variable(LONG, "..rrl_reflen", vs_file_static);
- if( any_length )
- {
- rt_capacity =
- gg_cast(LONG,
- member(refer.field->var_decl_node, "capacity"));
- }
- else
- {
- rt_capacity =
- build_int_cst_type(LONG, refer.field->data.capacity);
- }
+ tree rt_capacity = get_any_capacity(refer.field);
gg_assign(reflen, gg_cast(TREE_TYPE(reflen), integer_one_node));
- if( process_this_exception(ec_bound_ref_mod_e) )
- {
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("a refmod FROM value is not an integer");
- }
- }
- ELSE
- gg_assign(refstart, value64);
- ENDIF
- }
- else
+ get_integer_value(refstart,
+ refer.refmod.from->field,
+ refer_offset_source(*refer.refmod.from),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- get_integer_value(value64,
- refer.refmod.from->field,
- refer_offset_source(*refer.refmod.from)
- );
- gg_assign(refstart, value64);
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, gg_cast(LONG, integer_one_node));
}
+ ELSE
+ ENDIF
// Make refstart zero-based:
gg_decrement(refstart);
- if( process_this_exception(ec_bound_ref_mod_e) )
+ IF( refstart, lt_op, build_int_cst_type(LONG, 0 ) )
{
- IF( refstart, lt_op, build_int_cst_type(LONG, 0 ) )
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, gg_cast(LONG, integer_zero_node));
+ }
+ ELSE
+ {
+ IF( refstart, gt_op, gg_cast(TREE_TYPE(refstart), rt_capacity) )
{
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- }
- else
- {
- rt_error("a refmod FROM value is less than zero");
- }
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(refstart, gg_cast(LONG, integer_zero_node));
}
ELSE
{
- IF( refstart, gt_op, rt_capacity )
+ if( refer.refmod.len )
{
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
+ get_integer_value(reflen,
+ refer.refmod.len->field,
+ refer_offset_source(*refer.refmod.len),
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits,
+ ne_op,
+ integer_zero_node )
{
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
+ // length is not an integer
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(reflen, gg_cast(LONG, integer_one_node));
}
- else
+ ELSE
{
- rt_error("a refmod FROM value is too large");
}
- }
- ELSE
- {
- if( refer.refmod.len )
- {
- get_integer_value(value64,
- refer.refmod.len->field,
- refer_offset_source(*refer.refmod.len),
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits,
- ne_op,
- integer_zero_node )
- {
- // length is not an integer
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(reflen, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("a refmod LENGTH is not an integer");
- }
- }
- ELSE
- {
- gg_assign(reflen, gg_cast(LONG, value64));
- }
- ENDIF
+ ENDIF
- IF( reflen, lt_op, gg_cast(LONG, integer_one_node) )
+ IF( reflen, lt_op, gg_cast(LONG, integer_one_node) )
+ {
+ // length is too small
+ set_exception_code(ec_bound_ref_mod_e);
+ gg_assign(reflen, gg_cast(LONG, integer_one_node));
+ }
+ ELSE
+ {
+ IF( gg_add(refstart, reflen),
+ gt_op,
+ gg_cast(TREE_TYPE(refstart), rt_capacity) )
{
- // length is too small
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
- gg_assign(reflen, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("a refmod LENGTH is less than one");
- }
+ // Start + Length is too large
+ set_exception_code(ec_bound_ref_mod_e);
+
+ // Our intentions are honorable. But at this point, where
+ // we notice that start + length is too long, the
+ // get_data_offset_source routine has already been run and
+ // it's too late to actually change the refstart. There are
+ // theoretical solutions to this -- mainly,
+ // get_data_offset_source needs to check the start + len for
+ // validity. But I am not going to do it now. Think of this
+ // as the TODO item.
+ gg_assign(refstart, gg_cast(LONG, integer_zero_node));
+ gg_assign(reflen, gg_cast(LONG, integer_one_node));
}
ELSE
- {
- IF( gg_add(refstart, reflen),
- gt_op,
- rt_capacity )
- {
- // Start + Length is too large
- if( enabled_exceptions.match(ec_bound_ref_mod_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_ref_mod_e);
-
- // Our intentions are honorable. But at this point, where
- // we notice that start + length is too long, the
- // get_data_offset_source routine has already been run and
- // it's too late to actually change the refstart. There are
- // theoretical solutions to this -- mainly,
- // get_data_offset_source needs to check the start + len for
- // validity. But I am not going to do it now. Think of this
- // as the TODO item.
- gg_assign(refstart, gg_cast(LONG, integer_zero_node));
- gg_assign(reflen, gg_cast(LONG, integer_one_node));
- }
- else
- {
- rt_error("refmod START + LENGTH is too large");
- }
- }
- ELSE
- ENDIF
- }
ENDIF
}
- else
- {
- // There is no refmod length, so we default to the remaining characters
- tree subtract_expr = gg_subtract( rt_capacity,
- refstart);
- gg_assign(reflen, subtract_expr);
- }
+ ENDIF
+ }
+ else
+ {
+ // There is no refmod length, so we default to the remaining characters
+ tree subtract_expr = gg_subtract( rt_capacity,
+ refstart);
+ gg_assign(reflen, subtract_expr);
}
- ENDIF
}
ENDIF
}
- else
- {
- if( refer.refmod.len )
- {
- get_integer_value(value64,
- refer.refmod.len->field,
- refer_offset_source(*refer.refmod.len)
- );
- gg_assign(reflen, gg_cast(LONG, value64));
- }
- else
- {
- // There is no refmod length, so we default to the remaining characters
- gg_assign(reflen, gg_subtract(rt_capacity,
- refstart));
- }
- }
+ ENDIF
// Arrive here with valid values for refstart and reflen:
@@ -2346,73 +2105,42 @@ refer_fill_depends(cbl_refer_t &refer)
// depending_on->name);
static tree value64 = gg_define_variable(LONG, "..rfd_value64", vs_file_static);
- if( process_this_exception(ec_bound_odo_e) )
+ get_integer_value(value64,
+ depending_on,
+ NULL,
+ CHECK_FOR_FRACTIONAL_DIGITS);
+ IF( var_decl_rdigits, ne_op, integer_zero_node )
{
- get_integer_value(value64,
- depending_on,
- NULL,
- CHECK_FOR_FRACTIONAL_DIGITS);
- IF( var_decl_rdigits, ne_op, integer_zero_node )
- {
- // This needs to evaluate to an integer
- if( enabled_exceptions.match(ec_bound_odo_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper));
- }
- else
- {
- rt_error("DEPENDING ON is not an integer");
- }
- }
- ELSE
- ENDIF
+ // This needs to evaluate to an integer
+ set_exception_code(ec_bound_odo_e);
+ gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper));
}
- else
+ ELSE
+ ENDIF
+
+ IF( value64, gt_op, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper) )
{
- get_integer_value(value64, depending_on);
+ set_exception_code(ec_bound_odo_e);
+ gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper));
}
-
- if( process_this_exception(ec_bound_odo_e) )
+ ELSE
{
- IF( value64, gt_op, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper) )
+ IF( value64, lt_op, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.lower) )
{
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.upper));
+ set_exception_code(ec_bound_odo_e);
+ gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.lower));
}
ELSE
+ ENDIF
+ IF( value64, lt_op, gg_cast(TREE_TYPE(value64), integer_zero_node) )
{
- IF( value64, lt_op, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.lower) )
- {
- if( enabled_exceptions.match(ec_bound_odo_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- gg_assign(value64, build_int_cst_type(TREE_TYPE(value64), odo->occurs.bounds.lower));
- }
- else
- {
- rt_error("DEPENDING ON is less than OCCURS lower limit");
- }
- }
- ELSE
- ENDIF
- IF( value64, lt_op, gg_cast(TREE_TYPE(value64), integer_zero_node) )
- {
- if( enabled_exceptions.match(ec_bound_odo_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- gg_assign(value64, gg_cast(TREE_TYPE(value64), integer_zero_node));
- }
- else
- {
- rt_error("DEPENDING ON is greater than OCCURS upper limit");
- }
- }
- ELSE
- ENDIF
+ set_exception_code(ec_bound_odo_e);
+ gg_assign(value64, gg_cast(TREE_TYPE(value64), integer_zero_node));
}
+ ELSE
ENDIF
}
+ ENDIF
// value64 is >= zero and < bounds.upper
// We multiply the ODO value by the size of the data capacity to get the
@@ -2448,22 +2176,12 @@ refer_offset_dest(cbl_refer_t &refer)
tree retval = gg_define_variable(SIZE_T);
gg_assign(retval, get_data_offset_dest(refer));
- if( process_this_exception(ec_bound_odo_e) )
+ IF( var_decl_odo_violation, ne_op, integer_zero_node )
{
- IF( var_decl_odo_violation, ne_op, integer_zero_node )
- {
- if( enabled_exceptions.match(ec_bound_odo_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- }
- else
- {
- rt_error("receiving item subscript not in DEPENDING ON range");
- }
- }
- ELSE
- ENDIF
+ set_exception_code(ec_bound_odo_e);
}
+ ELSE
+ ENDIF
return retval;
}
@@ -2482,14 +2200,7 @@ refer_size_dest(cbl_refer_t &refer)
{
// When the refer has no modifications, we return zero, which is interpreted
// as "use the original length"
- if( refer.field->attr & (intermediate_e | any_length_e) )
- {
- return member(refer.field->var_decl_node, "capacity");
- }
- else
- {
- return build_int_cst_type(SIZE_T, refer.field->data.capacity);
- }
+ return get_any_capacity(refer.field);
}
// Step the first: Get the actual full length:
@@ -2546,22 +2257,12 @@ refer_offset_source(cbl_refer_t &refer,
gg_assign(var_decl_odo_violation, integer_zero_node);
gg_assign(retval, get_data_offset_source(refer, pflags));
- if( process_this_exception(ec_bound_odo_e) )
+ IF( var_decl_odo_violation, ne_op, integer_zero_node )
{
- IF( var_decl_odo_violation, ne_op, integer_zero_node )
- {
- if( enabled_exceptions.match(ec_bound_odo_e) )
- {
- SET_EXCEPTION_CODE(ec_bound_odo_e);
- }
- else
- {
- rt_error("sending item subscript not in DEPENDING ON range");
- }
- }
- ELSE
- ENDIF
+ set_exception_code(ec_bound_odo_e);
}
+ ELSE
+ ENDIF
return retval;
}
diff --git a/gcc/common.opt b/gcc/common.opt
index 88d987e..e3fa0da 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2279,9 +2279,6 @@ Enum
Name(lto_partition_model) Type(enum lto_partition_model) UnknownError(unknown LTO partitioning model %qs)
EnumValue
-Enum(lto_partition_model) String(default) Value(LTO_PARTITION_DEFAULT)
-
-EnumValue
Enum(lto_partition_model) String(none) Value(LTO_PARTITION_NONE)
EnumValue
@@ -2300,7 +2297,7 @@ EnumValue
Enum(lto_partition_model) String(cache) Value(LTO_PARTITION_CACHE)
flto-partition=
-Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_DEFAULT)
+Common Joined RejectNegative Enum(lto_partition_model) Var(flag_lto_partition) Init(LTO_PARTITION_BALANCED)
Specify the algorithm to partition symbols and vars at linktime.
; The initial value of -1 comes from Z_DEFAULT_COMPRESSION in zlib.h.
diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
index 38c112c..f7bccf5 100644
--- a/gcc/config/aarch64/aarch64.cc
+++ b/gcc/config/aarch64/aarch64.cc
@@ -9417,13 +9417,16 @@ aarch64_emit_stack_tie (rtx reg)
}
/* Allocate POLY_SIZE bytes of stack space using TEMP1 and TEMP2 as scratch
- registers. If POLY_SIZE is not large enough to require a probe this function
- will only adjust the stack. When allocating the stack space
- FRAME_RELATED_P is then used to indicate if the allocation is frame related.
- FINAL_ADJUSTMENT_P indicates whether we are allocating the area below
- the saved registers. If we are then we ensure that any allocation
- larger than the ABI defined buffer needs a probe so that the
- invariant of having a 1KB buffer is maintained.
+ registers, given that the stack pointer is currently BYTES_BELOW_SP bytes
+ above the bottom of the static frame.
+
+ If POLY_SIZE is not large enough to require a probe this function will only
+ adjust the stack. When allocating the stack space FRAME_RELATED_P is then
+ used to indicate if the allocation is frame related. FINAL_ADJUSTMENT_P
+ indicates whether we are allocating the area below the saved registers.
+ If we are then we ensure that any allocation larger than the ABI defined
+ buffer needs a probe so that the invariant of having a 1KB buffer is
+ maintained.
We emit barriers after each stack adjustment to prevent optimizations from
breaking the invariant that we never drop the stack more than a page. This
@@ -9440,6 +9443,7 @@ aarch64_emit_stack_tie (rtx reg)
static void
aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
poly_int64 poly_size,
+ poly_int64 bytes_below_sp,
aarch64_isa_mode force_isa_mode,
bool frame_related_p,
bool final_adjustment_p)
@@ -9503,8 +9507,8 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
poly_size, temp1, temp2, force_isa_mode,
false, true);
- rtx_insn *insn = get_last_insn ();
-
+ auto initial_cfa_offset = frame.frame_size - bytes_below_sp;
+ auto final_cfa_offset = initial_cfa_offset + poly_size;
if (frame_related_p)
{
/* This is done to provide unwinding information for the stack
@@ -9514,28 +9518,31 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
The tie will expand to nothing but the optimizers will not touch
the instruction. */
rtx stack_ptr_copy = gen_rtx_REG (Pmode, STACK_CLASH_SVE_CFA_REGNUM);
- emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
+ auto *insn = emit_move_insn (stack_ptr_copy, stack_pointer_rtx);
aarch64_emit_stack_tie (stack_ptr_copy);
/* We want the CFA independent of the stack pointer for the
duration of the loop. */
- add_reg_note (insn, REG_CFA_DEF_CFA, stack_ptr_copy);
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ plus_constant (Pmode, stack_ptr_copy,
+ initial_cfa_offset));
RTX_FRAME_RELATED_P (insn) = 1;
}
rtx probe_const = gen_int_mode (min_probe_threshold, Pmode);
rtx guard_const = gen_int_mode (guard_size, Pmode);
- insn = emit_insn (gen_probe_sve_stack_clash (Pmode, stack_pointer_rtx,
- stack_pointer_rtx, temp1,
- probe_const, guard_const));
+ auto *insn
+ = emit_insn (gen_probe_sve_stack_clash (Pmode, stack_pointer_rtx,
+ stack_pointer_rtx, temp1,
+ probe_const, guard_const));
/* Now reset the CFA register if needed. */
if (frame_related_p)
{
add_reg_note (insn, REG_CFA_DEF_CFA,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- gen_int_mode (poly_size, Pmode)));
+ plus_constant (Pmode, stack_pointer_rtx,
+ final_cfa_offset));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9581,12 +9588,13 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
We can determine which allocation we are doing by looking at
the value of FRAME_RELATED_P since the final allocations are not
frame related. */
+ auto cfa_offset = frame.frame_size - (bytes_below_sp - rounded_size);
if (frame_related_p)
{
/* We want the CFA independent of the stack pointer for the
duration of the loop. */
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (Pmode, temp1, rounded_size));
+ plus_constant (Pmode, temp1, cfa_offset));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9608,7 +9616,7 @@ aarch64_allocate_and_probe_stack_space (rtx temp1, rtx temp2,
if (frame_related_p)
{
add_reg_note (insn, REG_CFA_DEF_CFA,
- plus_constant (Pmode, stack_pointer_rtx, rounded_size));
+ plus_constant (Pmode, stack_pointer_rtx, cfa_offset));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9916,17 +9924,22 @@ aarch64_expand_prologue (void)
code below does not handle it for -fstack-clash-protection. */
gcc_assert (known_eq (initial_adjust, 0) || callee_adjust == 0);
+ /* The offset of the current SP from the bottom of the static frame. */
+ poly_int64 bytes_below_sp = frame_size;
+
/* Will only probe if the initial adjustment is larger than the guard
less the amount of the guard reserved for use by the caller's
outgoing args. */
aarch64_allocate_and_probe_stack_space (tmp0_rtx, tmp1_rtx, initial_adjust,
- force_isa_mode, true, false);
+ bytes_below_sp, force_isa_mode,
+ true, false);
+ bytes_below_sp -= initial_adjust;
if (callee_adjust != 0)
- aarch64_push_regs (reg1, reg2, callee_adjust);
-
- /* The offset of the current SP from the bottom of the static frame. */
- poly_int64 bytes_below_sp = frame_size - initial_adjust - callee_adjust;
+ {
+ aarch64_push_regs (reg1, reg2, callee_adjust);
+ bytes_below_sp -= callee_adjust;
+ }
if (emit_frame_chain)
{
@@ -9994,7 +10007,7 @@ aarch64_expand_prologue (void)
|| known_eq (frame.reg_offset[VG_REGNUM], bytes_below_sp));
aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx,
sve_callee_adjust,
- force_isa_mode,
+ bytes_below_sp, force_isa_mode,
!frame_pointer_needed, false);
bytes_below_sp -= sve_callee_adjust;
}
@@ -10005,10 +10018,11 @@ aarch64_expand_prologue (void)
/* We may need to probe the final adjustment if it is larger than the guard
that is assumed by the called. */
- gcc_assert (known_eq (bytes_below_sp, final_adjust));
aarch64_allocate_and_probe_stack_space (tmp1_rtx, tmp0_rtx, final_adjust,
- force_isa_mode,
+ bytes_below_sp, force_isa_mode,
!frame_pointer_needed, true);
+ bytes_below_sp -= final_adjust;
+ gcc_assert (known_eq (bytes_below_sp, 0));
if (emit_frame_chain && maybe_ne (final_adjust, 0))
aarch64_emit_stack_tie (hard_frame_pointer_rtx);
diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc
index 3b4dfd9..78df3d9 100644
--- a/gcc/config/i386/i386.cc
+++ b/gcc/config/i386/i386.cc
@@ -25375,14 +25375,32 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
case COND_EXPR:
{
/* SSE2 conditinal move sequence is:
- pcmpgtd %xmm5, %xmm0
+ pcmpgtd %xmm5, %xmm0 (accounted separately)
pand %xmm0, %xmm2
pandn %xmm1, %xmm0
por %xmm2, %xmm0
while SSE4 uses cmp + blend
- and AVX512 masked moves. */
-
- int ninsns = TARGET_SSE4_1 ? 2 : 4;
+ and AVX512 masked moves.
+
+ The condition is accounted separately since we usually have
+ p = a < b
+ c = p ? x : y
+ and we will account first statement as setcc. Exception is when
+ p is loaded from memory as bool and then we will not acocunt
+ the compare, but there is no way to check for this. */
+
+ int ninsns = TARGET_SSE4_1 ? 1 : 3;
+
+ /* If one of parameters is 0 or -1 the sequence will be simplified:
+ (if_true & mask) | (if_false & ~mask) -> if_true & mask */
+ if (ninsns > 1
+ && (zerop (gimple_assign_rhs2 (stmt_info->stmt))
+ || zerop (gimple_assign_rhs3 (stmt_info->stmt))
+ || integer_minus_onep
+ (gimple_assign_rhs2 (stmt_info->stmt))
+ || integer_minus_onep
+ (gimple_assign_rhs3 (stmt_info->stmt))))
+ ninsns = 1;
if (SSE_FLOAT_MODE_SSEMATH_OR_HFBF_P (mode))
stmt_cost = ninsns * ix86_cost->sse_op;
@@ -25393,8 +25411,8 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
else if (VECTOR_MODE_P (mode))
stmt_cost = ix86_vec_cost (mode, ninsns * ix86_cost->sse_op);
else
- /* compare + cmov. */
- stmt_cost = ix86_cost->add * 2;
+ /* compare (accounted separately) + cmov. */
+ stmt_cost = ix86_cost->add;
}
break;
@@ -25416,9 +25434,18 @@ ix86_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
{
stmt_cost = ix86_vec_cost (mode, ix86_cost->sse_op);
/* vpmin was introduced in SSE3.
- SSE2 needs pcmpgtd + pand + pandn + pxor. */
+ SSE2 needs pcmpgtd + pand + pandn + pxor.
+ If one of parameters is 0 or -1 the sequence is simplified
+ to pcmpgtd + pand. */
if (!TARGET_SSSE3)
- stmt_cost *= 4;
+ {
+ if (zerop (gimple_assign_rhs2 (stmt_info->stmt))
+ || integer_minus_onep
+ (gimple_assign_rhs2 (stmt_info->stmt)))
+ stmt_cost *= 2;
+ else
+ stmt_cost *= 4;
+ }
}
else
/* cmp + cmov. */
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index d82b16e..0e9140e 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -14496,7 +14496,21 @@ s390_call_saved_register_used (tree call_expr)
for (reg = 0; reg < nregs; reg++)
if (!call_used_or_fixed_reg_p (reg + REGNO (parm_rtx)))
- return true;
+ {
+ rtx parm;
+ /* Allow passing through unmodified value from caller,
+ see PR119873. */
+ if (TREE_CODE (parameter) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (parameter)
+ && SSA_NAME_VAR (parameter)
+ && TREE_CODE (SSA_NAME_VAR (parameter)) == PARM_DECL
+ && (parm = DECL_INCOMING_RTL (SSA_NAME_VAR (parameter)))
+ && REG_P (parm)
+ && REGNO (parm) == REGNO (parm_rtx)
+ && REG_NREGS (parm) == REG_NREGS (parm_rtx))
+ break;
+ return true;
+ }
}
else if (GET_CODE (parm_rtx) == PARALLEL)
{
@@ -14543,8 +14557,9 @@ s390_function_ok_for_sibcall (tree decl, tree exp)
return false;
/* Register 6 on s390 is available as an argument register but unfortunately
- "caller saved". This makes functions needing this register for arguments
- not suitable for sibcalls. */
+ "caller saved". This makes functions needing this register for arguments
+ not suitable for sibcalls, unless the same value is passed from the
+ caller. */
return !s390_call_saved_register_used (exp);
}
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d9f0298..cd128e2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2025-04-24 Jason Merrill <jason@redhat.com>
+
+ PR c++/116954
+ * contracts.cc (remove_contract_attributes): Return early if
+ not enabled.
+
2025-04-22 Nathaniel Shead <nathanieloshead@gmail.com>
* name-lookup.cc (lookup_imported_hidden_friend): Remove
diff --git a/gcc/cp/contracts.cc b/gcc/cp/contracts.cc
index 3ca2102..d0cfd2e 100644
--- a/gcc/cp/contracts.cc
+++ b/gcc/cp/contracts.cc
@@ -860,6 +860,9 @@ cp_contract_assertion_p (const_tree attr)
void
remove_contract_attributes (tree fndecl)
{
+ if (!flag_contracts)
+ return;
+
tree list = NULL_TREE;
for (tree p = DECL_ATTRIBUTES (fndecl); p; p = TREE_CHAIN (p))
if (!cxx_contract_attribute_p (p))
diff --git a/gcc/dwarf2out.cc b/gcc/dwarf2out.cc
index 69e9d77..34ffeed 100644
--- a/gcc/dwarf2out.cc
+++ b/gcc/dwarf2out.cc
@@ -1536,7 +1536,7 @@ loc_descr_equal_p_1 (dw_loc_descr_ref a, dw_loc_descr_ref b)
/* ??? This is only ever set for DW_OP_constNu, for N equal to the
address size, but since we always allocate cleared storage it
should be zero for other types of locations. */
- if (a->dtprel != b->dtprel)
+ if (a->dw_loc_dtprel != b->dw_loc_dtprel)
return false;
return (dw_val_equal_p (&a->dw_loc_oprnd1, &b->dw_loc_oprnd1)
@@ -2115,7 +2115,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
dw2_asm_output_data (2, val1->v.val_int, NULL);
break;
case DW_OP_const4u:
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
{
gcc_assert (targetm.asm_out.output_dwarf_dtprel);
targetm.asm_out.output_dwarf_dtprel (asm_out_file, 4,
@@ -2128,7 +2128,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
dw2_asm_output_data (4, val1->v.val_int, NULL);
break;
case DW_OP_const8u:
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
{
gcc_assert (targetm.asm_out.output_dwarf_dtprel);
targetm.asm_out.output_dwarf_dtprel (asm_out_file, 8,
@@ -2323,7 +2323,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
break;
case DW_OP_addr:
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
{
if (targetm.asm_out.output_dwarf_dtprel)
{
@@ -4028,7 +4028,7 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
ref->dw_loc_oprnd1.val_class = dw_val_class_addr;
ref->dw_loc_oprnd1.v.val_addr = addr;
- ref->dtprel = dtprel;
+ ref->dw_loc_dtprel = dtprel;
if (dwarf_split_debug_info)
ref->dw_loc_oprnd1.val_entry
= add_addr_table_entry (addr,
@@ -7036,7 +7036,7 @@ loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx)
inchash::hash hstate;
hashval_t hash;
- tem = (loc->dtprel << 8) | ((unsigned int) loc->dw_loc_opc);
+ tem = (loc->dw_loc_dtprel << 8) | ((unsigned int) loc->dw_loc_opc);
CHECKSUM (tem);
hash_loc_operands (loc, hstate);
hash = hstate.end();
@@ -7259,7 +7259,7 @@ loc_checksum_ordered (dw_loc_descr_ref loc, struct md5_ctx *ctx)
inchash::hash hstate;
hashval_t hash;
- CHECKSUM_ULEB128 (loc->dtprel);
+ CHECKSUM_ULEB128 (loc->dw_loc_dtprel);
CHECKSUM_ULEB128 (loc->dw_loc_opc);
hash_loc_operands (loc, hstate);
hash = hstate.end ();
@@ -18310,7 +18310,7 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
/* If needed, relocate the picking offset with respect to the frame
offset. */
- if (l->frame_offset_rel)
+ if (l->dw_loc_frame_offset_rel)
{
unsigned HOST_WIDE_INT off;
switch (l->dw_loc_opc)
@@ -18826,7 +18826,7 @@ loc_list_from_tree_1 (tree loc, int want_address,
&& want_address == 0)
{
ret = new_loc_descr (DW_OP_pick, 0, 0);
- ret->frame_offset_rel = 1;
+ ret->dw_loc_frame_offset_rel = 1;
context->placeholder_seen = true;
break;
}
@@ -18993,7 +18993,7 @@ loc_list_from_tree_1 (tree loc, int want_address,
gcc_assert (cursor != NULL_TREE);
ret = new_loc_descr (DW_OP_pick, i, 0);
- ret->frame_offset_rel = 1;
+ ret->dw_loc_frame_offset_rel = 1;
break;
}
/* FALLTHRU */
@@ -31061,7 +31061,7 @@ resolve_addr_in_expr (dw_attr_node *a, dw_loc_descr_ref loc)
|| loc->dw_loc_opc == DW_OP_addrx)
|| ((loc->dw_loc_opc == DW_OP_GNU_const_index
|| loc->dw_loc_opc == DW_OP_constx)
- && loc->dtprel))
+ && loc->dw_loc_dtprel))
{
rtx rtl = loc->dw_loc_oprnd1.val_entry->addr.rtl;
if (!resolve_one_addr (&rtl))
@@ -31073,7 +31073,7 @@ resolve_addr_in_expr (dw_attr_node *a, dw_loc_descr_ref loc)
break;
case DW_OP_const4u:
case DW_OP_const8u:
- if (loc->dtprel
+ if (loc->dw_loc_dtprel
&& !resolve_one_addr (&loc->dw_loc_oprnd1.v.val_addr))
return false;
break;
@@ -31359,8 +31359,12 @@ copy_deref_exprloc (dw_loc_descr_ref expr)
while (expr != l)
{
*p = new_loc_descr (expr->dw_loc_opc, 0, 0);
- (*p)->dw_loc_oprnd1 = expr->dw_loc_oprnd1;
- (*p)->dw_loc_oprnd2 = expr->dw_loc_oprnd2;
+ (*p)->dw_loc_oprnd1.val_class = expr->dw_loc_oprnd1.val_class;
+ (*p)->dw_loc_oprnd1.val_entry = expr->dw_loc_oprnd1.val_entry;
+ (*p)->dw_loc_oprnd1.v = expr->dw_loc_oprnd1.v;
+ (*p)->dw_loc_oprnd2.val_class = expr->dw_loc_oprnd2.val_class;
+ (*p)->dw_loc_oprnd2.val_entry = expr->dw_loc_oprnd2.val_entry;
+ (*p)->dw_loc_oprnd2.v = expr->dw_loc_oprnd2.v;
p = &(*p)->dw_loc_next;
expr = expr->dw_loc_next;
}
@@ -31451,7 +31455,9 @@ optimize_string_length (dw_attr_node *a)
copy over the DW_AT_location attribute from die to a. */
if (l->dw_loc_next != NULL)
{
- a->dw_attr_val = av->dw_attr_val;
+ a->dw_attr_val.val_class = av->dw_attr_val.val_class;
+ a->dw_attr_val.val_entry = av->dw_attr_val.val_entry;
+ a->dw_attr_val.v = av->dw_attr_val.v;
return 1;
}
@@ -31737,7 +31743,7 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
{
case DW_OP_const4u:
case DW_OP_const8u:
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
goto hash_addr;
/* FALLTHRU */
case DW_OP_const1u:
@@ -31839,7 +31845,7 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
break;
case DW_OP_addr:
hash_addr:
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
{
unsigned char dtprel = 0xd1;
hstate.add_object (dtprel);
@@ -31851,7 +31857,7 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
case DW_OP_GNU_const_index:
case DW_OP_constx:
{
- if (loc->dtprel)
+ if (loc->dw_loc_dtprel)
{
unsigned char dtprel = 0xd1;
hstate.add_object (dtprel);
@@ -31998,7 +32004,7 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
{
case DW_OP_const4u:
case DW_OP_const8u:
- if (x->dtprel)
+ if (x->dw_loc_dtprel)
goto hash_addr;
/* FALLTHRU */
case DW_OP_const1u:
@@ -32162,7 +32168,7 @@ compare_locs (dw_loc_descr_ref x, dw_loc_descr_ref y)
{
for (; x != NULL && y != NULL; x = x->dw_loc_next, y = y->dw_loc_next)
if (x->dw_loc_opc != y->dw_loc_opc
- || x->dtprel != y->dtprel
+ || x->dw_loc_dtprel != y->dw_loc_dtprel
|| !compare_loc_operands (x, y))
break;
return x == NULL && y == NULL;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index fe50956..a0b0fa4 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -276,6 +276,25 @@ typedef struct GTY(()) dw_loc_list_struct {
struct GTY(()) dw_val_node {
enum dw_val_class val_class;
+ /* On 64-bit host, there are 4 bytes of padding between val_class
+ and val_entry. Reuse the padding for other content of
+ dw_loc_descr_node and dw_attr_struct. */
+ union dw_val_node_parent
+ {
+ struct dw_val_loc_descr_node
+ {
+ ENUM_BITFIELD (dwarf_location_atom) dw_loc_opc_v : 8;
+ /* Used to distinguish DW_OP_addr with a direct symbol relocation
+ from DW_OP_addr with a dtp-relative symbol relocation. */
+ unsigned int dw_loc_dtprel_v : 1;
+ /* For DW_OP_pick, DW_OP_dup and DW_OP_over operations: true iff.
+ it targets a DWARF prodecure argument. In this case, it needs to be
+ relocated according to the current frame offset. */
+ unsigned int dw_loc_frame_offset_rel_v : 1;
+ } u1;
+ int u2;
+ enum dwarf_attribute u3;
+ } GTY((skip)) u;
struct addr_table_entry * GTY(()) val_entry;
union dw_val_struct_union
{
@@ -321,15 +340,15 @@ struct GTY(()) dw_val_node {
struct GTY((chain_next ("%h.dw_loc_next"))) dw_loc_descr_node {
dw_loc_descr_ref dw_loc_next;
- ENUM_BITFIELD (dwarf_location_atom) dw_loc_opc : 8;
+#define dw_loc_opc dw_loc_oprnd1.u.u1.dw_loc_opc_v
/* Used to distinguish DW_OP_addr with a direct symbol relocation
from DW_OP_addr with a dtp-relative symbol relocation. */
- unsigned int dtprel : 1;
+#define dw_loc_dtprel dw_loc_oprnd1.u.u1.dw_loc_dtprel_v
/* For DW_OP_pick, DW_OP_dup and DW_OP_over operations: true iff.
it targets a DWARF prodecure argument. In this case, it needs to be
relocated according to the current frame offset. */
- unsigned int frame_offset_rel : 1;
- int dw_loc_addr;
+#define dw_loc_frame_offset_rel dw_loc_oprnd1.u.u1.dw_loc_frame_offset_rel_v
+#define dw_loc_addr dw_loc_oprnd2.u.u2
dw_val_node dw_loc_oprnd1;
dw_val_node dw_loc_oprnd2;
};
@@ -493,7 +512,7 @@ void dwarf2out_cc_finalize (void);
Attributes are typically linked below the DIE they modify. */
typedef struct GTY(()) dw_attr_struct {
- enum dwarf_attribute dw_attr;
+#define dw_attr dw_attr_val.u.u3
dw_val_node dw_attr_val;
}
dw_attr_node;
diff --git a/gcc/flag-types.h b/gcc/flag-types.h
index db57376..9a3cc4a 100644
--- a/gcc/flag-types.h
+++ b/gcc/flag-types.h
@@ -404,8 +404,7 @@ enum lto_partition_model {
LTO_PARTITION_BALANCED = 2,
LTO_PARTITION_1TO1 = 3,
LTO_PARTITION_MAX = 4,
- LTO_PARTITION_CACHE = 5,
- LTO_PARTITION_DEFAULT= 6
+ LTO_PARTITION_CACHE = 5
};
/* flag_lto_locality_cloning initialization values. */
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index bda22d1..7c6a415 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2025-04-23 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ PR fortran/119200
+ * check.cc (gfc_check_lcobound): Use locus from intrinsic_where.
+ (gfc_check_image_index): Same.
+ (gfc_check_num_images): Same.
+ (gfc_check_team_number): Same.
+ (gfc_check_this_image): Same.
+ (gfc_check_ucobound): Same.
+
2025-04-22 Andre Vehreschild <vehre@gcc.gnu.org>
* match.cc (match_exit_cycle): Allow to exit team block.
diff --git a/gcc/ipa-cp.cc b/gcc/ipa-cp.cc
index abde64b..b4b9699 100644
--- a/gcc/ipa-cp.cc
+++ b/gcc/ipa-cp.cc
@@ -4639,7 +4639,7 @@ update_counts_for_self_gen_clones (cgraph_node *orig_node,
const vec<cgraph_node *> &self_gen_clones)
{
profile_count redist_sum = orig_node->count.ipa ();
- if (!(redist_sum > profile_count::zero ()))
+ if (!redist_sum.nonzero_p ())
return;
if (dump_file)
@@ -4710,7 +4710,7 @@ update_counts_for_self_gen_clones (cgraph_node *orig_node,
it. */
for (cgraph_node *n : self_gen_clones)
{
- if (!(n->count.ipa () > profile_count::zero ()))
+ if (!n->count.ipa ().nonzero_p ())
continue;
desc_incoming_count_struct desc;
@@ -4756,7 +4756,7 @@ update_profiling_info (struct cgraph_node *orig_node,
profile_count new_sum;
profile_count remainder, orig_node_count = orig_node->count.ipa ();
- if (!(orig_node_count > profile_count::zero ()))
+ if (!orig_node_count.nonzero_p ())
return;
if (dump_file)
@@ -4920,7 +4920,7 @@ update_specialized_profile (struct cgraph_node *new_node,
orig_node_count.dump (dump_file);
fprintf (dump_file, "\n");
}
- if (!(orig_node_count > profile_count::zero ()))
+ if (!orig_node_count.nonzero_p ())
return;
new_node_count = new_node->count;
diff --git a/gcc/m2/ChangeLog b/gcc/m2/ChangeLog
index eeb5f66..5290f7c 100644
--- a/gcc/m2/ChangeLog
+++ b/gcc/m2/ChangeLog
@@ -1,3 +1,39 @@
+2025-04-24 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/119915
+ * gm2-libs/FormatStrings.mod (PerformFormatString): Handle
+ the %u and %x format specifiers in a similar way to the %d
+ specifier. Avoid using Slice and use Copy instead.
+
+2025-04-24 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/119914
+ * gm2-compiler/M2Check.mod (checkConstMeta): Add check for
+ Ztype, Rtype and Ctype and unbounded arrays.
+ (IsZRCType): New procedure function.
+ (isZRC): Add comment.
+ * gm2-compiler/M2Quads.mod:
+ * gm2-compiler/M2Range.mod (gdbinit): New procedure.
+ (BreakWhenRangeCreated): Ditto.
+ (CheckBreak): Ditto.
+ (InitRange): Call CheckBreak.
+ (Init): Add gdbhook and initialize interactive watch point.
+ * gm2-compiler/SymbolTable.def (GetNthParamAnyClosest): New
+ procedure function.
+ * gm2-compiler/SymbolTable.mod (BreakSym): Remove constant.
+ (BreakSym): Add Variable.
+ (stop): Remove.
+ (gdbhook): New procedure.
+ (BreakWhenSymCreated): Ditto.
+ (CheckBreak): Ditto.
+ (NewSym): Call CheckBreak.
+ (Init): Add gdbhook and initialize interactive watch point.
+ (MakeProcedure): Replace guarded call to stop with CheckBreak.
+ (GetNthParamChoice): New procedure function.
+ (GetNthParamOrdered): Ditto.
+ (GetNthParamAnyClosest): Ditto.
+ (GetOuterModuleScope): Ditto.
+
2025-04-11 Gaius Mulley <gaiusmod2@gmail.com>
PR modula2/119735
diff --git a/gcc/m2/gm2-libs/FormatStrings.mod b/gcc/m2/gm2-libs/FormatStrings.mod
index ec2985b..aea8da9 100644
--- a/gcc/m2/gm2-libs/FormatStrings.mod
+++ b/gcc/m2/gm2-libs/FormatStrings.mod
@@ -378,7 +378,7 @@ BEGIN
THEN
INC (afterperc) ;
Cast (u, w) ;
- in := ConCat (in, Slice (fmt, startpos, nextperc)) ;
+ in := Copy (fmt, in, startpos, nextperc) ;
in := ConCat (in, CardinalToString (u, width, leader, 16, TRUE)) ;
startpos := afterperc ;
DSdbExit (NIL) ;
@@ -387,7 +387,7 @@ BEGIN
THEN
INC (afterperc) ;
Cast (u, w) ;
- in := ConCat (in, Slice (fmt, startpos, nextperc)) ;
+ in := Copy (fmt, in, startpos, nextperc) ;
in := ConCat (in, CardinalToString (u, width, leader, 10, FALSE)) ;
startpos := afterperc ;
DSdbExit (NIL) ;
diff --git a/gcc/opts.cc b/gcc/opts.cc
index 5e7b77d..ffcbdfe 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -1047,9 +1047,9 @@ validate_ipa_reorder_locality_lto_partition (struct gcc_options *opts,
{
static bool validated_p = false;
- if (opts->x_flag_lto_partition != LTO_PARTITION_DEFAULT)
+ if (opts_set->x_flag_lto_partition)
{
- if (opts_set->x_flag_ipa_reorder_for_locality && !validated_p)
+ if (opts->x_flag_ipa_reorder_for_locality && !validated_p)
error ("%<-fipa-reorder-for-locality%> is incompatible with"
" an explicit %qs option", "-flto-partition");
}
@@ -1269,8 +1269,6 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
SET_OPTION_IF_UNSET (opts, opts_set, flag_reorder_functions, 1);
validate_ipa_reorder_locality_lto_partition (opts, opts_set);
- if (opts_set->x_flag_lto_partition != LTO_PARTITION_DEFAULT)
- opts_set->x_flag_lto_partition = opts->x_flag_lto_partition = LTO_PARTITION_BALANCED;
/* The -gsplit-dwarf option requires -ggnu-pubnames. */
if (opts->x_dwarf_split_debug_info)
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index b1537f7..96da438 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,11 @@
+2025-04-23 Joseph Myers <josmyers@redhat.com>
+
+ * gcc.pot: Regenerate.
+
+2025-04-23 Joseph Myers <josmyers@redhat.com>
+
+ * sv.po: Update.
+
2025-04-09 Joseph Myers <josmyers@redhat.com>
* de.po: Update.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index af49263..47666a9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,97 @@
+2025-04-24 Jakub Jelinek <jakub@redhat.com>
+ Stefan Schulze Frielinghaus <stefansf@gcc.gnu.org>
+
+ PR target/119873
+ * gcc.target/s390/pr119873-1.c: New test.
+ * gcc.target/s390/pr119873-2.c: New test.
+ * gcc.target/s390/pr119873-3.c: New test.
+ * gcc.target/s390/pr119873-4.c: New test.
+
+2025-04-24 Robert Dubner <rdubner@symas.com>
+
+ * cobol.dg/group1/declarative_1.cob: Adjust for repaired exception logic.
+
+2025-04-24 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.target/i386/pr119919.c: New test.
+
+2025-04-24 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR target/119610
+ * g++.dg/torture/pr119610.C: New test.
+ * g++.target/aarch64/sve/pr119610-sve.C: Likewise.
+
+2025-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/110343
+ * gcc.dg/raw-string-1.c: New test.
+
+2025-04-24 Kyrylo Tkachov <ktkachov@nvidia.com>
+
+ * gcc.dg/completion-2.c: Remove check for default.
+
+2025-04-24 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/119915
+ * gm2/pimlib/run/pass/format2.mod: New test.
+
+2025-04-24 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/avx512vl-pr103750-1.c: New test.
+ * gcc.target/i386/avx512f-pr96891-3.c: Adjust testcase.
+ * gcc.target/i386/avx512f-vpcmpgtuq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpeqq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpequq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgeq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgeuq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgtq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpgtuq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpleq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpleuq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpltq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpltuq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpneqq-1.c: Ditto.
+ * gcc.target/i386/avx512vl-vpcmpnequq-1.c: Ditto.
+
+2025-04-24 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/119914
+ * gm2/pim/fail/constintarraybyte.mod: New test.
+
+2025-04-23 Dimitar Dimitrov <dimitar@dinux.eu>
+
+ * g++.dg/no-stack-protector-attr-3.C: Require effective target
+ fstack_protector.
+
+2025-04-23 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/ipa/ipa-clone-4.c: New file.
+ * gcc.dg/tree-prof/ipa-cp-1.c: New file.
+
+2025-04-23 Christophe Lyon <christophe.lyon@linaro.org>
+
+ PR target/71233
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x2.c: Enable on arm.
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x3.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vld1x4.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x2.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x3.c: Likewise.
+ * gcc.target/aarch64/advsimd-intrinsics/vst1x4.c: Likewise.
+
+2025-04-23 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * g++.dg/eh/pr119507.C: Skip on sparc*-*-solaris2* && !gas.
+
+2025-04-23 Tamar Christina <tamar.christina@arm.com>
+
+ PR target/119286
+ * gcc.dg/vect/vect-early-break_38.c: Force -march=gfx908 for amdgcn.
+
+2025-04-23 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/blendv-to-maxmin.c: New test.
+ * gcc.target/i386/blendv-to-pand.c: New test.
+
2025-04-22 Jan Hubicka <hubicka@ucw.cz>
* gcc.target/i386/pr89618-2.c: XFAIL.
diff --git a/gcc/testsuite/cobol.dg/group1/declarative_1.cob b/gcc/testsuite/cobol.dg/group1/declarative_1.cob
index 744495a..ec68e9c 100644
--- a/gcc/testsuite/cobol.dg/group1/declarative_1.cob
+++ b/gcc/testsuite/cobol.dg/group1/declarative_1.cob
@@ -1,14 +1,14 @@
*> { dg-do run }
*> { dg-output {Turning EC\-ALL CHECKING OFF \-\- Expecting \+00\.00 from ACOS\(\-3\)(\n|\r\n|\r)} }
-*> { dg-output { \+00\.00 TABL\(VSIX\) is 6(\n|\r\n|\r)} }
+*> { dg-output { \+00\.00 TABL\(VSIX\) is 1(\n|\r\n|\r)} }
*> { dg-output {Turning EC\-ARGUMENT\-FUNCTION CHECKING ON(\n|\r\n|\r)} }
*> { dg-output { Expecting \+0\.00 and DECLARATIVE FOR EC\-ARGUMENT\-FUNCTION(\n|\r\n|\r)} }
*> { dg-output { DECLARATIVE FOR EC\-ARGUMENT\-FUNCTION(\n|\r\n|\r)} }
-*> { dg-output { \+00\.00 TABL\(VSIX\) is 6(\n|\r\n|\r)} }
+*> { dg-output { \+00\.00 TABL\(VSIX\) is 1(\n|\r\n|\r)} }
*> { dg-output {Turning EC\-ARGUMENT CHECKING ON(\n|\r\n|\r)} }
*> { dg-output { Expecting \+0\.00 and DECLARATIVE FOR EC\-ARGUMENT\-FUNCTION(\n|\r\n|\r)} }
*> { dg-output { DECLARATIVE FOR EC\-ARGUMENT\-FUNCTION(\n|\r\n|\r)} }
-*> { dg-output { \+00\.00 TABL\(VSIX\) is 6(\n|\r\n|\r)} }
+*> { dg-output { \+00\.00 TABL\(VSIX\) is 1(\n|\r\n|\r)} }
*> { dg-output {Turning EC\-ALL CHECKING ON(\n|\r\n|\r)} }
*> { dg-output { Expecting \+0\.00 and DECLARATIVE EC\-ARGUMENT\-FUNCTION(\n|\r\n|\r)} }
*> { dg-output { Followed by DECLARATIVE EC\-ALL for TABL\(6\) access(\n|\r\n|\r)} }
diff --git a/gcc/testsuite/g++.dg/torture/pr119610.C b/gcc/testsuite/g++.dg/torture/pr119610.C
new file mode 100644
index 0000000..9998026
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr119610.C
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-additional-options "-fstack-protector-strong" { target fstack_protector } }
+// { dg-additional-options "-fstack-clash-protection" { target supports_stack_clash_protection } }
+
+int *ptr;
+void foo() {
+ int c[1024*128];
+ ptr = c;
+ throw 1;
+}
+int main()
+{
+ try {
+ foo();
+ } catch(int x) {
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/pr119610-sve.C b/gcc/testsuite/g++.target/aarch64/sve/pr119610-sve.C
new file mode 100644
index 0000000..0044e51
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/pr119610-sve.C
@@ -0,0 +1,20 @@
+// { dg-do run { target aarch64_sve_hw } }
+// { dg-additional-options "-fstack-protector-strong" { target fstack_protector } }
+// { dg-additional-options "-fstack-clash-protection" { target supports_stack_clash_protection } }
+
+void *a_ptr, *b_ptr;
+void foo() {
+ __SVInt32_t a;
+ int b[1024*128];
+ a_ptr = &a;
+ b_ptr = b;
+ throw 1;
+}
+int main()
+{
+ try {
+ foo();
+ } catch(int x) {
+ return 0;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/completion-2.c b/gcc/testsuite/gcc.dg/completion-2.c
index 46c511c..99e6531 100644
--- a/gcc/testsuite/gcc.dg/completion-2.c
+++ b/gcc/testsuite/gcc.dg/completion-2.c
@@ -5,7 +5,6 @@
-flto-partition=1to1
-flto-partition=balanced
-flto-partition=cache
--flto-partition=default
-flto-partition=max
-flto-partition=none
-flto-partition=one
diff --git a/gcc/testsuite/gcc.dg/raw-string-1.c b/gcc/testsuite/gcc.dg/raw-string-1.c
new file mode 100644
index 0000000..77d6145
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/raw-string-1.c
@@ -0,0 +1,25 @@
+/* PR c++/110343 */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu23" } */
+
+const void *s0 = R"0123456789abcdefg()0123456789abcdefg" 0;
+ /* { dg-error "raw string delimiter longer" "longer" { target *-*-* } .-1 } */
+ /* { dg-error "stray" "stray" { target *-*-* } .-2 } */
+const void *s1 = R" () " 0;
+ /* { dg-error "invalid character" "invalid" { target *-*-* } .-1 } */
+ /* { dg-error "stray" "stray" { target *-*-* } .-2 } */
+const void *s2 = R" () " 0;
+ /* { dg-error "invalid character" "invalid" { target *-*-* } .-1 } */
+ /* { dg-error "stray" "stray" { target *-*-* } .-2 } */
+const void *s3 = R")())" 0;
+ /* { dg-error "invalid character" "invalid" { target *-*-* } .-1 } */
+ /* { dg-error "stray" "stray" { target *-*-* } .-2 } */
+const char *s4 = R"@()@";
+const char *s5 = R"$()$";
+const char *s6 = R"`()`";
+const void *s7 = R"\u0040()\u0040" 0;
+ /* { dg-error "invalid character" "invalid" { target *-*-* } .-1 } */
+ /* { dg-error "stray" "stray" { target *-*-* } .-2 } */
+const char *s8 = R"`@$$@`@`$()`@$$@`@`$";
+
+int main () {}
diff --git a/gcc/testsuite/gcc.target/i386/pr119919.c b/gcc/testsuite/gcc.target/i386/pr119919.c
new file mode 100644
index 0000000..ed64656
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr119919.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -fdump-tree-vect-details" } */
+int a[9*9];
+bool b[9];
+void test()
+{
+ for (int i = 0; i < 9; i++)
+ {
+ b[i] = a[i*9] != 0;
+ }
+}
+
+/* { dg-final { scan-tree-dump "loop vectorized using 8 byte vectors" "vect" } } */
diff --git a/gcc/testsuite/gcc.target/s390/pr119873-1.c b/gcc/testsuite/gcc.target/s390/pr119873-1.c
new file mode 100644
index 0000000..7a9a988
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr119873-1.c
@@ -0,0 +1,11 @@
+/* PR target/119873 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+const char *foo (void *, void *, void *, void *, unsigned long, unsigned long);
+
+const char *
+bar (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f)
+{
+ [[gnu::musttail]] return foo (a, b, c, d, e, f);
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr119873-2.c b/gcc/testsuite/gcc.target/s390/pr119873-2.c
new file mode 100644
index 0000000..f275253
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr119873-2.c
@@ -0,0 +1,17 @@
+/* PR target/119873 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+const char *foo (void *, void *, void *, void *, unsigned long, unsigned long);
+
+const char *
+bar (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f)
+{
+ [[gnu::musttail]] return foo (a, b, c, d, e + 1, f); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */
+}
+
+const char *
+baz (void *a, void *b, void *c, void *d, unsigned long e, unsigned long f)
+{
+ [[gnu::musttail]] return foo (a, b, c, d, f, e); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr119873-3.c b/gcc/testsuite/gcc.target/s390/pr119873-3.c
new file mode 100644
index 0000000..048fcaa
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr119873-3.c
@@ -0,0 +1,27 @@
+/* PR target/119873 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern int foo (int, int, int, long long, int);
+
+int
+bar (int u, int v, int w, long long x, int y)
+{
+ [[gnu::musttail]] return foo (u, v, w, x, y);
+}
+
+extern int baz (int, int, int, int, int);
+
+int
+qux (int u, int v, int w, int x, int y)
+{
+ [[gnu::musttail]] return baz (u, v, w, x, y);
+}
+
+extern int corge (int, int, int, int, unsigned short);
+
+int
+garply (int u, int v, int w, int x, unsigned short y)
+{
+ [[gnu::musttail]] return corge (u, v, w, x, y);
+}
diff --git a/gcc/testsuite/gcc.target/s390/pr119873-4.c b/gcc/testsuite/gcc.target/s390/pr119873-4.c
new file mode 100644
index 0000000..384170c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/pr119873-4.c
@@ -0,0 +1,27 @@
+/* PR target/119873 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern int foo (int, int, int, long long, int);
+
+int
+bar (int u, int v, int w, long long x, int y)
+{
+ [[gnu::musttail]] return foo (u, v, w, x + 1, y - 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */
+}
+
+extern int baz (int, int, int, int, int);
+
+int
+qux (int u, int v, int w, int x, int y)
+{
+ [[gnu::musttail]] return baz (u, v, w, x, y + 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */
+}
+
+extern int corge (int, int, int, int, unsigned short);
+
+int
+garply (int u, int v, int w, int x, unsigned short y)
+{
+ [[gnu::musttail]] return corge (u, v, w, x, y + 1); /* { dg-error "cannot tail-call: target is not able to optimize the call into a sibling call" } */
+}
diff --git a/gcc/testsuite/gm2/pimlib/run/pass/format2.mod b/gcc/testsuite/gm2/pimlib/run/pass/format2.mod
new file mode 100644
index 0000000..2ad6a8c
--- /dev/null
+++ b/gcc/testsuite/gm2/pimlib/run/pass/format2.mod
@@ -0,0 +1,63 @@
+MODULE format2;
+
+FROM libc IMPORT exit, printf ;
+FROM Terminal IMPORT Write, WriteLn;
+FROM NumberIO IMPORT WriteCard;
+FROM DynamicStrings IMPORT String, Length, char, InitString;
+FROM FormatStrings IMPORT Sprintf1;
+
+PROCEDURE WriteString (s: String);
+VAR
+ l, i: CARDINAL;
+BEGIN
+ l := Length (s) ;
+ i := 0 ;
+ WHILE i < l DO
+ Write (char (s, i)) ;
+ INC (i)
+ END
+END WriteString;
+
+
+(*
+ assert -
+*)
+
+PROCEDURE assert (cond: BOOLEAN; line: CARDINAL; file: ARRAY OF CHAR) ;
+BEGIN
+ IF NOT cond
+ THEN
+ printf ("%s:%d assertion failed\n", file, line);
+ exit (1)
+ END
+END assert ;
+
+
+VAR
+ n: CARDINAL;
+ r, s: String;
+BEGIN
+ n := 2;
+ r := InitString("%u pieces of cake") ;
+ WriteString (r) ; WriteLn ;
+ assert (Length (r) = 17, __LINE__, __FILE__) ;
+ s := Sprintf1 (r, n) ;
+ WriteCard (Length (s), 4) ; WriteLn ;
+ assert (Length (s) = 16, __LINE__, __FILE__) ;
+
+ r := InitString("%d pieces of cake") ;
+ WriteString (r) ; WriteLn ;
+ assert (Length (r) = 17, __LINE__, __FILE__) ;
+ s := Sprintf1 (r, n) ;
+ WriteCard (Length (s), 4) ; WriteLn ;
+ assert (Length (s) = 16, __LINE__, __FILE__) ;
+
+ r := InitString("%x pieces of cake") ;
+ WriteString (r) ; WriteLn ;
+ assert (Length (r) = 17, __LINE__, __FILE__) ;
+ s := Sprintf1 (r, n) ;
+ WriteCard (Length (s), 4) ; WriteLn ;
+ assert (Length (s) = 16, __LINE__, __FILE__) ;
+
+ WriteString (InitString ('all tests pass')) ; WriteLn ;
+END format2.
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 353227a..775b000 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,9 @@
+2025-04-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/110343
+ * lex.cc (lex_raw_string): For C allow $@` in raw string delimiters
+ if CPP_OPTION (pfile, low_ucns) i.e. for C23 and later.
+
2025-04-09 Jakub Jelinek <jakub@redhat.com>
PR preprocessor/118674
diff --git a/libcpp/lex.cc b/libcpp/lex.cc
index 2d02ce6..e7705a6 100644
--- a/libcpp/lex.cc
+++ b/libcpp/lex.cc
@@ -2711,8 +2711,9 @@ lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base)
|| c == '!' || c == '=' || c == ','
|| c == '"' || c == '\''
|| ((c == '$' || c == '@' || c == '`')
- && CPP_OPTION (pfile, cplusplus)
- && CPP_OPTION (pfile, lang) > CLK_CXX23)))
+ && (CPP_OPTION (pfile, cplusplus)
+ ? CPP_OPTION (pfile, lang) > CLK_CXX23
+ : CPP_OPTION (pfile, low_ucns)))))
prefix[prefix_len++] = c;
else
{
diff --git a/libgm2/ChangeLog b/libgm2/ChangeLog
index fb9920e..51a8e38 100644
--- a/libgm2/ChangeLog
+++ b/libgm2/ChangeLog
@@ -1,3 +1,44 @@
+2025-04-24 Gaius Mulley <gaiusmod2@gmail.com>
+
+ PR modula2/115276
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+ * configure.ac (AC_STRUCT_TIMEZONE): Add.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_year.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_mon.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_mday.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_hour.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_min.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_sec.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_year.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_yday.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_wday.
+ (AC_CHECK_MEMBER): Test for struct tm.tm_isdst.
+ (AC_CHECK_MEMBER): Test for struct timeval.tv_sec.
+ (AC_CHECK_MEMBER): Test for struct timeval.tv_sec.
+ (AC_CHECK_MEMBER): Test for struct timeval.tv_usec.
+ * libm2iso/wraptime.cc (InitTimeval): Guard against lack
+ struct timeval and malloc.
+ (InitTimezone): Guard against lack of struct tm.tm_zone
+ and malloc.
+ (KillTimezone): Ditto.
+ (InitTimeval): Guard against lack of struct timeval
+ and malloc.
+ (KillTimeval): Guard against lack of malloc.
+ (settimeofday): Guard against lack of struct tm.tm_zone.
+ (GetFractions): Guard against lack of struct timeval.
+ (localtime_r): Ditto.
+ (GetYear): Guard against lack of struct tm.
+ (GetMonth): Ditto.
+ (GetDay): Ditto.
+ (GetHour): Ditto.
+ (GetMinute): Ditto.
+ (GetSecond): Ditto.
+ (GetSummerTime): Ditto.
+ (GetDST): Guards against lack of struct timezone.
+ (SetTimezone): Ditto.
+ (SetTimeval): Guard against lack of struct tm.
+
2025-03-28 Gaius Mulley <gaiusmod2@gmail.com>
PR modula2/118045
diff --git a/libgm2/config.h.in b/libgm2/config.h.in
index 321ef3b..f9710ff 100644
--- a/libgm2/config.h.in
+++ b/libgm2/config.h.in
@@ -34,6 +34,10 @@
*/
#undef HAVE_DECL_GETENV
+/* Define to 1 if you have the declaration of `tzname', and to 0 if you don't.
+ */
+#undef HAVE_DECL_TZNAME
+
/* Define to 1 if you have the <direct.h> header file. */
#undef HAVE_DIRECT_H
@@ -232,6 +236,9 @@
/* Define to 1 if the system has the type `struct tm'. */
#undef HAVE_STRUCT_TM
+/* Define to 1 if `tm_zone' is a member of `struct tm'. */
+#undef HAVE_STRUCT_TM_TM_ZONE
+
/* Define to 1 if you have the <sys/errno.h> header file. */
#undef HAVE_SYS_ERRNO_H
@@ -286,6 +293,10 @@
/* Define if struct tm has a tm_gmtoff field. */
#undef HAVE_TM_TM_GMTOFF
+/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use
+ `HAVE_STRUCT_TM_TM_ZONE' instead. */
+#undef HAVE_TM_ZONE
+
/* function tzname exists */
#undef HAVE_TZNAME
@@ -338,6 +349,9 @@
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#undef TIME_WITH_SYS_TIME
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+#undef TM_IN_SYS_TIME
+
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
@@ -363,6 +377,45 @@
/* Version number of package */
#undef VERSION
+/* struct timeval was found */
+#undef WE_HAVE_STRUCT_TIMEVAL
+
+/* struct timeval.tv_sec was found */
+#undef WE_HAVE_STRUCT_TIMEVAL_TV_SEC
+
+/* struct timeval.tv_usec was found */
+#undef WE_HAVE_STRUCT_TIMEVAL_TV_USEC
+
+/* struct tm was found */
+#undef WE_HAVE_STRUCT_TM
+
+/* struct tm.tm_hour was found */
+#undef WE_HAVE_STRUCT_TM_HOUR
+
+/* struct tm.tm_isdst was found */
+#undef WE_HAVE_STRUCT_TM_ISDST
+
+/* struct tm.tm_mday was found */
+#undef WE_HAVE_STRUCT_TM_MDAY
+
+/* struct tm.tm_min was found */
+#undef WE_HAVE_STRUCT_TM_MIN
+
+/* struct tm.tm_mon was found */
+#undef WE_HAVE_STRUCT_TM_MON
+
+/* struct tm.tm_sec was found */
+#undef WE_HAVE_STRUCT_TM_SEC
+
+/* struct tm.tm_wday was found */
+#undef WE_HAVE_STRUCT_TM_WDAY
+
+/* struct tm.tm_yday was found */
+#undef WE_HAVE_STRUCT_TM_YDAY
+
+/* struct tm.tm_year was found */
+#undef WE_HAVE_STRUCT_TM_YEAR
+
/* Defined if no way to sleep is available. */
#undef _GLIBCXX_NO_SLEEP
diff --git a/libgm2/configure b/libgm2/configure
index efe3b66..8ffdb31 100755
--- a/libgm2/configure
+++ b/libgm2/configure
@@ -2100,6 +2100,109 @@ $as_echo "$ac_res" >&6; }
} # ac_fn_cxx_check_func
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
# ac_fn_c_try_link LINENO
# -----------------------
# Try to link conftest.$ac_ext, and return whether this succeeded.
@@ -2269,52 +2372,6 @@ $as_echo "$ac_res" >&6; }
eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
} # ac_fn_c_check_type
-
-# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
-# ---------------------------------------------
-# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
-# accordingly.
-ac_fn_c_check_decl ()
-{
- as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
- as_decl_name=`echo $2|sed 's/ *(.*//'`
- as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
-$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
-if eval \${$3+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-$4
-int
-main ()
-{
-#ifndef $as_decl_name
-#ifdef __cplusplus
- (void) $as_decl_use;
-#else
- (void) $as_decl_name;
-#endif
-#endif
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- eval "$3=yes"
-else
- eval "$3=no"
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-eval ac_res=\$$3
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
-$as_echo "$ac_res" >&6; }
- eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
-
-} # ac_fn_c_check_decl
cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
@@ -6872,6 +6929,7 @@ $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h
fi
+
ac_fn_c_check_header_mongrel "$LINENO" "math.h" "ac_cv_header_math_h" "$ac_includes_default"
if test "x$ac_cv_header_math_h" = xyes; then :
@@ -6903,6 +6961,223 @@ fi
done
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5
+$as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; }
+if ${ac_cv_struct_tm+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+#include <time.h>
+
+int
+main ()
+{
+struct tm tm;
+ int *p = &tm.tm_sec;
+ return !p;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_struct_tm=time.h
+else
+ ac_cv_struct_tm=sys/time.h
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_tm" >&5
+$as_echo "$ac_cv_struct_tm" >&6; }
+if test $ac_cv_struct_tm = sys/time.h; then
+
+$as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_zone" "ac_cv_member_struct_tm_tm_zone" "#include <sys/types.h>
+#include <$ac_cv_struct_tm>
+
+"
+if test "x$ac_cv_member_struct_tm_tm_zone" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TM_TM_ZONE 1
+_ACEOF
+
+
+fi
+
+if test "$ac_cv_member_struct_tm_tm_zone" = yes; then
+
+$as_echo "#define HAVE_TM_ZONE 1" >>confdefs.h
+
+else
+ ac_fn_c_check_decl "$LINENO" "tzname" "ac_cv_have_decl_tzname" "#include <time.h>
+"
+if test "x$ac_cv_have_decl_tzname" = xyes; then :
+ ac_have_decl=1
+else
+ ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_TZNAME $ac_have_decl
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tzname" >&5
+$as_echo_n "checking for tzname... " >&6; }
+if ${ac_cv_var_tzname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test x$gcc_no_link = xyes; then
+ as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5
+fi
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <time.h>
+#if !HAVE_DECL_TZNAME
+extern char *tzname[];
+#endif
+
+int
+main ()
+{
+return tzname[0][0];
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_var_tzname=yes
+else
+ ac_cv_var_tzname=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_var_tzname" >&5
+$as_echo "$ac_cv_var_tzname" >&6; }
+ if test $ac_cv_var_tzname = yes; then
+
+$as_echo "#define HAVE_TZNAME 1" >>confdefs.h
+
+ fi
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_year" "ac_cv_member_struct_tm_tm_year" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_year" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_year" "ac_cv_member_struct_tm_tm_year" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_year" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_YEAR 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_mon" "ac_cv_member_struct_tm_tm_mon" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_mon" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_MON 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_mday" "ac_cv_member_struct_tm_tm_mday" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_mday" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_MDAY 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_hour" "ac_cv_member_struct_tm_tm_hour" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_hour" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_HOUR 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_min" "ac_cv_member_struct_tm_tm_min" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_min" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_MIN 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_sec" "ac_cv_member_struct_tm_tm_sec" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_sec" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_SEC 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_year" "ac_cv_member_struct_tm_tm_year" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_year" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_YEAR 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_yday" "ac_cv_member_struct_tm_tm_yday" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_yday" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_YDAY 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_wday" "ac_cv_member_struct_tm_tm_wday" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_wday" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_WDAY 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct tm" "tm_isdst" "ac_cv_member_struct_tm_tm_isdst" "#include <time.h>
+"
+if test "x$ac_cv_member_struct_tm_tm_isdst" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TM_ISDST 1" >>confdefs.h
+
+fi
+
+
+ac_fn_c_check_member "$LINENO" "struct timeval" "tv_sec" "ac_cv_member_struct_timeval_tv_sec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_timeval_tv_sec" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TIMEVAL 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct timeval" "tv_sec" "ac_cv_member_struct_timeval_tv_sec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_timeval_tv_sec" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TIMEVAL_TV_SEC 1" >>confdefs.h
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct timeval" "tv_usec" "ac_cv_member_struct_timeval_tv_usec" "$ac_includes_default"
+if test "x$ac_cv_member_struct_timeval_tv_usec" = xyes; then :
+
+$as_echo "#define WE_HAVE_STRUCT_TIMEVAL_TV_USEC 1" >>confdefs.h
+
+fi
+
+
case ${build_alias} in
"") build_noncanonical=${build} ;;
@@ -14579,7 +14854,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 14582 "configure"
+#line 14857 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -14685,7 +14960,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 14688 "configure"
+#line 14963 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
diff --git a/libgm2/configure.ac b/libgm2/configure.ac
index c070491..437485f 100644
--- a/libgm2/configure.ac
+++ b/libgm2/configure.ac
@@ -89,6 +89,7 @@ AC_ARG_WITH(cross-host,
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
AC_HEADER_TIME
+
AC_CHECK_HEADER([math.h],
[AC_DEFINE([HAVE_MATH_H], [1], [have math.h])])
@@ -102,6 +103,49 @@ AC_CHECK_HEADERS(getopt.h limits.h stddef.h string.h strings.h \
pthread.h stdarg.h stdio.h sys/types.h termios.h \
netinet/in.h netdb.h sys/uio.h sys/stat.h wchar.h)
+AC_STRUCT_TIMEZONE
+
+AC_CHECK_MEMBER([struct tm.tm_year],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM, [1], [struct tm was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_year],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_YEAR, [1], [struct tm.tm_year was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_mon],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_MON, [1], [struct tm.tm_mon was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_mday],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_MDAY, [1], [struct tm.tm_mday was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_hour],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_HOUR, [1], [struct tm.tm_hour was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_min],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_MIN, [1], [struct tm.tm_min was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_sec],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_SEC, [1], [struct tm.tm_sec was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_year],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_YEAR, [1], [struct tm.tm_year was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_yday],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_YDAY, [1], [struct tm.tm_yday was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_wday],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_WDAY, [1], [struct tm.tm_wday was found])],
+ [], [[#include <time.h>]])
+AC_CHECK_MEMBER([struct tm.tm_isdst],
+ [AC_DEFINE(WE_HAVE_STRUCT_TM_ISDST, [1], [struct tm.tm_isdst was found])],
+ [], [[#include <time.h>]])
+
+AC_CHECK_MEMBER([struct timeval.tv_sec],
+ [AC_DEFINE(WE_HAVE_STRUCT_TIMEVAL, [1], [struct timeval was found])])
+AC_CHECK_MEMBER([struct timeval.tv_sec],
+ [AC_DEFINE(WE_HAVE_STRUCT_TIMEVAL_TV_SEC, [1], [struct timeval.tv_sec was found])])
+AC_CHECK_MEMBER([struct timeval.tv_usec],
+ [AC_DEFINE(WE_HAVE_STRUCT_TIMEVAL_TV_USEC, [1], [struct timeval.tv_usec was found])])
+
AC_CANONICAL_HOST
ACX_NONCANONICAL_HOST
ACX_NONCANONICAL_TARGET
diff --git a/libgm2/libm2iso/wraptime.cc b/libgm2/libm2iso/wraptime.cc
index 4bbd5f9..ed5f05e 100644
--- a/libgm2/libm2iso/wraptime.cc
+++ b/libgm2/libm2iso/wraptime.cc
@@ -58,7 +58,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
/* InitTimeval returns a newly created opaque type. */
-#if defined(HAVE_STRUCT_TIMEVAL) && defined(HAVE_MALLOC_H)
+#if defined(WE_HAVE_STRUCT_TIMEVAL) && defined(HAVE_MALLOC_H)
extern "C" struct timeval *
EXPORT(InitTimeval) (void)
{
@@ -85,7 +85,7 @@ EXPORT(KillTimeval) (void *tv)
/* InitTimezone returns a newly created opaque type. */
-#if defined(HAVE_STRUCT_TIMEZONE) && defined(HAVE_MALLOC_H)
+#if defined(HAVE_STRUCT_TM_TM_ZONE) && defined(HAVE_MALLOC_H)
extern "C" struct timezone *
EXPORT(InitTimezone) (void)
{
@@ -102,14 +102,20 @@ EXPORT(InitTimezone) (void)
/* KillTimezone - deallocates the memory associated with an opaque
type. */
+#if defined(HAVE_STRUCT_TM_TM_ZONE) && defined(HAVE_MALLOC_H)
extern "C" struct timezone *
EXPORT(KillTimezone) (struct timezone *tv)
{
-#if defined(HAVE_MALLOC_H)
free (tv);
-#endif
return NULL;
}
+#else
+extern "C" void *
+EXPORT(KillTimezone) (void *tv)
+{
+ return NULL;
+}
+#endif
/* InitTM - returns a newly created opaque type. */
@@ -141,7 +147,7 @@ EXPORT(KillTM) (struct tm *tv)
/* gettimeofday - calls gettimeofday(2) with the same parameters, tv,
and, tz. It returns 0 on success. */
-#if defined(HAVE_STRUCT_TIMEZONE) && defined(HAVE_GETTIMEOFDAY)
+#if defined(HAVE_STRUCT_TM_TM_ZONE) && defined(HAVE_GETTIMEOFDAY)
extern "C" int
EXPORT(gettimeofday) (void *tv, struct timezone *tz)
{
@@ -158,7 +164,7 @@ EXPORT(gettimeofday) (void *tv, void *tz)
/* settimeofday - calls settimeofday(2) with the same parameters, tv,
and, tz. It returns 0 on success. */
-#if defined(HAVE_STRUCT_TIMEZONE) && defined(HAVE_SETTIMEOFDAY)
+#if defined(HAVE_STRUCT_TM_TM_ZONE) && defined(HAVE_SETTIMEOFDAY)
extern "C" int
EXPORT(settimeofday) (void *tv, struct timezone *tz)
{
@@ -175,7 +181,7 @@ EXPORT(settimeofday) (void *tv, void *tz)
/* wraptime_GetFractions - returns the tv_usec field inside the
timeval structure. */
-#if defined(HAVE_STRUCT_TIMEVAL)
+#if defined(WE_HAVE_STRUCT_TIMEVAL_TV_USEC)
extern "C" unsigned int
EXPORT(GetFractions) (struct timeval *tv)
{
@@ -194,7 +200,7 @@ EXPORT(GetFractions) (void *tv)
this procedure function expects, timeval, as its first parameter
and not a time_t (as expected by the posix equivalent). */
-#if defined(HAVE_STRUCT_TIMEVAL)
+#if defined(WE_HAVE_STRUCT_TIMEVAL_TV_SEC)
extern "C" struct tm *
EXPORT(localtime_r) (struct timeval *tv, struct tm *m)
{
@@ -210,7 +216,7 @@ EXPORT(localtime_r) (void *tv, struct tm *m)
/* wraptime_GetYear - returns the year from the structure, m. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_YEAR)
extern "C" unsigned int
EXPORT(GetYear) (struct tm *m)
{
@@ -226,7 +232,7 @@ EXPORT(GetYear) (void *m)
/* wraptime_GetMonth - returns the month from the structure, m. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_MON)
extern "C" unsigned int
EXPORT(GetMonth) (struct tm *m)
{
@@ -243,7 +249,7 @@ EXPORT(GetMonth) (void *m)
/* wraptime_GetDay - returns the day of the month from the structure,
m. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_MDAY)
extern "C" unsigned int
EXPORT(GetDay) (struct tm *m)
{
@@ -260,7 +266,7 @@ EXPORT(GetDay) (void *m)
/* wraptime_GetHour - returns the hour of the day from the structure,
m. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_HOUR)
extern "C" unsigned int
EXPORT(GetHour) (struct tm *m)
{
@@ -277,7 +283,7 @@ EXPORT(GetHour) (void *m)
/* wraptime_GetMinute - returns the minute within the hour from the
structure, m. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_MIN)
extern "C" unsigned int
EXPORT(GetMinute) (struct tm *m)
{
@@ -295,7 +301,7 @@ EXPORT(GetMinute) (void *m)
structure, m. The return value will always be in the range 0..59.
A leap minute of value 60 will be truncated to 59. */
-#if defined(HAVE_STRUCT_TM)
+#if defined(WE_HAVE_STRUCT_TM_SEC)
extern "C" unsigned int
EXPORT(GetSecond) (struct tm *m)
{
@@ -314,7 +320,7 @@ EXPORT(GetSecond) (void *m)
/* wraptime_GetSummerTime - returns true if summer time is in effect. */
-#if defined(HAVE_STRUCT_TIMEZONE)
+#if defined(HAVE_STRUCT_TM_TM_ZONE)
extern "C" bool
EXPORT(GetSummerTime) (struct timezone *tz)
{
@@ -330,7 +336,7 @@ EXPORT(GetSummerTime) (void *tz)
/* wraptime_GetDST - returns the number of minutes west of GMT. */
-#if defined(HAVE_STRUCT_TIMEZONE)
+#if defined(HAVE_STRUCT_TM_TM_ZONE)
extern "C" int
EXPORT(GetDST) (struct timezone *tz)
{
@@ -350,7 +356,7 @@ EXPORT(GetDST) (void *tz)
/* SetTimezone - set the timezone field inside timeval, tv. */
-#if defined(HAVE_STRUCT_TIMEZONE)
+#if defined(HAVE_STRUCT_TM_TM_ZONE)
extern "C" void
EXPORT(SetTimezone) (struct timezone *tz, int zone, int minuteswest)
{
@@ -367,22 +373,40 @@ EXPORT(SetTimezone) (void *tz, int zone, int minuteswest)
/* SetTimeval - sets the fields in tm, t, with: second, minute, hour,
day, month, year, fractions. */
-#if defined(HAVE_STRUCT_TIMEVAL)
+#if defined(WE_HAVE_STRUCT_TM)
extern "C" void
EXPORT(SetTimeval) (struct tm *t, unsigned int second, unsigned int minute,
unsigned int hour, unsigned int day, unsigned int month,
unsigned int year, unsigned int yday, unsigned int wday,
unsigned int isdst)
{
+#if defined(WE_HAVE_STRUCT_TM_SEC)
t->tm_sec = second;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_MIN)
t->tm_min = minute;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_HOUR)
t->tm_hour = hour;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_MDAY)
t->tm_mday = day;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_MON)
t->tm_mon = month;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_YEAR)
t->tm_year = year;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_YDAY)
t->tm_yday = yday;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_WDAY)
t->tm_wday = wday;
+#endif
+#if defined(WE_HAVE_STRUCT_TM_ISDST)
t->tm_isdst = isdst;
+#endif
}
#else
extern "C" void
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 096e17b..49a62d4 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,53 @@
+2025-04-24 Tobias Burnus <tburnus@baylibre.com>
+
+ * testsuite/lib/libgomp.exp
+ (check_effective_target_gomp_hip_header_nvidia): Compile with
+ "-Wno-deprecated-declarations".
+ * testsuite/libgomp.c/interop-hip-nvidia-full.c: Likewise.
+ * testsuite/libgomp.c/interop-hipblas-nvidia-full.c: Likewise.
+ * testsuite/libgomp.c/interop-hipblas.h: Add workarounds
+ when using the HIP headers with __HIP_PLATFORM_NVIDIA__.
+
+2025-04-24 Tobias Burnus <tburnus@baylibre.com>
+
+ * testsuite/lib/libgomp.exp (check_effective_target_openacc_cublas,
+ check_effective_target_openacc_cudart): Update description as
+ the check requires more.
+ (check_effective_target_openacc_libcuda,
+ check_effective_target_openacc_libcublas,
+ check_effective_target_openacc_libcudart,
+ check_effective_target_gomp_hip_header_amd,
+ check_effective_target_gomp_hip_header_nvidia,
+ check_effective_target_gomp_hipfort_module,
+ check_effective_target_gomp_libamdhip64,
+ check_effective_target_gomp_libhipblas): New.
+ * testsuite/libgomp.c-c++-common/interop-2.c: New test.
+ * testsuite/libgomp.c/interop-cublas-full.c: New test.
+ * testsuite/libgomp.c/interop-cublas-libonly.c: New test.
+ * testsuite/libgomp.c/interop-cuda-full.c: New test.
+ * testsuite/libgomp.c/interop-cuda-libonly.c: New test.
+ * testsuite/libgomp.c/interop-hip-amd-full.c: New test.
+ * testsuite/libgomp.c/interop-hip-amd-no-hip-header.c: New test.
+ * testsuite/libgomp.c/interop-hip-nvidia-full.c: New test.
+ * testsuite/libgomp.c/interop-hip-nvidia-no-headers.c: New test.
+ * testsuite/libgomp.c/interop-hip-nvidia-no-hip-header.c: New test.
+ * testsuite/libgomp.c/interop-hip.h: New test.
+ * testsuite/libgomp.c/interop-hipblas-amd-full.c: New test.
+ * testsuite/libgomp.c/interop-hipblas-amd-no-hip-header.c: New test.
+ * testsuite/libgomp.c/interop-hipblas-nvidia-full.c: New test.
+ * testsuite/libgomp.c/interop-hipblas-nvidia-no-headers.c: New test.
+ * testsuite/libgomp.c/interop-hipblas-nvidia-no-hip-header.c: New test.
+ * testsuite/libgomp.c/interop-hipblas.h: New test.
+ * testsuite/libgomp.fortran/interop-hip-amd-full.F90: New test.
+ * testsuite/libgomp.fortran/interop-hip-amd-no-module.F90: New test.
+ * testsuite/libgomp.fortran/interop-hip-nvidia-full.F90: New test.
+ * testsuite/libgomp.fortran/interop-hip-nvidia-no-module.F90: New test.
+ * testsuite/libgomp.fortran/interop-hip.h: New test.
+
+2025-04-23 Tobias Burnus <tburnus@baylibre.com>
+
+ * testsuite/libgomp.fortran/target-enter-data-8.f90: New test.
+
2025-04-17 Jakub Jelinek <jakub@redhat.com>
PR libgomp/119849
diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index bc38e3c..54f2f708 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -553,7 +553,23 @@ int main() {
} } "-lcuda" ]
}
-# Return 1 if cublas_v2.h and -lcublas are available.
+# Return 1 if -lcuda is available (header not required).
+
+proc check_effective_target_openacc_libcuda { } {
+ return [check_no_compiler_messages openacc_libcuda executable {
+typedef enum { CUDA_SUCCESS } CUresult;
+typedef int CUdevice;
+CUresult cuDeviceGet (CUdevice *, int);
+int main() {
+ CUdevice dev;
+ CUresult r = cuDeviceGet (&dev, 0);
+ if (r != CUDA_SUCCESS)
+ return 1;
+ return 0;
+} } "-lcuda" ]
+}
+
+# Return 1 if cublas_v2.h, cuda.h, -lcublas and -lcuda are available.
proc check_effective_target_openacc_cublas { } {
return [check_no_compiler_messages openacc_cublas executable {
@@ -573,7 +589,25 @@ int main() {
} } "-lcuda -lcublas" ]
}
-# Return 1 if cuda_runtime_api.h and -lcudart are available.
+# Return 1 if -lcublas is available header not required).
+
+proc check_effective_target_openacc_libcublas { } {
+ return [check_no_compiler_messages openacc_libcublas executable {
+typedef enum { CUBLAS_STATUS_SUCCESS } cublasStatus_t;
+typedef struct cublasContext* cublasHandle_t;
+#define cublasCreate cublasCreate_v2
+cublasStatus_t cublasCreate_v2 (cublasHandle_t *);
+int main() {
+ cublasStatus_t s;
+ cublasHandle_t h;
+ s = cublasCreate (&h);
+ if (s != CUBLAS_STATUS_SUCCESS)
+ return 1;
+ return 0;
+} } "-lcublas" ]
+}
+
+# Return 1 if cuda_runtime_api.h, cuda.h, -lcuda and -lcudart are available.
proc check_effective_target_openacc_cudart { } {
return [check_no_compiler_messages openacc_cudart executable {
@@ -592,3 +626,98 @@ int main() {
return 0;
} } "-lcuda -lcudart" ]
}
+
+# Return 1 if -lcudart is available (no header required).
+
+proc check_effective_target_openacc_libcudart { } {
+ return [check_no_compiler_messages openacc_libcudart executable {
+typedef int cudaError_t;
+cudaError_t cudaGetDevice(int *);
+enum { cudaSuccess };
+int main() {
+ cudaError_t e;
+ int devn;
+ e = cudaGetDevice (&devn);
+ if (e != cudaSuccess)
+ return 1;
+ return 0;
+} } "-lcudart" ]
+}
+
+# Return 1 if hip.h is available (no link check; AMD platform).
+
+proc check_effective_target_gomp_hip_header_amd { } {
+ return [check_no_compiler_messages gomp_hip_header_amd assembly {
+#define __HIP_PLATFORM_AMD__
+#include <hip/hip_runtime_api.h>
+int main() {
+ hipDevice_t dev;
+ hipError_t r = hipDeviceGet (&dev, 0);
+ if (r != hipSuccess)
+ return 1;
+ return 0;
+} }]
+}
+
+# Return 1 if hip.h is available (no link check; Nvidia/CUDA platform).
+
+proc check_effective_target_gomp_hip_header_nvidia { } {
+ return [check_no_compiler_messages gomp_hip_header_nvidia assembly {
+#define __HIP_PLATFORM_NVIDIA__
+#include <hip/hip_runtime_api.h>
+int main() {
+ hipDevice_t dev;
+ hipError_t r = hipDeviceGet (&dev, 0);
+ if (r != hipSuccess)
+ return 1;
+ return 0;
+} } "-Wno-deprecated-declarations"]
+}
+
+# Return 1 if the Fortran hipfort module is available (no link check)
+
+proc check_effective_target_gomp_hipfort_module { } {
+ return [check_no_compiler_messages gomp_hipfort_module assembly {
+! Fortran
+use hipfort
+implicit none
+integer(kind(hipSuccess)) :: r
+integer(c_int) :: dev
+r = hipDeviceGet (dev, 0)
+if (r /= hipSuccess) error stop
+end
+}]
+}
+
+# Return 1 if AMD HIP's -lamdhip64 is available (no header required).
+
+proc check_effective_target_gomp_libamdhip64 { } {
+ return [check_no_compiler_messages gomp_libamdhip64 executable {
+typedef int hipError_t;
+typedef int hipDevice_t;
+enum { hipSuccess = 0 };
+hipError_t hipDeviceGet(hipDevice_t*, int);
+int main() {
+ hipDevice_t dev;
+ hipError_t r = hipDeviceGet (&dev, 0);
+ if (r != hipSuccess)
+ return 1;
+ return 0;
+} } "-lamdhip64" ]
+}
+
+# Return 1 if AMD HIP's -lamdhip64 is available (no header required).
+
+proc check_effective_target_gomp_libhipblas { } {
+ return [check_no_compiler_messages gomp_libhipblas executable {
+typedef enum { HIPBLAS_STATUS_SUCCESS = 0 } hipblasStatus_t;
+typedef void* hipblasHandle_t;
+hipblasStatus_t hipblasCreate (hipblasHandle_t*);
+int main() {
+ hipblasHandle_t handle;
+ hipblasStatus_t stat = hipblasCreate (&handle);
+ if (stat != HIPBLAS_STATUS_SUCCESS)
+ return 1;
+ return 0;
+} } "-lhipblas" ]
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/interop-2.c b/libgomp/testsuite/libgomp.c-c++-common/interop-2.c
new file mode 100644
index 0000000..a7526dc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/interop-2.c
@@ -0,0 +1,129 @@
+/* { dg-do run } */
+/* { dg-additional-options "-lm" } */
+
+/* Note: At the time this program was written, Nvptx was not asynchronous
+ enough to trigger the issue (with a 'nowait' added); however, one
+ AMD GPUs, it triggered. */
+
+/* Test whether nowait / dependency is handled correctly.
+ Motivated by OpenMP_VV's 5.1/interop/test_interop_target.c
+
+ The code actually only creates a streaming object without actually using it,
+ except for dependency tracking.
+
+ Note that there is a difference between having a steaming (targetsync) object
+ and not (= omp_interop_none); at least if one assumes that omp_interop_none
+ does not include 'targetsync' as (effective) interop type - in that case,
+ 'nowait' has no effect and the 'depend' is active as included task, otherwise
+ the code continues with the depend being active only for the about to be
+ destroyed or used thread.
+
+ The OpenMP spec states (here 6.0):
+ "If the interop-type set includes 'targetsync', an empty mergeable task is
+ generated. If the 'nowait' clause is not present on the construct then
+ the task is also an included task. If the interop-type set does not
+ include 'targetsync', the 'nowait' clause has no effect. Any depend
+ clauses that are present on the construct apply to the generated task. */
+
+#include <omp.h>
+
+void
+test_async (const int dev)
+{
+ constexpr int N = 2048;
+ constexpr int ulp = 4;
+ constexpr double M_PI = 2.0 * __builtin_acos (0.0);
+ omp_interop_t obj1, obj2;
+ double A[N] = { };
+ int B[N] = { };
+
+ /* Create interop object. */
+ #pragma omp interop device(dev) init(targetsync : obj1, obj2)
+
+ if (dev == omp_initial_device || dev == omp_get_num_devices ())
+ {
+ if (obj1 != omp_interop_none || obj2 != omp_interop_none)
+ __builtin_abort ();
+ }
+ else
+ {
+ if (obj1 == omp_interop_none || obj2 == omp_interop_none)
+ __builtin_abort ();
+ }
+
+ /* DOUBLE */
+
+ /* Now in the background update it, slowly enough that the
+ code afterwards is reached while still running asynchronously.
+ As OpenMP_VV's Issue #863 shows, the overhead is high enough to
+ fail even when only doing an atomic integer increment. */
+
+ #pragma omp target device(dev) map(A) depend(out: A[:N]) nowait
+ for (int i = 0; i < N; i++)
+ #pragma omp atomic update
+ A[i] += __builtin_sin (2*i*M_PI/N);
+
+ /* DESTROY take care of the dependeny such that ... */
+
+ if (obj1 == omp_interop_none)
+ {
+ // Same as below as 'nowait' is ignored.
+ #pragma omp interop destroy(obj1) depend(in: A[:N]) nowait
+ }
+ else
+ {
+ #pragma omp interop destroy(obj1) depend(in: A[:N])
+ }
+
+ /* ... this code is only executed once the dependency as been fulfilled. */
+
+ /* Check the value - part I: quick, avoid A[0] == sin(0) = 0. */
+ for (int i = 1; i < N; i++)
+ if (A[i] == 0.0)
+ __builtin_abort ();
+
+ /* Check the value - part II: throughly */
+ for (int i = 0; i < N; i++)
+ {
+ double x = A[i];
+ double y = __builtin_sin (2*i*M_PI/N);
+ if (__builtin_fabs (x - y) > ulp * __builtin_fabs (x+y) * __DBL_EPSILON__)
+ __builtin_abort ();
+ }
+
+ /* Integer */
+
+ #pragma omp target device(dev) map(B) depend(out: B[:N]) nowait
+ for (int i = 0; i < N; i++)
+ #pragma omp atomic update
+ B[i] += 42;
+
+ /* Same - but using USE. */
+ if (obj2 == omp_interop_none)
+ {
+ // Same as below as 'nowait' is ignored.
+ #pragma omp interop use(obj2) depend(in: B[:N]) nowait
+ }
+ else
+ {
+ #pragma omp interop use(obj2) depend(in: B[:N])
+ }
+
+ for (int i = 0; i < N; i++)
+ if (B[i] != 42)
+ __builtin_abort ();
+
+ #pragma omp interop destroy(obj2)
+}
+
+int
+main ()
+{
+ int ndev = omp_get_num_devices ();
+
+ for (int dev = 0; dev <= ndev; dev++)
+ test_async (dev);
+ test_async (omp_initial_device);
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/interop-cublas-full.c b/libgomp/testsuite/libgomp.c/interop-cublas-full.c
new file mode 100644
index 0000000..2df5277
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-cublas-full.c
@@ -0,0 +1,176 @@
+/* { dg-require-effective-target openacc_cublas } */
+/* { dg-additional-options "-lcublas" } */
+
+/* NOTE: This file is also included by libgomp.c-c++-common/interop-cudablas-libonly.c
+ to test the fallback version. */
+
+/* Check whether cuBlas' daxpy works with an interop object.
+ daxpy(N, DA, DX, INCX, DY, INCY)
+ calculates (for DX = DY = 1):
+ DY(1:N) = DY(1:N) + DA * DX(1:N)
+ and otherwise N array elements, taking every INCX-th or INCY-th one, repectively.
+
+Based on the interop example in OpenMP's example document */
+
+/* Minimal check whether CUDA works - by checking whether the API routines
+ seem to work. This includes a fallback if the header is not
+ available. */
+
+#include <assert.h>
+#include <omp.h>
+#include "../libgomp.c-c++-common/on_device_arch.h"
+
+
+#if __has_include(<cuda.h>) && __has_include(<cudaTypedefs.h>) && __has_include(<cuda_runtime.h>) && __has_include(<cublas_v2.h>) && !defined(USE_CUDA_FALLBACK_HEADER)
+ #include <cuda.h>
+ #include <cudaTypedefs.h>
+ #include <cuda_runtime.h>
+ #include <cublas_v2.h>
+
+#else
+ /* Add a poor man's fallback declaration. */
+ #if USE_CUDA_FALLBACK_HEADER
+ // Don't warn.
+ #elif !__has_include(<cuda.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda.h"
+ #elif !__has_include(<cudaTypedefs.h>)
+ #warning "Using GCC's cuda.h as fallback for cudaTypedefs.h"
+ #elif !__has_include(<cuda_runtime.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda_runtime.h"
+ #else
+ #warning "Using GCC's cuda.h as fallback for cublas_v2.h"
+ #endif
+ #include "../../../include/cuda/cuda.h"
+
+ typedef enum {
+ CUBLAS_STATUS_SUCCESS = 0,
+ } cublasStatus_t;
+
+ typedef CUstream cudaStream_t;
+ typedef struct cublasContext* cublasHandle_t;
+
+ #define cublasCreate cublasCreate_v2
+ cublasStatus_t cublasCreate_v2 (cublasHandle_t *);
+
+ #define cublasSetStream cublasSetStream_v2
+ cublasStatus_t cublasSetStream_v2 (cublasHandle_t, cudaStream_t);
+
+ #define cublasDaxpy cublasDaxpy_v2
+ cublasStatus_t cublasDaxpy_v2(cublasHandle_t, int, const double*, const double*, int, double*, int);
+#endif
+
+static int used_variant = 0;
+
+void
+run_cuBlasdaxpy (int n, double da, const double *dx, int incx, double *dy, int incy, omp_interop_t obj)
+{
+ used_variant = 1;
+
+ omp_interop_rc_t res;
+ cublasStatus_t stat;
+
+ omp_intptr_t fr = omp_get_interop_int(obj, omp_ipr_fr_id, &res);
+ assert (res == omp_irc_success && fr == omp_ifr_cuda);
+
+ cudaStream_t stream = (cudaStream_t) omp_get_interop_ptr (obj, omp_ipr_targetsync, &res);
+ assert (res == omp_irc_success);
+
+ cublasHandle_t handle;
+ stat = cublasCreate (&handle);
+ assert (stat == CUBLAS_STATUS_SUCCESS);
+
+ stat = cublasSetStream (handle, stream);
+ assert (stat == CUBLAS_STATUS_SUCCESS);
+
+ /* 'da' can be in host or device space, 'dx' and 'dy' must be in device space. */
+ stat = cublasDaxpy (handle, n, &da, dx, 1, dy, 1) ;
+ assert (stat == CUBLAS_STATUS_SUCCESS);
+}
+
+
+#pragma omp declare variant(run_cuBlasdaxpy) \
+ match(construct={dispatch}, target_device={kind(nohost), arch("nvptx")}) \
+ adjust_args(need_device_ptr : dx, dy) \
+ append_args(interop(targetsync, prefer_type("cuda")))
+
+void
+run_daxpy (int n, double da, const double *dx, int incx, double *dy, int incy)
+{
+ used_variant = 2;
+
+ if (incx == 1 && incy == 1)
+ #pragma omp simd
+ for (int i = 0; i < n; i++)
+ dy[i] += da * dx[i];
+ else
+ {
+ int ix = 0;
+ int iy = 0;
+ for (int i = 0; i < n; i++)
+ {
+ dy[iy] += da * dx[ix];
+ ix += incx;
+ iy += incy;
+ }
+ }
+}
+
+
+void
+run_test (int dev)
+{
+ constexpr int N = 1024;
+
+ // A = {1,2,...,N}
+ // B = {-1, -2, ..., N}
+ // B' = daxpy (N, 3, A, incx=1, B, incy=1)
+ // = B + 3*A
+ // -> B' = {0, 2, 4, 6, ... }
+
+ double A[N], B[N];
+ double factor = 3.0;
+ for (int i = 0; i < N; i++)
+ {
+ A[i] = i;
+ B[i] = -i;
+ }
+
+ if (dev != omp_initial_device && dev != omp_get_num_devices ())
+ {
+ #pragma omp target enter data device(dev) map(A, B)
+ }
+
+ used_variant = 99;
+ #pragma omp dispatch device(dev)
+ run_daxpy (N, factor, A, 1, B, 1);
+
+ if (dev != omp_initial_device && dev != omp_get_num_devices ())
+ {
+ #pragma omp target exit data device(dev) map(release: A) map(from: B)
+
+ int tmp = omp_get_default_device ();
+ omp_set_default_device (dev);
+ if (on_device_arch_nvptx ())
+ assert (used_variant == 1);
+ else
+ assert (used_variant == 2);
+ omp_set_default_device (tmp);
+ }
+ else
+ assert (used_variant == 2);
+
+ for (int i = 0; i < N; i++)
+ assert (B[i] == 2*i);
+}
+
+int
+main ()
+{
+ int ndev = omp_get_num_devices ();
+
+ for (int dev = 0; dev <= ndev; dev++)
+ run_test (dev);
+ run_test (omp_initial_device);
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c/interop-cublas-libonly.c b/libgomp/testsuite/libgomp.c/interop-cublas-libonly.c
new file mode 100644
index 0000000..89c0652
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-cublas-libonly.c
@@ -0,0 +1,7 @@
+/* { dg-require-effective-target openacc_libcublas } */
+/* { dg-additional-options "-lcublas" } */
+
+/* Same as interop-cudablas-full.c, but also works if the header is not available. */
+
+#define USE_CUDA_FALLBACK_HEADER 1
+#include "interop-cublas-full.c"
diff --git a/libgomp/testsuite/libgomp.c/interop-cuda-full.c b/libgomp/testsuite/libgomp.c/interop-cuda-full.c
new file mode 100644
index 0000000..38aa6b1
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-cuda-full.c
@@ -0,0 +1,159 @@
+/* { dg-require-effective-target openacc_cuda } */
+/* { dg-require-effective-target openacc_cudart } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+
+/* NOTE: This file is also included by libgomp.c-c++-common/interop-cuda-libonly.c
+ to test the fallback version, which defines USE_CUDA_FALLBACK_HEADER. */
+
+/* Minimal check whether CUDA works - by checking whether the API routines
+ seem to work. This includes a fallback if the header is not
+ available. */
+
+#include <assert.h>
+#include <omp.h>
+
+#if __has_include(<cuda.h>) && __has_include(<cudaTypedefs.h>) && __has_include(<cuda_runtime.h>) && !defined(USE_CUDA_FALLBACK_HEADER)
+ #include <cuda.h>
+ #include <cudaTypedefs.h>
+ #include <cuda_runtime.h>
+
+#else
+ /* Add a poor man's fallback declaration. */
+ #if USE_CUDA_FALLBACK_HEADER
+ // Don't warn.
+ #elif !__has_include(<cuda.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda.h"
+ #elif !__has_include(<cudaTypedefs.h>)
+ #warning "Using GCC's cuda.h as fallback for cudaTypedefs.h"
+ #else
+ #warning "Using GCC's cuda.h as fallback for cuda_runtime.h"
+ #endif
+ #include "../../../include/cuda/cuda.h"
+
+ typedef int cudaError_t;
+ typedef CUstream cudaStream_t;
+ enum {
+ cudaSuccess = 0
+ };
+
+ enum cudaDeviceAttr {
+ cudaDevAttrClockRate = 13,
+ cudaDevAttrMaxGridDimX = 5
+ };
+
+ cudaError_t cudaDeviceGetAttribute (int *, enum cudaDeviceAttr, int);
+ cudaError_t cudaStreamQuery(cudaStream_t);
+ CUresult cuCtxGetApiVersion(CUcontext, unsigned int *);
+ CUresult cuStreamGetCtx (CUstream, CUcontext *);
+#endif
+
+int
+main ()
+{
+ int ivar;
+ unsigned uvar;
+ omp_interop_rc_t res;
+ omp_interop_t obj_cuda = omp_interop_none;
+ omp_interop_t obj_cuda_driver = omp_interop_none;
+ cudaError_t cuda_err;
+ CUresult cu_err;
+
+ #pragma omp interop init(target, targetsync, prefer_type("cuda") : obj_cuda) \
+ init(target, targetsync, prefer_type("cuda_driver") : obj_cuda_driver) \
+
+ omp_interop_fr_t fr = (omp_interop_fr_t) omp_get_interop_int (obj_cuda, omp_ipr_fr_id, &res);
+ assert (res == omp_irc_success);
+ assert (fr == omp_ifr_cuda);
+
+ fr = (omp_interop_fr_t) omp_get_interop_int (obj_cuda_driver, omp_ipr_fr_id, &res);
+ assert (res == omp_irc_success);
+ assert (fr == omp_ifr_cuda_driver);
+
+ ivar = (int) omp_get_interop_int (obj_cuda, omp_ipr_vendor, &res);
+ assert (res == omp_irc_success);
+ assert (ivar == 11);
+
+ ivar = (int) omp_get_interop_int (obj_cuda_driver, omp_ipr_vendor, &res);
+ assert (res == omp_irc_success);
+ assert (ivar == 11);
+
+
+ /* Check whether the omp_ipr_device -> cudaDevice_t yields a valid device. */
+
+ CUdevice cu_dev = (int) omp_get_interop_int (obj_cuda_driver, omp_ipr_device, &res);
+ assert (res == omp_irc_success);
+
+ /* Assume a clock size is available and > 1 GHz; value is in kHz. */
+ cu_err = cuDeviceGetAttribute (&ivar, cudaDevAttrClockRate, cu_dev);
+ assert (cu_err == CUDA_SUCCESS);
+ assert (ivar > 1000000 /* kHz */);
+
+ /* Assume that the MaxGridDimX is available and > 1024. */
+ cu_err = cuDeviceGetAttribute (&ivar, cudaDevAttrMaxGridDimX, cu_dev);
+ assert (cu_err == CUDA_SUCCESS);
+ assert (ivar > 1024);
+
+ int cuda_dev = (int) omp_get_interop_int (obj_cuda, omp_ipr_device, &res);
+ assert (res == omp_irc_success);
+ assert (cuda_dev == (CUdevice) cu_dev); // Assume they are the same ...
+
+ /* Assume a clock size is available and > 1 GHz; value is in kHz. */
+ cuda_err = cudaDeviceGetAttribute (&ivar, cudaDevAttrClockRate, cuda_dev);
+ assert (cuda_err == cudaSuccess);
+ assert (ivar > 1000000 /* kHz */);
+
+ /* Assume that the MaxGridDimX is available and > 1024. */
+ cuda_err = cudaDeviceGetAttribute (&ivar, cudaDevAttrMaxGridDimX, cuda_dev);
+ assert (cuda_err == cudaSuccess);
+ assert (ivar > 1024);
+
+
+
+
+ /* Check whether the omp_ipr_device_context -> CUcontext yields a context. */
+
+ CUcontext cu_ctx = (CUcontext) omp_get_interop_ptr (obj_cuda_driver, omp_ipr_device_context, &res);
+ assert (res == omp_irc_success);
+
+ /* Assume API Version > 0 for Nvidia, cudaErrorNotSupported for AMD. */
+ uvar = 99;
+ cu_err = cuCtxGetApiVersion (cu_ctx, &uvar);
+ assert (cu_err == CUDA_SUCCESS);
+ assert (uvar > 0);
+
+
+ /* Check whether the omp_ipr_targetsync -> cudaStream_t yields a stream. */
+
+ cudaStream_t cuda_sm = (cudaStream_t) omp_get_interop_ptr (obj_cuda, omp_ipr_targetsync, &res);
+ assert (res == omp_irc_success);
+
+ CUstream cu_sm = (cudaStream_t) omp_get_interop_ptr (obj_cuda_driver, omp_ipr_targetsync, &res);
+ assert (res == omp_irc_success);
+
+ assert ((void*) cu_sm != (void*) cuda_sm); // Type compatible but should have created two streams
+
+ int dev_stream = 99;
+#if CUDA_VERSION >= 12080
+ cuda_err = cudaStreamGetDevice (cuda_sm, &dev_stream);
+ assert (cuda_err == cudaSuccess);
+#else
+ cu_err = cuStreamGetCtx (cu_sm, &cu_ctx) != CUDA_SUCCESS;
+ if (cu_err == CUDA_SUCCESS)
+ cuda_err = cuCtxPushCurrent (cu_ctx) != CUDA_SUCCESS;
+ if (cu_err == CUDA_SUCCESS)
+ cuda_err = cuCtxGetDevice (&dev_stream) != CUDA_SUCCESS;
+ if (cu_err == CUDA_SUCCESS)
+ cu_err = cuCtxPopCurrent (&cu_ctx) != CUDA_SUCCESS;
+ assert (cu_err == CUDA_SUCCESS);
+#endif
+ assert (dev_stream == cuda_dev);
+
+ /* All jobs should have been completed (as there were none none) */
+ cuda_err = cudaStreamQuery (cuda_sm);
+ assert (cuda_err == cudaSuccess);
+
+ cu_err = cuStreamQuery (cu_sm);
+ assert (cu_err == CUDA_SUCCESS);
+
+ #pragma omp interop destroy(obj_cuda, obj_cuda_driver)
+}
diff --git a/libgomp/testsuite/libgomp.c/interop-cuda-libonly.c b/libgomp/testsuite/libgomp.c/interop-cuda-libonly.c
new file mode 100644
index 0000000..17cbb15
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-cuda-libonly.c
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target openacc_libcudart } */
+/* { dg-require-effective-target openacc_libcuda } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+
+/* Same as interop-cuda-full.c, but also works if the header is not available. */
+
+#define USE_CUDA_FALLBACK_HEADER 1
+#include "interop-cuda-full.c"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip-amd-full.c b/libgomp/testsuite/libgomp.c/interop-hip-amd-full.c
new file mode 100644
index 0000000..d7725fc
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip-amd-full.c
@@ -0,0 +1,7 @@
+/* { dg-require-effective-target gomp_hip_header_amd } */
+/* { dg-require-effective-target gomp_libamdhip64 } */
+/* { dg-additional-options "-lamdhip64" } */
+
+#define __HIP_PLATFORM_AMD__ 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip-amd-no-hip-header.c b/libgomp/testsuite/libgomp.c/interop-hip-amd-no-hip-header.c
new file mode 100644
index 0000000..2584537
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip-amd-no-hip-header.c
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target gomp_libamdhip64 } */
+/* { dg-additional-options "-lamdhip64" } */
+
+#define __HIP_PLATFORM_AMD__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip-nvidia-full.c b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-full.c
new file mode 100644
index 0000000..79af47d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-full.c
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target openacc_cudart } */
+/* { dg-require-effective-target openacc_cuda } */
+/* { dg-require-effective-target gomp_hip_header_nvidia } */
+/* { dg-additional-options "-lcuda -lcudart -Wno-deprecated-declarations" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-headers.c b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-headers.c
new file mode 100644
index 0000000..4586398
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-headers.c
@@ -0,0 +1,10 @@
+/* { dg-require-effective-target openacc_libcudart } */
+/* { dg-require-effective-target openacc_libcuda } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+#define USE_CUDA_FALLBACK_HEADER 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-hip-header.c b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-hip-header.c
new file mode 100644
index 0000000..4186984
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip-nvidia-no-hip-header.c
@@ -0,0 +1,9 @@
+/* { dg-require-effective-target openacc_cudart } */
+/* { dg-require-effective-target openacc_cuda } */
+/* { dg-additional-options "-lcuda -lcudart" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hip.h b/libgomp/testsuite/libgomp.c/interop-hip.h
new file mode 100644
index 0000000..20a1ccb
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hip.h
@@ -0,0 +1,234 @@
+/* Minimal check whether HIP works - by checking whether the API routines
+ seem to work. This includes various fallbacks if the header is not
+ available. */
+
+#include <assert.h>
+#include <omp.h>
+
+#if !defined(__HIP_PLATFORM_AMD__) && !defined(__HIP_PLATFORM_NVIDIA__)
+ #error "Either __HIP_PLATFORM_AMD__ or __HIP_PLATFORM_NVIDIA__ must be defined"
+#endif
+
+#if defined(__HIP_PLATFORM_AMD__) && defined(__HIP_PLATFORM_NVIDIA__)
+ #error "Either __HIP_PLATFORM_AMD__ or __HIP_PLATFORM_NVIDIA__ must be defined"
+#endif
+
+#if __has_include(<hip/hip_runtime_api.h>) && !defined(USE_HIP_FALLBACK_HEADER)
+ #include <hip/hip_runtime_api.h>
+
+#elif defined(__HIP_PLATFORM_AMD__)
+ /* Add a poor man's fallback declaration. */
+ #if !defined(USE_HIP_FALLBACK_HEADER)
+ #warning "Using fallback declaration for <hip/hip_runtime_api.h> for __HIP_PLATFORM_AMD__"
+ #endif
+
+ typedef struct ihipStream_t* hipStream_t;
+ typedef struct ihipCtx_t* hipCtx_t;
+ typedef int hipError_t;
+ typedef int hipDevice_t;
+ enum {
+ hipSuccess = 0,
+ hipErrorNotSupported = 801
+ };
+
+ typedef enum hipDeviceAttribute_t {
+ hipDeviceAttributeClockRate = 5,
+ hipDeviceAttributeMaxGridDimX = 29
+ } hipDeviceAttribute_t;
+
+ hipError_t hipDeviceGetAttribute (int *, hipDeviceAttribute_t, hipDevice_t);
+ hipError_t hipCtxGetApiVersion (hipCtx_t, int *);
+ hipError_t hipStreamGetDevice (hipStream_t, hipDevice_t *);
+ hipError_t hipStreamQuery (hipStream_t);
+
+#elif defined(__HIP_PLATFORM_NVIDIA__)
+ /* Add a poor man's fallback declaration. */
+ #if !defined(USE_HIP_FALLBACK_HEADER)
+ #warning "Using fallback declaration for <hip/hip_runtime_api.h> for __HIP_PLATFORM_NVIDIA__"
+ #endif
+
+ #if __has_include(<cuda.h>) && __has_include(<cudaTypedefs.h>) && __has_include(<cuda_runtime.h>) && !defined(USE_CUDA_FALLBACK_HEADER)
+ #include <cuda.h>
+ #include <cudaTypedefs.h>
+ #include <cuda_runtime.h>
+ #else
+ #if defined(USE_CUDA_FALLBACK_HEADER)
+ // no warning
+ #elif !__has_include(<cuda.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda.h"
+ #elif !__has_include(<cudaTypedefs.h>)
+ #warning "Using GCC's cuda.h as fallback for cudaTypedefs.h"
+ #else
+ #warning "Using GCC's cuda.h as fallback for cuda_runtime.h"
+ #endif
+
+ #include "../../../include/cuda/cuda.h"
+
+ typedef int cudaError_t;
+ enum {
+ cudaSuccess = 0
+ };
+
+ enum cudaDeviceAttr {
+ cudaDevAttrClockRate = 13,
+ cudaDevAttrMaxGridDimX = 5
+ };
+
+ cudaError_t cudaDeviceGetAttribute (int *, enum cudaDeviceAttr, int);
+ CUresult cuCtxGetApiVersion(CUcontext, unsigned int *);
+ CUresult cuStreamGetCtx (CUstream, CUcontext *);
+ #endif
+
+ typedef CUstream hipStream_t;
+ typedef CUcontext hipCtx_t;
+ typedef CUdevice hipDevice_t;
+
+ typedef int hipError_t;
+ typedef int hipDevice_t;
+ enum {
+ hipSuccess = 0,
+ hipErrorNotSupported = 801
+ };
+
+
+ typedef enum hipDeviceAttribute_t {
+ hipDeviceAttributeClockRate = 5,
+ hipDeviceAttributeMaxGridDimX = 29
+ } hipDeviceAttribute_t;
+
+ inline static hipError_t
+ hipDeviceGetAttribute (int *ival, hipDeviceAttribute_t attr, hipDevice_t dev)
+ {
+ enum cudaDeviceAttr cuattr;
+ switch (attr)
+ {
+ case hipDeviceAttributeClockRate:
+ cuattr = cudaDevAttrClockRate;
+ break;
+ case hipDeviceAttributeMaxGridDimX:
+ cuattr = cudaDevAttrMaxGridDimX;
+ break;
+ default:
+ assert (0);
+ }
+ return cudaDeviceGetAttribute (ival, cuattr, dev) != cudaSuccess;
+ }
+
+ inline static hipError_t
+ hipCtxGetApiVersion (hipCtx_t ctx, int *ver)
+ {
+ unsigned uver;
+ hipError_t err;
+ err = cuCtxGetApiVersion (ctx, &uver) != CUDA_SUCCESS;
+ *ver = (int) uver;
+ return err;
+ }
+
+ inline static hipError_t
+ hipStreamGetDevice (hipStream_t stream, hipDevice_t *dev)
+ {
+#if CUDA_VERSION >= 12080
+ return cudaStreamGetDevice (stream, dev);
+#else
+ hipError_t err;
+ CUcontext ctx;
+ err = cuStreamGetCtx (stream, &ctx) != CUDA_SUCCESS;
+ if (err == hipSuccess)
+ err = cuCtxPushCurrent (ctx) != CUDA_SUCCESS;
+ if (err == hipSuccess)
+ err = cuCtxGetDevice (dev) != CUDA_SUCCESS;
+ if (err == hipSuccess)
+ err = cuCtxPopCurrent (&ctx) != CUDA_SUCCESS;
+ return err;
+#endif
+ }
+
+ inline static hipError_t
+ hipStreamQuery (hipStream_t stream)
+ {
+ return cuStreamQuery (stream) != CUDA_SUCCESS;
+ }
+
+#else
+ #error "should be unreachable"
+#endif
+
+int
+main ()
+{
+ int ivar;
+ omp_interop_rc_t res;
+ omp_interop_t obj = omp_interop_none;
+ hipError_t hip_err;
+
+ #pragma omp interop init(target, targetsync, prefer_type("hip") : obj)
+
+ omp_interop_fr_t fr = (omp_interop_fr_t) omp_get_interop_int (obj, omp_ipr_fr_id, &res);
+ assert (res == omp_irc_success);
+ assert (fr == omp_ifr_hip);
+
+ ivar = (int) omp_get_interop_int (obj, omp_ipr_vendor, &res);
+ assert (res == omp_irc_success);
+ int vendor_is_amd = ivar == 1;
+ #if defined(__HIP_PLATFORM_AMD__)
+ assert (ivar == 1);
+ #elif defined(__HIP_PLATFORM_NVIDIA__)
+ assert (ivar == 11);
+ #else
+ assert (0);
+ #endif
+
+
+ /* Check whether the omp_ipr_device -> hipDevice_t yields a valid device. */
+
+ hipDevice_t hip_dev = (int) omp_get_interop_int (obj, omp_ipr_device, &res);
+ assert (res == omp_irc_success);
+
+ /* Assume a clock size is available and > 1 GHz; value is in kHz. */
+ hip_err = hipDeviceGetAttribute (&ivar, hipDeviceAttributeClockRate, hip_dev);
+ assert (hip_err == hipSuccess);
+ assert (ivar > 1000000 /* kHz */);
+
+ /* Assume that the MaxGridDimX is available and > 1024. */
+ hip_err = hipDeviceGetAttribute (&ivar, hipDeviceAttributeMaxGridDimX, hip_dev);
+ assert (hip_err == hipSuccess);
+ assert (ivar > 1024);
+
+
+ /* Check whether the omp_ipr_device_context -> hipCtx_t yields a context. */
+
+ hipCtx_t hip_ctx = (hipCtx_t) omp_get_interop_ptr (obj, omp_ipr_device_context, &res);
+ assert (res == omp_irc_success);
+
+ /* Assume API Version > 0 for Nvidia, hipErrorNotSupported for AMD. */
+ ivar = -99;
+ #pragma GCC diagnostic push
+ #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+ hip_err = hipCtxGetApiVersion (hip_ctx, &ivar);
+ #pragma GCC diagnostic pop
+
+ if (vendor_is_amd)
+ assert (hip_err == hipErrorNotSupported && ivar == -99);
+ else
+ {
+ assert (hip_err == hipSuccess);
+ assert (ivar > 0);
+ }
+
+
+ /* Check whether the omp_ipr_targetsync -> hipStream_t yields a stream. */
+
+ hipStream_t hip_sm = (hipStream_t) omp_get_interop_ptr (obj, omp_ipr_targetsync, &res);
+ assert (res == omp_irc_success);
+
+ hipDevice_t dev_stream = 99;
+ hip_err = hipStreamGetDevice (hip_sm, &dev_stream);
+ assert (hip_err == hipSuccess);
+ assert (dev_stream == hip_dev);
+
+ /* All jobs should have been completed (as there were none none) */
+ hip_err = hipStreamQuery (hip_sm);
+ assert (hip_err == hipSuccess);
+
+ #pragma omp interop destroy(obj)
+}
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas-amd-full.c b/libgomp/testsuite/libgomp.c/interop-hipblas-amd-full.c
new file mode 100644
index 0000000..53c05bd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas-amd-full.c
@@ -0,0 +1,7 @@
+/* { dg-require-effective-target gomp_hip_header_amd } */
+/* { dg-require-effective-target gomp_libhipblas } */
+/* { dg-additional-options "-lhipblas" } */
+
+#define __HIP_PLATFORM_AMD__ 1
+
+#include "interop-hipblas.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas-amd-no-hip-header.c b/libgomp/testsuite/libgomp.c/interop-hipblas-amd-no-hip-header.c
new file mode 100644
index 0000000..0ea3133
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas-amd-no-hip-header.c
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target gomp_libhipblas } */
+/* { dg-additional-options "-lhipblas" } */
+
+#define __HIP_PLATFORM_AMD__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+
+#include "interop-hipblas.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-full.c b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-full.c
new file mode 100644
index 0000000..ed428c6
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-full.c
@@ -0,0 +1,7 @@
+/* { dg-require-effective-target openacc_cublas } */
+/* { dg-require-effective-target gomp_hip_header_nvidia } */
+/* { dg-additional-options "-lcublas -Wno-deprecated-declarations" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#include "interop-hipblas.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-headers.c b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-headers.c
new file mode 100644
index 0000000..1a31b30
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-headers.c
@@ -0,0 +1,9 @@
+/* { dg-require-effective-target openacc_libcublas } */
+/* { dg-additional-options "-lcublas" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+#define USE_CUDA_FALLBACK_HEADER 1
+
+#include "interop-hipblas.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-hip-header.c b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-hip-header.c
new file mode 100644
index 0000000..f85c13b
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas-nvidia-no-hip-header.c
@@ -0,0 +1,8 @@
+/* { dg-require-effective-target openacc_cublas } */
+/* { dg-additional-options "-lcublas" } */
+
+#define __HIP_PLATFORM_NVIDIA__ 1
+
+#define USE_HIP_FALLBACK_HEADER 1
+
+#include "interop-hipblas.h"
diff --git a/libgomp/testsuite/libgomp.c/interop-hipblas.h b/libgomp/testsuite/libgomp.c/interop-hipblas.h
new file mode 100644
index 0000000..d7cb174
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c/interop-hipblas.h
@@ -0,0 +1,240 @@
+/* Check whether hipBlas' daxpy works with an interop object.
+ daxpy(N, DA, DX, INCX, DY, INCY)
+ calculates (for DX = DY = 1):
+ DY(1:N) = DY(1:N) + DA * DX(1:N)
+ and otherwise N array elements, taking every INCX-th or INCY-th one, repectively.
+
+Based on the interop example in OpenMP's example document */
+
+/* Minimal check whether HIP works - by checking whether the API routines
+ seem to work. This includes a fallback if the header is not
+ available. */
+
+#if !defined(__HIP_PLATFORM_AMD__) && !defined(__HIP_PLATFORM_NVIDIA__)
+ #error "Either __HIP_PLATFORM_AMD__ or __HIP_PLATFORM_NVIDIA__ must be defined"
+#endif
+
+#if defined(__HIP_PLATFORM_AMD__) && defined(__HIP_PLATFORM_NVIDIA__)
+ #error "Either __HIP_PLATFORM_AMD__ or __HIP_PLATFORM_NVIDIA__ must be defined"
+#endif
+
+
+#include <assert.h>
+#include <omp.h>
+#include "../libgomp.c-c++-common/on_device_arch.h"
+
+
+#if __has_include(<hipblas/hipblas.h>) && (__has_include(<library_types.h>) || !defined(__HIP_PLATFORM_NVIDIA__)) && !defined(USE_HIP_FALLBACK_HEADER)
+ #ifdef __HIP_PLATFORM_NVIDIA__
+ /* There seems to be an issue with hip/library_types.h including
+ CUDA's "library_types.h". Include CUDA's one explicitly here.
+ Could possibly worked around by using -isystem vs. -I. */
+ #include <library_types.h>
+
+ /* For some reasons, the following symbols do not seem to get
+ mapped from HIP to CUDA, causing link errors. */
+ #define hipblasSetStream cublasSetStream_v2
+ #define hipblasDaxpy cublasDaxpy_v2
+ #define hipblasCreate cublasCreate_v2
+ #endif
+ #include <hipblas/hipblas.h>
+
+#elif defined(__HIP_PLATFORM_AMD__)
+ /* Add a poor man's fallback declaration. */
+ #if !defined(USE_HIP_FALLBACK_HEADER)
+ #warning "Using fallback declaration for <hipblas/hipblas.h> for __HIP_PLATFORM_AMD__"
+ #endif
+
+ typedef enum
+ {
+ HIPBLAS_STATUS_SUCCESS = 0
+
+ } hipblasStatus_t;
+
+ typedef struct ihipStream_t* hipStream_t;
+ typedef void* hipblasHandle_t;
+
+ hipblasStatus_t hipblasCreate (hipblasHandle_t*);
+ hipblasStatus_t hipblasSetStream (hipblasHandle_t, hipStream_t);
+ hipblasStatus_t hipblasDaxpy (hipblasHandle_t, int, const double*, const double*, int, double*, int);
+
+#else
+ /* Add a poor man's fallback declaration. */
+ #if !defined(USE_HIP_FALLBACK_HEADER)
+ #warning "Using fallback declaration for <hipblas/hipblas.h> for __HIP_PLATFORM_NVIDA__"
+ #endif
+
+ #if __has_include(<cuda.h>) && __has_include(<cudaTypedefs.h>) && __has_include(<cuda_runtime.h>) && __has_include(<cublas_v2.h>) && !defined(USE_CUDA_FALLBACK_HEADER)
+ #include <cuda.h>
+ #include <cudaTypedefs.h>
+ #include <cuda_runtime.h>
+ #include <cublas_v2.h>
+
+ #else
+ /* Add a poor man's fallback declaration. */
+ #if defined(USE_CUDA_FALLBACK_HEADER)
+ // no warning
+ #elif !__has_include(<cuda.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda.h"
+ #elif !__has_include(<cudaTypedefs.h>)
+ #warning "Using GCC's cuda.h as fallback for cudaTypedefs.h"
+ #elif !__has_include(<cuda_runtime.h>)
+ #warning "Using GCC's cuda.h as fallback for cuda_runtime.h"
+ #else
+ #warning "Using GCC's cuda.h as fallback for cublas_v2.h"
+ #endif
+ #include "../../../include/cuda/cuda.h"
+
+ typedef enum {
+ CUBLAS_STATUS_SUCCESS = 0,
+ } cublasStatus_t;
+
+ typedef CUstream cudaStream_t;
+ typedef struct cublasContext* cublasHandle_t;
+
+ #define cublasCreate cublasCreate_v2
+ cublasStatus_t cublasCreate_v2 (cublasHandle_t *);
+
+ #define cublasSetStream cublasSetStream_v2
+ cublasStatus_t cublasSetStream_v2 (cublasHandle_t, cudaStream_t);
+
+ #define cublasDaxpy cublasDaxpy_v2
+ cublasStatus_t cublasDaxpy_v2(cublasHandle_t, int, const double*, const double*, int, double*, int);
+ #endif
+
+ #define HIPBLAS_STATUS_SUCCESS CUBLAS_STATUS_SUCCESS
+ #define hipblasStatus_t cublasStatus_t
+ #define hipStream_t cudaStream_t
+ #define hipblasHandle_t cublasHandle_t
+ #define hipblasCreate cublasCreate
+ #define hipblasSetStream cublasSetStream
+ #define hipblasDaxpy cublasDaxpy
+#endif
+
+static int used_variant = 0;
+
+void
+run_hipBlasdaxpy (int n, double da, const double *dx, int incx, double *dy, int incy, omp_interop_t obj)
+{
+ used_variant = 1;
+
+ omp_interop_rc_t res;
+ hipblasStatus_t stat;
+
+ omp_intptr_t fr = omp_get_interop_int(obj, omp_ipr_fr_id, &res);
+ assert (res == omp_irc_success && fr == omp_ifr_hip);
+
+ hipStream_t stream = (hipStream_t) omp_get_interop_ptr (obj, omp_ipr_targetsync, &res);
+ assert (res == omp_irc_success);
+
+ hipblasHandle_t handle;
+ stat = hipblasCreate (&handle);
+ assert (stat == HIPBLAS_STATUS_SUCCESS);
+
+ stat = hipblasSetStream (handle, stream);
+ assert (stat == HIPBLAS_STATUS_SUCCESS);
+
+ /* 'da' can be in host or device space, 'dx' and 'dy' must be in device space. */
+ stat = hipblasDaxpy (handle, n, &da, dx, 1, dy, 1) ;
+ assert (stat == HIPBLAS_STATUS_SUCCESS);
+}
+
+#if defined(__HIP_PLATFORM_AMD__)
+#pragma omp declare variant(run_hipBlasdaxpy) \
+ match(construct={dispatch}, target_device={kind(nohost), arch("amdgcn")}) \
+ adjust_args(need_device_ptr : dx, dy) \
+ append_args(interop(targetsync, prefer_type("hip")))
+#elif defined(__HIP_PLATFORM_NVIDIA__)
+#pragma omp declare variant(run_hipBlasdaxpy) \
+ match(construct={dispatch}, target_device={kind(nohost), arch("nvptx")}) \
+ adjust_args(need_device_ptr : dx, dy) \
+ append_args(interop(targetsync, prefer_type("hip")))
+#else
+ #error "wrong platform"
+#endif
+
+void
+run_daxpy (int n, double da, const double *dx, int incx, double *dy, int incy)
+{
+ used_variant = 2;
+
+ if (incx == 1 && incy == 1)
+ #pragma omp simd
+ for (int i = 0; i < n; i++)
+ dy[i] += da * dx[i];
+ else
+ {
+ int ix = 0;
+ int iy = 0;
+ for (int i = 0; i < n; i++)
+ {
+ dy[iy] += da * dx[ix];
+ ix += incx;
+ iy += incy;
+ }
+ }
+}
+
+
+void
+run_test (int dev)
+{
+ constexpr int N = 1024;
+
+ // A = {1,2,...,N}
+ // B = {-1, -2, ..., N}
+ // B' = daxpy (N, 3, A, incx=1, B, incy=1)
+ // = B + 3*A
+ // -> B' = {0, 2, 4, 6, ... }
+
+ double A[N], B[N];
+ double factor = 3.0;
+ for (int i = 0; i < N; i++)
+ {
+ A[i] = i;
+ B[i] = -i;
+ }
+
+ if (dev != omp_initial_device && dev != omp_get_num_devices ())
+ {
+ #pragma omp target enter data device(dev) map(A, B)
+ }
+
+ used_variant = 99;
+ #pragma omp dispatch device(dev)
+ run_daxpy (N, factor, A, 1, B, 1);
+
+ if (dev != omp_initial_device && dev != omp_get_num_devices ())
+ {
+ #pragma omp target exit data device(dev) map(release: A) map(from: B)
+
+ int tmp = omp_get_default_device ();
+ omp_set_default_device (dev);
+#if defined(__HIP_PLATFORM_AMD__)
+ if (on_device_arch_gcn ())
+#else
+ if (on_device_arch_nvptx ())
+#endif
+ assert (used_variant == 1);
+ else
+ assert (used_variant == 2);
+ omp_set_default_device (tmp);
+ }
+ else
+ assert (used_variant == 2);
+
+ for (int i = 0; i < N; i++)
+ assert (B[i] == 2*i);
+}
+
+int
+main ()
+{
+ int ndev = omp_get_num_devices ();
+
+ for (int dev = 0; dev <= ndev; dev++)
+ run_test (dev);
+ run_test (omp_initial_device);
+
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.fortran/interop-hip-amd-full.F90 b/libgomp/testsuite/libgomp.fortran/interop-hip-amd-full.F90
new file mode 100644
index 0000000..bbd49dd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/interop-hip-amd-full.F90
@@ -0,0 +1,7 @@
+! { dg-require-effective-target gomp_hipfort_module }
+! { dg-require-effective-target gomp_libamdhip64 }
+! { dg-additional-options "-lamdhip64" }
+
+#define HAVE_HIPFORT 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.fortran/interop-hip-amd-no-module.F90 b/libgomp/testsuite/libgomp.fortran/interop-hip-amd-no-module.F90
new file mode 100644
index 0000000..0afec83
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/interop-hip-amd-no-module.F90
@@ -0,0 +1,6 @@
+! { dg-require-effective-target gomp_libamdhip64 }
+! { dg-additional-options "-lamdhip64" }
+
+#define USE_HIP_FALLBACK_MODULE 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-full.F90 b/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-full.F90
new file mode 100644
index 0000000..cef592f
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-full.F90
@@ -0,0 +1,9 @@
+! { dg-require-effective-target gomp_hipfort_module }
+! { dg-require-effective-target openacc_cudart }
+! { dg-require-effective-target openacc_cuda }
+! { dg-additional-options "-lcuda -lcudart" }
+
+#define HAVE_HIPFORT 1
+#define USE_CUDA_NAMES 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-no-module.F90 b/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-no-module.F90
new file mode 100644
index 0000000..c1ef29d
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/interop-hip-nvidia-no-module.F90
@@ -0,0 +1,8 @@
+! { dg-require-effective-target openacc_libcudart }
+! { dg-require-effective-target openacc_libcuda }
+! { dg-additional-options "-lcuda -lcudart" }
+
+#define USE_CUDA_NAMES 1
+#define USE_HIP_FALLBACK_MODULE 1
+
+#include "interop-hip.h"
diff --git a/libgomp/testsuite/libgomp.fortran/interop-hip.h b/libgomp/testsuite/libgomp.fortran/interop-hip.h
new file mode 100644
index 0000000..753ccce
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/interop-hip.h
@@ -0,0 +1,214 @@
+! Minimal check whether HIP works - by checking whether the API routines
+! seem to work. This includes a fallback if hipfort is not available
+
+#ifndef HAVE_HIPFORT
+#ifndef USE_HIP_FALLBACK_MODULE
+#if USE_CUDA_NAMES
+#warning "Using fallback implementation for module hipfort as HAVE_HIPFORT is undefined (for NVIDA/CUDA)"
+#else
+#warning "Using fallback implementation for module hipfort as HAVE_HIPFORT is undefined - assume AMD as USE_CUDA_NAMES is unset"
+#endif
+#endif
+module hipfort ! Minimal implementation for the testsuite
+ implicit none
+
+ enum, bind(c)
+ enumerator :: hipSuccess = 0
+ enumerator :: hipErrorNotSupported = 801
+ end enum
+
+ enum, bind(c)
+ enumerator :: hipDeviceAttributeClockRate = 5
+ enumerator :: hipDeviceAttributeMaxGridDimX = 29
+ end enum
+
+ interface
+ integer(kind(hipSuccess)) function hipDeviceGetAttribute (ip, attr, dev) &
+#if USE_CUDA_NAMES
+ bind(c, name="cudaDeviceGetAttribute")
+#else
+ bind(c, name="hipDeviceGetAttribute")
+#endif
+ use iso_c_binding, only: c_ptr, c_int
+ import
+ implicit none
+ type(c_ptr), value :: ip
+ integer(kind(hipDeviceAttributeClockRate)), value :: attr
+ integer(c_int), value :: dev
+ end
+
+ integer(kind(hipSuccess)) function hipCtxGetApiVersion (ctx, ip) &
+#if USE_CUDA_NAMES
+ bind(c, name="cudaCtxGetApiVersion")
+#else
+ bind(c, name="hipCtxGetApiVersion")
+#endif
+ use iso_c_binding, only: c_ptr
+ import
+ implicit none
+ type(c_ptr), value :: ctx, ip
+ end
+
+ integer(kind(hipSuccess)) function hipStreamQuery (stream) &
+#if USE_CUDA_NAMES
+ bind(c, name="cudaStreamQuery")
+#else
+ bind(c, name="hipStreamQuery")
+#endif
+ use iso_c_binding, only: c_ptr
+ import
+ implicit none
+ type(c_ptr), value :: stream
+ end
+
+ integer(kind(hipSuccess)) function hipStreamGetFlags (stream, flags) &
+#if USE_CUDA_NAMES
+ bind(c, name="cudaStreamGetFlags")
+#else
+ bind(c, name="hipStreamGetFlags")
+#endif
+ use iso_c_binding, only: c_ptr
+ import
+ implicit none
+ type(c_ptr), value :: stream
+ type(c_ptr), value :: flags
+ end
+ end interface
+end module
+#endif
+
+program main
+ use iso_c_binding, only: c_ptr, c_int, c_loc
+ use omp_lib
+ use hipfort
+ implicit none (type, external)
+
+! Only supported since CUDA 12.8 - skip for better compatibility
+! ! Manally implement hipStreamGetDevice as hipfort misses it
+! ! -> https://github.com/ROCm/hipfort/issues/238
+! interface
+! integer(kind(hipSuccess)) function my_hipStreamGetDevice(stream, dev) &
+!#if USE_CUDA_NAMES
+! bind(c, name="cudaStreamGetDevice")
+!#else
+! bind(c, name="hipStreamGetDevice")
+!#endif
+! use iso_c_binding, only: c_ptr, c_int
+! import
+! implicit none
+! type(c_ptr), value :: stream
+! integer(c_int) :: dev
+! end
+! end interface
+
+ integer(c_int), target :: ivar
+ integer(omp_interop_rc_kind) :: res
+ integer(omp_interop_kind) :: obj
+ integer(omp_interop_fr_kind) :: fr
+ integer(kind(hipSuccess)) :: hip_err
+ integer(c_int) :: hip_dev, dev_stream
+ type(c_ptr) :: hip_ctx, hip_sm
+
+ logical :: vendor_is_amd
+
+ obj = omp_interop_none
+
+ !$omp interop init(target, targetsync, prefer_type("hip") : obj)
+
+ fr = omp_get_interop_int (obj, omp_ipr_fr_id, res)
+ if (res /= omp_irc_success) error stop 1
+ if (fr /= omp_ifr_hip) error stop 1
+
+ ivar = omp_get_interop_int (obj, omp_ipr_vendor, res)
+ if (ivar == 1) then ! AMD
+ vendor_is_amd = .true.
+ else if (ivar == 11) then ! Nvidia
+ vendor_is_amd = .false.
+ else
+ error stop 1 ! Unknown
+ endif
+#if USE_CUDA_NAMES
+ if (vendor_is_amd) error stop 1
+#else
+ if (.not. vendor_is_amd) error stop 1
+#endif
+
+ ! Check whether the omp_ipr_device -> hipDevice_t yields a valid device.
+
+ hip_dev = omp_get_interop_int (obj, omp_ipr_device, res)
+ if (res /= omp_irc_success) error stop 1
+
+! AMD messed up in Fortran with the attribute handling, missing the
+! translation table it has for C.
+block
+ enum, bind(c)
+ enumerator :: cudaDevAttrClockRate = 13
+ enumerator :: cudaDevAttrMaxGridDimX = 5
+ end enum
+
+ ! Assume a clock size is available and > 1 GHz; value is in kHz.
+ ! c_loc is completely bogus, but as AMD messed up the interface ...
+ ! Cf. https://github.com/ROCm/hipfort/issues/239
+if (vendor_is_amd) then
+ hip_err = hipDeviceGetAttribute (c_loc(ivar), hipDeviceAttributeClockRate, hip_dev)
+else
+ hip_err = hipDeviceGetAttribute (c_loc(ivar), cudaDevAttrClockRate, hip_dev)
+endif
+ if (hip_err /= hipSuccess) error stop 1
+ if (ivar <= 1000000) error stop 1 ! in kHz
+
+ ! Assume that the MaxGridDimX is available and > 1024
+ ! c_loc is completely bogus, but as AMD messed up the interface ...
+ ! Cf. https://github.com/ROCm/hipfort/issues/239
+if (vendor_is_amd) then
+ hip_err = hipDeviceGetAttribute (c_loc(ivar), hipDeviceAttributeMaxGridDimX, hip_dev)
+else
+ hip_err = hipDeviceGetAttribute (c_loc(ivar), cudaDevAttrMaxGridDimX, hip_dev)
+endif
+ if (hip_err /= hipSuccess) error stop 1
+ if (ivar <= 1024) error stop 1
+end block
+
+
+ ! Check whether the omp_ipr_device_context -> hipCtx_t yields a context.
+
+ hip_ctx = omp_get_interop_ptr (obj, omp_ipr_device_context, res)
+ if (res /= omp_irc_success) error stop 1
+
+! ! Assume API Version > 0 for Nvidia, hipErrorNotSupported for AMD. */
+! ivar = -99
+! ! AMD deprectated hipCtxGetApiVersion (in C/C++)
+! hip_err = hipCtxGetApiVersion (hip_ctx, c_loc(ivar))
+!
+! if (vendor_is_amd) then
+! if (hip_err /= hipErrorNotSupported .or. ivar /= -99) error stop 1
+! else
+! if (hip_err /= hipSuccess) error stop 1
+! if (ivar <= 0) error stop 1
+! end if
+
+
+ ! Check whether the omp_ipr_targetsync -> hipStream_t yields a stream.
+
+ hip_sm = omp_get_interop_ptr (obj, omp_ipr_targetsync, res)
+ if (res /= omp_irc_success) error stop 1
+
+! Skip as this is only in CUDA 12.8
+! dev_stream = 99
+! ! Not (yet) implemented: https://github.com/ROCm/hipfort/issues/238
+! ! hip_err = hipStreamGetDevice (hip_sm, dev_stream)
+! hip_err = my_hipStreamGetDevice (hip_sm, dev_stream)
+! if (hip_err /= hipSuccess) error stop 1
+! if (dev_stream /= hip_dev) error stop 1
+
+ ! Get flags of the stream
+ hip_err = hipStreamGetFlags (hip_sm, c_loc (ivar))
+ if (hip_err /= hipSuccess) error stop 1
+ ! Accept any value
+
+ ! All jobs should have been completed (as there were none none)
+ hip_err = hipStreamQuery (hip_sm)
+ if (hip_err /= hipSuccess) error stop 1
+
+ !$omp interop destroy(obj)
+end
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 4615d0f..6433d3f 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,36 @@
+2025-04-24 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/23_containers/forward_list/48101_neg.cc: Remove
+ dg-prune-output that doesn't match anything.
+ * testsuite/23_containers/list/48101_neg.cc: Likewise.
+ * testsuite/23_containers/multiset/48101_neg.cc: Likewise.
+ * testsuite/23_containers/set/48101_neg.cc: Likewise.
+
+2025-04-24 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/generator (generator::yield_value): Add overload
+ taking lvalue element_of view, as per LWG 3899.
+ * testsuite/24_iterators/range_generators/lwg3899.cc: New test.
+
+2025-04-24 François Dumont <frs.dumont@gmail.com>
+
+ * testsuite/util/replacement_memory_operators.h: Adapt for -fno-exceptions
+ context.
+ * testsuite/23_containers/deque/capacity/shrink_to_fit.cc: Adapt test
+ to check std::deque shrink_to_fit method.
+
+2025-04-23 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config/abi/post/powerpc-linux-gnu/baseline_symbols.txt: Update.
+ * config/abi/post/powerpc64-linux-gnu/32/baseline_symbols.txt: Update.
+ * config/abi/post/powerpc64-linux-gnu/baseline_symbols.txt: Update.
+
+2025-04-23 ZENG Hao <c@cyano.cn>
+
+ * src/c++23/std.cc.in (atomic_signed_lock_free): Guard with
+ preprocessor check for __cpp_lib_atomic_lock_free_type_aliases.
+ (atomic_unsigned_lock_free): Likewise.
+
2025-04-22 Patrick Palka <ppalka@redhat.com>
Revert:
diff --git a/libstdc++-v3/include/std/generator b/libstdc++-v3/include/std/generator
index 3f781f1..7ab2c9e 100644
--- a/libstdc++-v3/include/std/generator
+++ b/libstdc++-v3/include/std/generator
@@ -153,6 +153,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
noexcept
{ return _Recursive_awaiter { std::move(__r.range) }; }
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3899. co_yielding elements of an lvalue generator is
+ // unnecessarily inefficient
+ template<typename _R2, typename _V2, typename _A2, typename _U2>
+ requires std::same_as<_Yield2_t<_R2, _V2>, _Yielded>
+ auto
+ yield_value(ranges::elements_of<generator<_R2, _V2, _A2>&, _U2> __r)
+ noexcept
+ { return _Recursive_awaiter { std::move(__r.range) }; }
+
template<ranges::input_range _R, typename _Alloc>
requires convertible_to<ranges::range_reference_t<_R>, _Yielded>
auto
diff --git a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
index 7cb6707..4dbf405 100644
--- a/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
+++ b/libstdc++-v3/testsuite/23_containers/deque/capacity/shrink_to_fit.cc
@@ -1,4 +1,6 @@
// { dg-do run { target c++11 } }
+// { dg-require-effective-target std_allocator_new }
+// { dg-xfail-run-if "AIX operator new" { powerpc-ibm-aix* } }
// 2010-01-08 Paolo Carlini <paolo.carlini@oracle.com>
@@ -19,18 +21,42 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#include <vector>
+#include <deque>
#include <testsuite_hooks.h>
+#include <replacement_memory_operators.h>
// libstdc++/42573
void test01()
{
- std::vector<int> d(100);
- d.push_back(1);
- d.push_back(1);
- // VERIFY( d.size() < d.capacity() );
+ using namespace std;
+ __gnu_test::counter::reset();
+
+ const size_t buf_size = _GLIBCXX_STD_C::__deque_buf_size(sizeof(size_t));
+ deque<size_t> d;
+ for (size_t i = 0; i != buf_size; ++i)
+ d.push_back(i);
+
+ // No shrink if 1st buffer is full, create some front capacity.
+ d.pop_front();
+
+ // 1 node array allocation + 2 node allocation = 3.
+ VERIFY( __gnu_test::counter::count() == 3 );
+ VERIFY( __gnu_test::counter::get()._M_increments == 3 );
+
d.shrink_to_fit();
- // VERIFY( d.size() == d.capacity() );
+
+ // No reallocation if no exception support, shrink_to_fit is then a
+ // no-op.
+#if __cpp_exceptions
+ // 1 node array allocation + 1 node allocation = 2.
+ const int expected_count = 2;
+ const int expected_increments = 2;
+#else
+ const int expected_count = 3;
+ const int expected_increments = 0;
+#endif
+ VERIFY( __gnu_test::counter::count() == expected_count );
+ VERIFY( __gnu_test::counter::get()._M_increments == 3 + expected_increments );
}
int main()
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
index 2f2ea2a..d18195e 100644
--- a/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/48101_neg.cc
@@ -26,6 +26,5 @@ test01()
}
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "rebind_alloc" }
diff --git a/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
index 8b2e075..cc51705 100644
--- a/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/list/48101_neg.cc
@@ -26,5 +26,4 @@ test01()
}
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
diff --git a/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
index f0786cf..3cc0658 100644
--- a/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/multiset/48101_neg.cc
@@ -29,7 +29,6 @@ test01()
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
// { dg-error "comparison object must be invocable" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "no match for call" }
// { dg-prune-output "invalid conversion" }
diff --git a/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc b/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
index e8dec72..fe38d1a 100644
--- a/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/48101_neg.cc
@@ -29,7 +29,6 @@ test01()
// { dg-error "non-const, non-volatile value_type" "" { target *-*-* } 0 }
// { dg-error "comparison object must be invocable" "" { target *-*-* } 0 }
-// { dg-prune-output "std::allocator<.* has no member named " }
// { dg-prune-output "must have the same value_type as its allocator" }
// { dg-prune-output "no match for call" }
// { dg-prune-output "invalid conversion" }
diff --git a/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
new file mode 100644
index 0000000..5a812ec
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/range_generators/lwg3899.cc
@@ -0,0 +1,57 @@
+// { dg-do run { target c++23 } }
+
+// LWG 3899.
+// co_yielding elements of an lvalue generator is unnecessarily inefficient
+
+#include <generator>
+#include <memory_resource>
+#include <testsuite_hooks.h>
+
+struct memory_resource : std::pmr::memory_resource
+{
+ std::size_t count = 0;
+
+ void* do_allocate(std::size_t n, std::size_t a) override
+ {
+ count += n;
+ return std::pmr::new_delete_resource()->allocate(n, a);
+ }
+
+ void do_deallocate(void* p, std::size_t n, std::size_t a) override
+ {
+ return std::pmr::new_delete_resource()->deallocate(p, n, a);
+ }
+
+ bool do_is_equal(const std::pmr::memory_resource& mr) const noexcept override
+ { return this == &mr; }
+};
+
+std::pmr::generator<int>
+f(std::allocator_arg_t, std::pmr::polymorphic_allocator<>, int init)
+{
+ co_yield init + 0;
+ co_yield init + 1;
+}
+
+std::pmr::generator<int>
+g(std::allocator_arg_t, std::pmr::polymorphic_allocator<> alloc)
+{
+ auto gen = f(std::allocator_arg, alloc, 0);
+ auto gen2 = f(std::allocator_arg, alloc, 2);
+ co_yield std::ranges::elements_of(std::move(gen), alloc);
+ co_yield std::ranges::elements_of(gen2, alloc);
+}
+
+int
+main()
+{
+ std::size_t counts[4];
+ memory_resource mr;
+ for (auto d : g(std::allocator_arg , &mr))
+ counts[d] = mr.count;
+ VERIFY(counts[0] != 0);
+ // No allocations after the first one:
+ VERIFY(counts[1] == counts[0]);
+ VERIFY(counts[2] == counts[0]);
+ VERIFY(counts[3] == counts[0]);
+}
diff --git a/libstdc++-v3/testsuite/util/replacement_memory_operators.h b/libstdc++-v3/testsuite/util/replacement_memory_operators.h
index 2516cd2..69afa77 100644
--- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h
+++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h
@@ -36,8 +36,12 @@ namespace __gnu_test
~counter() THROW (counter_error)
{
+#if __cpp_exceptions
if (_M_throw && _M_count != 0)
throw counter_error();
+#else
+ VERIFY( !_M_throw || _M_count == 0 );
+#endif
}
static void
@@ -133,8 +137,12 @@ void* operator new(std::size_t size) THROW(std::bad_alloc)
{
std::printf("operator new is called \n");
void* p = std::malloc(size);
+#if __cpp_exceptions
if (!p)
throw std::bad_alloc();
+#else
+ VERIFY( p );
+#endif
__gnu_test::counter::increment();
return p;
}