Re: [PATCH v2] c++/modules: More fixes for merging DECL_MAYBE_DELETED functions

2025-04-12 Thread Jason Merrill

On 4/10/25 5:35 PM, Nathaniel Shead wrote:

On Thu, Apr 10, 2025 at 12:19:57PM -0400, Jason Merrill wrote:

On 4/10/25 8:46 AM, Nathaniel Shead wrote:

Regression raised with my by private correspondance.
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

My change in r15-9216 broke the case where we imported an uninstantiated
defaulted function over the top of one we had already finished.  This
patch ensures that we don't error for mismatches when either function
has mismatching deferral from the other.


These changes seem to mean that importing a deferred decl can overwrite
properties of an existing non-deferred one.



Right.


To assist in understanding these errors in the future as well, I've
customised the mismatch message for different cases.  I also rephrased
the message to talk about "imported declarations" rather than "global
module declarations", since as the FIXME noted we can also get
mismatches with some declarations attached to modules.  Ideally I'd like
to revisit the way this is structured entirely but that won't be
appropriate for GCC 15.


Please split these changes into a separate commit; that patch is OK.



Thanks, I've attached the patch I'll push after regtest/bootstrap.

The following patch tested so far on x86_64-pc-linux-gnu (only
modules.exp), ok for trunk if full bootstrap+regtest succeeds?


OK.


-- >8 --

My change in r15-9216 broke the case where we imported an uninstantiated
defaulted function over the top of one we had already finished.  This
patch ensures that we don't error for mismatches in this case.

gcc/cp/ChangeLog:

* module.cc (trees_in::is_matching_decl): Don't check for
mismatches when importing a DECL_MAYBE_DELETED function over one
that's already finished.

gcc/testsuite/ChangeLog:

* g++.dg/modules/noexcept-4_a.H: New test.
* g++.dg/modules/noexcept-4_b.C: New test.

Signed-off-by: Nathaniel Shead 
Reviewed-by: Jason Merrill 
---
  gcc/cp/module.cc|  5 -
  gcc/testsuite/g++.dg/modules/noexcept-4_a.H |  6 ++
  gcc/testsuite/g++.dg/modules/noexcept-4_b.C | 18 ++
  3 files changed, 28 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-4_a.H
  create mode 100644 gcc/testsuite/g++.dg/modules/noexcept-4_b.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 8efa18baff1..5ff5c462e79 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -12164,7 +12164,8 @@ trees_in::is_matching_decl (tree existing, tree decl, 
bool is_typedef)
}
}
}
-  else if (!DEFERRED_NOEXCEPT_SPEC_P (d_spec)
+  else if (!DECL_MAYBE_DELETED (d_inner)
+  && !DEFERRED_NOEXCEPT_SPEC_P (d_spec)
   && !comp_except_specs (d_spec, e_spec, ce_type))
{
  mismatch_msg = G_("conflicting % specifier for "
@@ -12195,6 +12196,8 @@ trees_in::is_matching_decl (tree existing, tree decl, 
bool is_typedef)
if (DECL_MAYBE_DELETED (e_inner) && !DECL_MAYBE_DELETED (d_inner)
  && DECL_DECLARED_CONSTEXPR_P (d_inner))
DECL_DECLARED_CONSTEXPR_P (e_inner) = true;
+  else if (!DECL_MAYBE_DELETED (e_inner) && DECL_MAYBE_DELETED (d_inner))
+   /* Nothing to do.  */;
else if (DECL_DECLARED_CONSTEXPR_P (e_inner)
   != DECL_DECLARED_CONSTEXPR_P (d_inner))
{
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-4_a.H 
b/gcc/testsuite/g++.dg/modules/noexcept-4_a.H
new file mode 100644
index 000..b888a1b93e6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/noexcept-4_a.H
@@ -0,0 +1,6 @@
+// { dg-additional-options "-fmodule-header -std=c++20" }
+// { dg-module-cmi {} }
+
+struct exception_ptr {
+  friend bool operator==(const exception_ptr&, const exception_ptr&) = default;
+};
diff --git a/gcc/testsuite/g++.dg/modules/noexcept-4_b.C 
b/gcc/testsuite/g++.dg/modules/noexcept-4_b.C
new file mode 100644
index 000..7cc55316c7c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/noexcept-4_b.C
@@ -0,0 +1,18 @@
+// { dg-additional-options "-fmodules -std=c++20" }
+
+struct exception_ptr {
+  friend bool operator==(const exception_ptr&, const exception_ptr&) = default;
+};
+
+void enqueue() {
+  exception_ptr e;
+  e == e;
+}
+
+import "noexcept-4_a.H";
+
+int main() {
+  constexpr exception_ptr e;
+  static_assert(e == e);
+  static_assert(noexcept(e == e));
+}




[committed] d: Fix -fonly= argument only matches when including full path [PR119758]

2025-04-12 Thread Iain Buclaw
Hi,

This patch fixes a couple issues with the `-fonly=' option in the
D front-end driver.

Using `strcmp' to match the `-fonly=' argument with the input source
file made the feature inflexible to use.  By mistake, the driver was
also found to omit all other modules on the command line as well, which
differed from the documentation on the flag:

Tell the compiler to parse and run semantic analysis on all modules
on the command line, but only generate code for the given argument.

New tests added to check the feature, which didn't exist before.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, and
committed to mainline.

Regards,
Iain.

---
PR d/119758

gcc/d/ChangeLog:

* d-lang.cc (d_parse_file): Use endswith in test for -fonly= argument.
* d-spec.cc (lang_specific_driver): Rework -fonly= and pass all input
files to the front-end compiler when the option is seen.

gcc/testsuite/ChangeLog:

* gdc.dg/driver_fonly1.d: New test.
* gdc.dg/driver_fonly2.d: New test.
* gdc.dg/driver_fonly3.d: New test.
* gdc.dg/imports/fonly.d: New test.
---
 gcc/d/d-lang.cc  |  6 ++--
 gcc/d/d-spec.cc  | 50 +++-
 gcc/testsuite/gdc.dg/driver_fonly1.d |  2 ++
 gcc/testsuite/gdc.dg/driver_fonly2.d |  8 +
 gcc/testsuite/gdc.dg/driver_fonly3.d |  8 +
 gcc/testsuite/gdc.dg/imports/fonly.d |  3 ++
 6 files changed, 51 insertions(+), 26 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/driver_fonly1.d
 create mode 100644 gcc/testsuite/gdc.dg/driver_fonly2.d
 create mode 100644 gcc/testsuite/gdc.dg/driver_fonly3.d
 create mode 100644 gcc/testsuite/gdc.dg/imports/fonly.d

diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index b3786be3c90..0dab76bbfbd 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -1085,9 +1085,9 @@ d_parse_file (void)
   /* Buffer for contents of .ddoc files.  */
   OutBuffer ddocbuf;
 
-  /* In this mode, the first file name is supposed to be a duplicate
- of one of the input files.  */
-  if (d_option.fonly && strcmp (d_option.fonly, main_input_filename) != 0)
+  /* In this mode, the main input file is supposed to be the same as the one
+ given by -fonly=.  */
+  if (d_option.fonly && !endswith (main_input_filename, d_option.fonly))
 error ("%<-fonly=%> argument is different from first input file name");
 
   for (size_t i = 0; i < num_in_fnames; i++)
diff --git a/gcc/d/d-spec.cc b/gcc/d/d-spec.cc
index 7f4a779ab72..c78804812e3 100644
--- a/gcc/d/d-spec.cc
+++ b/gcc/d/d-spec.cc
@@ -104,8 +104,8 @@ lang_specific_driver (cl_decoded_option 
**in_decoded_options,
   /* The total number of arguments with the new stuff.  */
   unsigned int num_args = 1;
 
-  /* "-fonly" if it appears on the command line.  */
-  const char *only_source_option = 0;
+  /* "-fonly=" if it appears on the command line.  */
+  const char *only_source_arg = 0;
 
   /* Whether the -o option was used.  */
   bool saw_opt_o = false;
@@ -280,13 +280,13 @@ lang_specific_driver (cl_decoded_option 
**in_decoded_options,
 
case OPT_fonly_:
  args[i] |= SKIPOPT;
- only_source_option = decoded_options[i].orig_option_with_args_text;
+ only_source_arg = arg;
 
  if (arg != NULL)
{
- const char *suffix = strrchr (only_source_option, '.');
+ const char *suffix = strrchr (only_source_arg, '.');
  if (suffix == NULL || strcmp (suffix, ".d") != 0)
-   only_source_option = concat (only_source_option, ".d", NULL);
+   only_source_arg = concat (only_source_arg, ".d", NULL);
}
  break;
 
@@ -335,48 +335,52 @@ lang_specific_driver (cl_decoded_option 
**in_decoded_options,
 + (phobos_library != PHOBOS_NOLINK) * 4 + 2;
   new_decoded_options = XNEWVEC (cl_decoded_option, num_args);
 
-  i = 0;
   j = 0;
 
   /* Copy the 0th argument, i.e., the name of the program itself.  */
-  new_decoded_options[j++] = decoded_options[i++];
+  new_decoded_options[j++] = decoded_options[0];
 
   /* NOTE: We start at 1 now, not 0.  */
-  while (i < argc)
+  for (i = 1; i < argc; i++)
 {
   if (args[i] & SKIPOPT)
-   {
- ++i;
- continue;
-   }
-
-  new_decoded_options[j] = decoded_options[i];
+   continue;
 
   if (!saw_libcxx && (args[i] & WITHLIBCXX))
{
- --j;
  saw_libcxx = &decoded_options[i];
+ continue;
}
 
-  if (args[i] & DSOURCE)
+  if (only_source_arg && (args[i] & DSOURCE))
{
- if (only_source_option)
-   --j;
+ if (!endswith (decoded_options[i].arg, only_source_arg))
+   continue;
}
 
-  i++;
+  new_decoded_options[j] = decoded_options[i];
   j++;
 }
 
-  if (only_source_option)
+  if (only_source_arg)
 {
-  const char *only_source_arg = only_source_option + 7;
+  /* Generate -fonly= option, then copy D inp

[committed] d: Add option to include imported modules in the compilation [PR109023]

2025-04-12 Thread Iain Buclaw
Hi,

This patch adds the ability to include imported modules in the
compilation, as if they were given on the command line.  When this
option is enabled, all imported modules are compiled except those that
are part of libphobos.

Bootstrapped and regression tested on x86_64-linux-gnu/-m32, and
committed to mainline.

Regards,
Iain.

---
PR d/109023

gcc/d/ChangeLog:

* d-compiler.cc: Include dmd/errors.h.
(Compiler::onImport): Implement.
* d-lang.cc (d_handle_option): Handle -finclude-imports.
(d_parse_file): Run semantic on included imports.
* gdc.texi: Document -finclude-imports.
* lang.opt: Add finclude-imports.
* lang.opt.urls: Regenerate.

gcc/testsuite/ChangeLog:

* gdc.dg/torture/imports/pr109023.d: New test.
* gdc.dg/torture/pr109023.d: New test.
---
 gcc/d/d-compiler.cc   | 37 ++-
 gcc/d/d-lang.cc   | 19 ++
 gcc/d/gdc.texi|  6 +++
 gcc/d/lang.opt|  4 ++
 gcc/d/lang.opt.urls   |  3 ++
 .../gdc.dg/torture/imports/pr109023.d |  3 ++
 gcc/testsuite/gdc.dg/torture/pr109023.d   |  6 +++
 7 files changed, 76 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/gdc.dg/torture/imports/pr109023.d
 create mode 100644 gcc/testsuite/gdc.dg/torture/pr109023.d

diff --git a/gcc/d/d-compiler.cc b/gcc/d/d-compiler.cc
index 160539d08ae..e18f5d33e6a 100644
--- a/gcc/d/d-compiler.cc
+++ b/gcc/d/d-compiler.cc
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 
 #include "dmd/compiler.h"
+#include "dmd/errors.h"
 #include "dmd/expression.h"
 #include "dmd/identifier.h"
 #include "dmd/module.h"
@@ -164,7 +165,39 @@ Compiler::onParseModule (Module *m)
driver intends on compiling the import.  */
 
 bool
-Compiler::onImport (Module *)
+Compiler::onImport (Module *m)
 {
-  return false;
+  if (!includeImports)
+return false;
+
+  if (m->filetype != FileType::d && m->filetype != FileType::c)
+return false;
+
+  /* All imports modules are included except those in the runtime library.  */
+  ModuleDeclaration *md = m->md;
+  if (md && md->id)
+{
+  if (md->packages.length >= 1)
+   {
+ if (!strcmp (md->packages.ptr[0]->toChars (), "core")
+ || !strcmp (md->packages.ptr[0]->toChars (), "std")
+ || !strcmp (md->packages.ptr[0]->toChars (), "gcc")
+ || !strcmp (md->packages.ptr[0]->toChars (), "etc"))
+   return false;
+   }
+  else if (!strcmp (md->id->toChars (), "object"))
+   return false;
+}
+  else if (m->ident)
+{
+  if (!strcmp (m->ident->toChars (), "object"))
+   return false;
+}
+
+  /* This import will be compiled.  */
+  if (global.params.v.verbose)
+message ("compileimport (%s)", m->srcfile.toChars ());
+
+  compiledImports.push (m);
+  return true;
 }
diff --git a/gcc/d/d-lang.cc b/gcc/d/d-lang.cc
index 0dab76bbfbd..ec2ea59938c 100644
--- a/gcc/d/d-lang.cc
+++ b/gcc/d/d-lang.cc
@@ -523,6 +523,10 @@ d_handle_option (size_t scode, const char *arg, 
HOST_WIDE_INT value,
   global.params.ignoreUnsupportedPragmas = value;
   break;
 
+case OPT_finclude_imports:
+  includeImports = true;
+  break;
+
 case OPT_finvariants:
   global.params.useInvariants = value ? CHECKENABLEon : CHECKENABLEoff;
   break;
@@ -1309,6 +1313,21 @@ d_parse_file (void)
   dmd::semantic3 (m, NULL);
 }
 
+  if (includeImports)
+{
+  for (size_t i = 0; i < compiledImports.length; i++)
+   {
+ Module *m = compiledImports[i];
+ gcc_assert (m->isRoot ());
+
+ if (global.params.v.verbose)
+   message ("semantic3 %s", m->toChars ());
+
+ dmd::semantic3 (m, NULL);
+ modules.push (m);
+   }
+}
+
   Module::runDeferredSemantic3 ();
 
   /* Check again, incase semantic3 pass loaded any more modules.  */
diff --git a/gcc/d/gdc.texi b/gcc/d/gdc.texi
index 2cb0c4a6267..3a8bea01050 100644
--- a/gcc/d/gdc.texi
+++ b/gcc/d/gdc.texi
@@ -277,6 +277,12 @@ Sets @code{__traits(getTargetInfo, "cppStd")} to 
@code{202002}.
 Sets @code{__traits(getTargetInfo, "cppStd")} to @code{202302}.
 @end table
 
+@opindex finclude-imports
+@item -finclude-imports
+Include imported modules in the compilation, as if they were given on the
+command line.  When this option is enabled, all imported modules are compiled
+except those that are part of libphobos.
+
 @opindex finvariants
 @opindex fno-invariants
 @item -fno-invariants
diff --git a/gcc/d/lang.opt b/gcc/d/lang.opt
index 50c6f2f4da4..298ff5843ef 100644
--- a/gcc/d/lang.opt
+++ b/gcc/d/lang.opt
@@ -327,6 +327,10 @@ fignore-unknown-pragmas
 D
 Ignore unsupported pragmas.
 
+finclude-imports
+D RejectNegative
+Include imported modules in the compilation.
+
 finvariants
 D Var(flag_invariants)
 Generate code f

Re: Documentation for the REDUCE intrinsic

2025-04-12 Thread Sandra Loosemore

On 4/12/25 01:10, Paul Richard Thomas wrote:

Hi All,

Now that the reduce intrinsic seems to be OK on all platforms, I thought 
that it was time to catch up with the documentation.


The attached produces good .html without any additional warnings or 
errors using texi2any and ~/share/info/gfortran.info 
 is as intended.


OK for mainline?


I took a look at this and it has some pretty substantial 
formatting/markup issues (I routinely inspect PDF output rather than the 
HTML or info since it's more prone to problems).  I'll see what I can do 
to fix it and get back to you hopefully in a day or two; it's going to 
take some trial and error, and it's likely more efficient for me to do 
this than to try to explain to you what to try where.


Also, I assume the "AR41 RAY" is a typo and "ARRAY" is meant there.

-Sandra


Re: [PATCH] c++: improve constexpr call caching [PR115639]

2025-04-12 Thread Patrick Palka
On Sat, 12 Apr 2025, Jason Merrill wrote:

> On 4/11/25 4:36 PM, Patrick Palka wrote:
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > GCC 15 perhaps?
> > 
> > -- >8 --
> > 
> > Here checking
> > 
> >static_assert(0 == big_calc());
> > 
> > takes twice as much time as
> > 
> >constexpr int ret = big_calc();
> >static_assert(0 == ret);
> > 
> > ultimately because in the former, we first constexpr evaluate big_calc()
> > with mce_unknown (as part of warning-dependent folding from
> > cp_build_binary_op).  We then constant evaluate it a second time, with
> > mce_true, during finish_static_assert.  The result of the first
> > evaluation isn't reused because of the different mce_value.
> > 
> > But the call doesn't depend on mce_value at all here (i.e. there's no if
> > consteval or __builtin_is_constant_evaluated calls, nested or otherwise)
> > so we should be able to reuse the result in this case.  Specifically if a
> > constexpr call with mce_unknown gets successfully evaluated, we can safely
> > reuse the result during a subsequent mce_true or mce_false evaluation.
> > 
> > This patch implements this by caching a successful mce_unknown call
> > result into the corresponding mce_true and mce_false slots, so that
> > such a subsequent evaluation effectively reuses the mce_unknown result.
> > To make it more convenient to access the cache slot for the same call
> > with different mce_value, this patch gives each constexpr_call entry
> > three result slots, one per mce_value, instead of having a distinct
> > constexpr_call entry for each mce_value.  And we can no longer use
> > NULL_TREE as the "in progress" result, so instead use unknown_type_node.
> > 
> > After this patch compile time for the above two fragments is the same.
> > 
> > PR c++/115639
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (struct constexpr_call): Add NSDMIs to each
> > field.  Replace 'result' data member with 3-element 'results'
> > array and a 'result' accessor function.  Remove
> > 'manifestly_const_eval' data member.
> > (constexpr_call_hasher::equal): Adjust after constexpr_call
> > layout change.
> > (cxx_eval_call_expression): Likewise.  Define some local
> > variables closer to their first use.  Use unknown_type_node
> > instead of NULL_TREE as the "in progress" result.  After
> > successully evaluating a call with mce_unknown, also cache the
> > result in the corresponding mce_true and mce_false slots.
> > ---
> >   gcc/cp/constexpr.cc | 59 +++--
> >   1 file changed, 35 insertions(+), 24 deletions(-)
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 0242425370f4..a4fd0d072f65 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -1119,20 +1119,22 @@ explain_invalid_constexpr_fn (tree fun)
> > struct GTY((for_user)) constexpr_call {
> > /* Description of the constexpr function definition.  */
> > -  constexpr_fundef *fundef;
> > +  constexpr_fundef *fundef = nullptr;
> > /* Parameter bindings environment.  A TREE_VEC of arguments.  */
> > -  tree bindings;
> > -  /* Result of the call.
> > -   NULL means the call is being evaluated.
> > +  tree bindings = NULL_TREE;
> > +  /* Result of the call, indexed by the value of
> > + constexpr_ctx::manifestly_const_eval.
> > +   unknown_type_node means the call is being evaluated.
> >  error_mark_node means that the evaluation was erroneous or
> > otherwise
> >  uncacheable (e.g. because it depends on the caller).
> >  Otherwise, the actual value of the call.  */
> > -  tree result;
> > +  tree results[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
> > /* The hash of this call; we remember it here to avoid having to
> >recalculate it when expanding the hash table.  */
> > -  hashval_t hash;
> > -  /* The value of constexpr_ctx::manifestly_const_eval.  */
> > -  enum mce_value manifestly_const_eval;
> > +  hashval_t hash = 0;
> > +
> > +  /* The result slot corresponding to the given mce_value.  */
> > +  tree& result (mce_value mce) { return results[1 + int(mce)]; }
> >   };
> > struct constexpr_call_hasher : ggc_ptr_hash
> > @@ -1427,8 +1429,6 @@ constexpr_call_hasher::equal (constexpr_call *lhs,
> > constexpr_call *rhs)
> >   return true;
> > if (lhs->hash != rhs->hash)
> >   return false;
> > -  if (lhs->manifestly_const_eval != rhs->manifestly_const_eval)
> > -return false;
> > if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
> >   return false;
> > return cp_tree_equal (lhs->bindings, rhs->bindings);
> > @@ -2855,9 +2855,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
> > tree t,
> >   {
> > location_t loc = cp_expr_loc_or_input_loc (t);
> > tree fun = get_function_named_in_call (t);
> > -  constexpr_call new_call
> > -= { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
> > -  int 

Re: [PATCH] c++: improve constexpr prvalue folding [PR116416]

2025-04-12 Thread Patrick Palka
On Sat, 12 Apr 2025, Jason Merrill wrote:

> On 4/11/25 4:36 PM, Patrick Palka wrote:
> > Boostrapped and regtested on x86_64-pc-linux- gnu, does this look OK
> > for GCC 15 perhaps?
> > 
> > -- >8 --
> > 
> > This patch improves upon r15-6052-g12de1942a0a673 by performing prvalue
> > folding with mce_false rather than mce_unknown when it's safe to do so
> > (i.e. the caller passed ff_mce_false), so that we can also fold temporary
> > initializers that call is_constant_evaluated etc.
> > 
> > In passing I noticed constexpr-prvalue1.C could more precisely verify
> > the optimization happened by inspecting what the front end spits out
> > instead of the final assembly.
> 
> I'm not sure that specificity is necessary, but OK.

Since we're compiling with -O the middle-end inlines the constructor
call, so the scan-assembler test succeeds even without r15-6052.

> 
> > PR c++/116416
> > 
> > gcc/cp/ChangeLog:
> > 
> > * constexpr.cc (maybe_constant_init_1): Generalize type of
> > of manifestly_const_eval parameter from bool to mce_value.
> > (maybe_constant_init): Define 3-parameter version taking a
> > manifestly_const_eval instead of bool parameter.
> > (cxx_constant_init): Adjust maybe_constant_init_1.
> > * cp-gimplify.cc (cp_fold_r) : Pass mce_false
> > to maybe_constant_init during prvalue folding if ff_mce_false is
> > set.
> > * cp-tree.h (maybe_constant_init): Declare new overload.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/cpp1y/constexpr-prvalue1.C: Adjust to instead inspect
> > the 'original' dump.
> > * g++.dg/cpp1y/constexpr-prvalue1a.C: New test.
> > ---
> >   gcc/cp/constexpr.cc   | 16 +++---
> >   gcc/cp/cp-gimplify.cc |  4 ++-
> >   gcc/cp/cp-tree.h  |  1 +
> >   .../g++.dg/cpp1y/constexpr-prvalue1.C | 11 ---
> >   .../g++.dg/cpp1y/constexpr-prvalue1a.C| 32 +++
> >   5 files changed, 53 insertions(+), 11 deletions(-)
> >   create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue1a.C
> > 
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index 497f64f3ceaa..0242425370f4 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -9679,7 +9679,7 @@ fold_non_dependent_init (tree t,
> > static tree
> >   maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
> > -  bool manifestly_const_eval)
> > +  mce_value manifestly_const_eval)
> >   {
> > if (!t)
> >   return t;
> > @@ -9709,13 +9709,13 @@ maybe_constant_init_1 (tree t, tree decl, bool
> > allow_non_constant,
> > bool is_static = (decl && DECL_P (decl)
> > && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
> > if (is_static)
> > -   manifestly_const_eval = true;
> > +   manifestly_const_eval = mce_true;
> >   -  if (cp_unevaluated_operand && !manifestly_const_eval)
> > +  if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
> > return fold_to_constant (t);
> >   t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
> > !is_static,
> > -   mce_value (manifestly_const_eval),
> > +   manifestly_const_eval,
> > false, decl);
> >   }
> > if (TREE_CODE (t) == TARGET_EXPR)
> > @@ -9731,6 +9731,12 @@ maybe_constant_init_1 (tree t, tree decl, bool
> > allow_non_constant,
> > tree
> >   maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
> > +{
> > +  return maybe_constant_init_1 (t, decl, true, mce_value
> > (manifestly_const_eval));
> > +}
> > +
> > +tree
> > +maybe_constant_init (tree t, tree decl, mce_value manifestly_const_eval)
> >   {
> > return maybe_constant_init_1 (t, decl, true, manifestly_const_eval);
> >   }
> > @@ -9740,7 +9746,7 @@ maybe_constant_init (tree t, tree decl, bool
> > manifestly_const_eval)
> >   tree
> >   cxx_constant_init (tree t, tree decl)
> >   {
> > -  return maybe_constant_init_1 (t, decl, false, true);
> > +  return maybe_constant_init_1 (t, decl, false, mce_true);
> >   }
> > #if 0
> > diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
> > index 550cea29dd29..8dfa5ac2b88d 100644
> > --- a/gcc/cp/cp-gimplify.cc
> > +++ b/gcc/cp/cp-gimplify.cc
> > @@ -1480,7 +1480,9 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void
> > *data_)
> >   *walk_subtrees = 0;
> >   if (!flag_no_inline)
> > {
> > - tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT
> > (stmt));
> > + tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT
> > (stmt),
> > +(data->flags & ff_mce_false
> > + ? mce_false : mce_unknown));
> >   if (folded != init && TREE_CONSTANT (folded))
> > init = folded;
> > }
> > di

[PATCH] testsuite: unxfail ira-shrinkwrap-prep-[12].c for x86_64 [PR117706]

2025-04-12 Thread Andrew Pinski
When late combine was enabled for x86_64 (r15-1735-ge62ea4fb8ffcab),
these 2 testcases start to xpass in a similar fashion as when late
combine was added and the testcase was updated for aarch64 not to
xfail them there.

Pushed as obvious after a test to make sure the testcase no longer xpass.

PR testsuite/117706
gcc/testsuite/ChangeLog:

* gcc.dg/ira-shrinkwrap-prep-1.c: Unxfail for i?68-*-* and x86_64-*-*.
* gcc.dg/ira-shrinkwrap-prep-2.c: Likewise.

Signed-off-by: Andrew Pinski 
---
 gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c | 2 +-
 gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c 
b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
index 8c150972f95..2be31fa296d 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-1.c
@@ -25,5 +25,5 @@ bar (long a)
 }
 
 /* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } 
*/
-/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" { xfail { ! 
aarch64*-*-* } } } } */
+/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" { xfail { ! 
{ aarch64*-*-* i?86-*-* x86_64-*-* } } } } } */
 /* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" 
} } */
diff --git a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c 
b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
index 0690e036eaa..61ee4c6dfb9 100644
--- a/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
+++ b/gcc/testsuite/gcc.dg/ira-shrinkwrap-prep-2.c
@@ -30,6 +30,6 @@ bar (long a)
 }
 
 /* { dg-final { scan-rtl-dump "Will split live ranges of parameters" "ira" } } 
*/
-/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" { xfail { ! 
aarch64*-*-* } } } } */
+/* { dg-final { scan-rtl-dump "Split live-range of register" "ira" { xfail { ! 
{ aarch64*-*-* i?86-*-* x86_64-*-* } } } } } */
 /* XFAIL due to PR70681.  */ 
 /* { dg-final { scan-rtl-dump "Performing shrink-wrapping" "pro_and_epilogue" 
{ xfail arm*-*-* powerpc*-*-* } } } */
-- 
2.43.0



[PUSHED] Fortran: Add code gen for do, concurrent's LOCAL/LOCAL_INIT: Fix 'static_assert' [PR101602]

2025-04-12 Thread Thomas Schwinge
Fix-up for commit 2d7e1d6e40a13a5f160b584336795b80f193ec3b
"Fortran: Add code gen for do,concurrent's LOCAL/LOCAL_INIT [PR101602]":

../../source-gcc/gcc/fortran/trans-stmt.cc: In function ‘void 
gfc_trans_concurrent_locality_spec(bool, stmtblock_t*, 
std::vector*, gfc_expr_list**)’:
../../source-gcc/gcc/fortran/trans-stmt.cc:5157:59: error: expected ‘,’ 
before ‘)’ token
   static_assert (LOCALITY_LOCAL_INIT - LOCALITY_LOCAL == 1);
   ^
../../source-gcc/gcc/fortran/trans-stmt.cc:5157:59: error: expected 
string-literal before ‘)’ token
make[2]: *** [Makefile:1210: fortran/trans-stmt.o] Error 1

PR fortran/101602
gcc/fortran/
* trans-stmt.cc (gfc_trans_concurrent_locality_spec): Fix
'static_assert'.
---
 gcc/fortran/trans-stmt.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index 94ecde096d5..37f8acaea3f 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -5154,7 +5154,7 @@ gfc_trans_concurrent_locality_spec (bool after_body, 
stmtblock_t *body,
   gfc_start_saved_local_decls ();
 
   cnt = 0;
-  static_assert (LOCALITY_LOCAL_INIT - LOCALITY_LOCAL == 1);
+  static_assert (LOCALITY_LOCAL_INIT - LOCALITY_LOCAL == 1, "locality_type");
   for (int type = LOCALITY_LOCAL;
type <= LOCALITY_LOCAL_INIT; type++)
 for (el = locality_list[type]; el; el = el->next)
-- 
2.34.1



Documentation for the REDUCE intrinsic

2025-04-12 Thread Paul Richard Thomas
Hi All,

Now that the reduce intrinsic seems to be OK on all platforms, I thought
that it was time to catch up with the documentation.

The attached produces good .html without any additional warnings or errors
using texi2any and ~/share/info/gfortran.info is as intended.

OK for mainline?

Paul
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 8c160e58b00..6fa6fc278be 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -270,6 +270,7 @@ Some basic guidelines for editing this document:
 * @code{RANGE}: RANGE, Decimal exponent range
 * @code{RANK} : RANK,  Rank of a data object
 * @code{REAL}:  REAL,  Convert to real type 
+* @code{REDUCE}:REDUCE,Reduction of an array with a user function
 * @code{RENAME}:RENAME,Rename a file
 * @code{REPEAT}:REPEAT,Repeated string concatenation
 * @code{RESHAPE}:   RESHAPE,   Function to reshape an array
@@ -12410,6 +12411,107 @@ integers}).
 
 
 
+@node REDUCE
+@section @code{REDUCE} --- Reduction of an array with a user function
+@fnindex REDUCE
+@cindex array, change dimensions
+@cindex array, transmogrify
+
+@table @asis
+@item @emph{Synopsis}:
+@code{RESULT = REDUCE (ARRAY, OPERATION [, MASK, IDENTITY, ORDERED])}
+or
+@code{RESULT = REDUCE (ARRAY, OPERATION, DIM [, MASK, IDENTITY, ORDERED])}
+
+@item @emph{Description}:
+Reduces @var{ARRAY} using the scalar function @var{OPERATION}. If DIM 
+is not present the result is a scalar. Otherwise, the reduction takes 
+place along the dimension @var{DIM} and the result has a rank one less 
+than that of @var{ARRAY}. @var{MASK} is a logical array with the same 
+shape as @var{ARRAY}. If any elements of the reduction are empty, they 
+are filled by @var{IDENTITY}. @var{ORDERED} has no effect at present.
+
+@item @emph{Class}:
+Transformational function
+
+@item @emph{Arguments}:
+@multitable @columnfractions .15 .70
+@item @var{ARRAY} @tab Shall be an array of any type.
+@item @var{OPERATION} @tab Shall be a pure function with exactly two 
+arguments; each argument shall be a scalar, nonallocatable, 
+noncoarray, nonpointer, nonpolymorphic, nonoptional dummy data object 
+with the same declared type and type parameters as @var{ARRAY}. If one 
+argument has the ASYNCHRONOUS, TARGET, or VALUE attribute, the other 
+shall have that attribute. Its result shall be a nonpolymorphic scalar 
+and have the same declared type and type parameters as @var{ARRAY}. 
+@var{OPERATION} should implement a mathematically associative 
+operation. It need not be commutative.
+@item @var{DIM} @tab Shall be an integer scalar with a value in the 
+range 1 ≤ @var{DIM} ≤ n, where n is the rank of @var{ARRAY}.
+@item @var{MASK} @tab (Optional) shall be of type logical and shall be 
+conformable with @var{ARRAY}.
+@item @var{IDENTITY} @tab (Optional) shall be scalar with the same 
+declared type and type parameters as @var{ARRAY}.
+@item @var{ORDERED} @tab (Optional) shall be a logical scalar.
+@end multitable
+
+
+@item @emph{Return value}:
+The result is of the same declared type and type parameters as 
+@var{ARRAY}. It is scalar if @var{DIM} does not appear; otherwise, the 
+result has rank n − 1 and shape [d1, d2, . . . , d@var{DIM}−1, 
+d@var{DIM}+1, . . . , dn] where [d1, d2, . . . , dn] is the shape of 
+@var{ARRAY}.
+
+Case (i): The result of @code{REDUCE (ARRAY, OPERATION [, IDENTITY = 
+IDENTITY, ORDERED = ORDERED])} over the sequence of values in 
+@var{ARRAY} is the result of an iterative process. The initial order 
+of the sequence is array element order. While the sequence has more 
+than one element, each iteration involves the execution of @code{r 
+= OPERATION(x, y)} for adjacent x and y in the sequence, with x 
+immediately preceding y, and the subsequent replacement of x and y 
+with r; if @var{ORDERED} is present with the value true, x and y shall 
+be the first two elements of the sequence. The process continues until 
+the sequence has only one element which is the value of the reduction. 
+If the initial sequence is empty, the result has the value 
+@var{IDENTITY} if @var{IDENTITY} is present, and otherwise, error 
+termination is initiated.
+
+Case (ii): The result of @code{REDUCE (ARRAY, OPERATION, MASK = MASK 
+[, IDENTITY = IDENTITY, ORDERED = ORDERED])} is as for Case (i) except 
+that the initial sequence is only those elements of @var{ARRAY} for 
+which the corresponding elements of @var{MASK} are true.
+
+Case (iii): If @var{ARRAY} has rank one, @code{REDUCE (ARRAY, 
+OPERATION, DIM = DIM [, MASK = MASK, IDENTITY = IDENTITY, ORDERED = 
+ORDERED])} has a value equal to that of @code{REDUCE (AR41 RAY, 
+OPERATION [, MASK = MASK, IDENTITY = IDENTITY, ORDERED = ORDERED])}. 
+Otherwise, the value of element (s1, s2, . . . , sDIM−1, sDIM+1, . . . 
+, sn) of @code{REDUCE (ARRAY, OPERATION, DIM = DIM [, MASK = MASK, 
+IDENTITY = IDENTITY, ORDERED = ORDERED])} is equal to @code{REDUCE 
+(ARRAY (s1, s2, . . . , 

[COMMITTED] Doc: Explicitly document extensions implied by -march=x86_64 [PR97585]

2025-04-12 Thread Sandra Loosemore
gcc/ChangeLog
PR target/97585
* doc/invoke.texi (x86 Options): Document list of extensions
supported by -march=x86_64, according to the declaration of
PTA_X86_64_BASELINE in config/i386/i386.h.
---
 gcc/doc/invoke.texi | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 4be80a7f7f9..fbaa29f4925 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -34838,7 +34838,8 @@ produces code optimized for the local machine under the 
constraints
 of the selected instruction set.
 
 @item x86-64
-A generic CPU with 64-bit extensions.
+A generic CPU with 64-bit extensions, MMX, SSE, SSE2, and FXSR instruction set
+support.
 
 @item x86-64-v2
 @itemx x86-64-v3
-- 
2.34.1



[PATCH] libstdc++: Fix std::string construction from volatile char* [PR119748]

2025-04-12 Thread Jonathan Wakely
My recent r15-9381-g648d5c26e25497 change assumes that a contiguous
iterator with the correct value_type can be converted to a const charT*
but that's not true for volatile charT*. The optimization should only be
done if it can be converted to the right pointer type.

Additionally, the generic loop for non-contiguous iterators needs an
explicit cast to deal with iterators that have a reference type that is
not explicitly convertible to charT.

libstdc++-v3/ChangeLog:

PR libstdc++/119748
* include/bits/basic_string.h (_S_copy_chars): Only optimize for
contiguous iterators that are convertible to const charT*. Use
explicit conversion to charT after dereferencing iterator.
(_S_copy_range): Likewise for contiguous ranges.
* include/bits/cow_string.h (_S_copy_chars): Likewise.
(basic_string(from_range_t, R&&, const Alloc&)): Likewise.
* testsuite/21_strings/basic_string/cons/char/119748.cc: New
test.
* testsuite/21_strings/basic_string/cons/wchar_t/119748.cc:
New test.
---

Tested x86_64-linux.

The static_cast<_CharT>(*__k1) bit in _S_copy_chars is relevant for the
branches too. Thinking about it now, I should probably add another
test with iterators that have a value_type with 'explicit operator char()'
because volatile char* isn't the only case that fails.

 libstdc++-v3/include/bits/basic_string.h  | 24 +--
 libstdc++-v3/include/bits/cow_string.h| 17 +
 .../basic_string/cons/char/119748.cc  | 11 +
 .../basic_string/cons/wchar_t/119748.cc   | 11 +
 4 files changed, 51 insertions(+), 12 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/cons/char/119748.cc
 create mode 100644 
libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/119748.cc

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 9c431c765ab..c90bd099b63 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -488,8 +488,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
  is_same<_IterBase, const _CharT*>>::value)
_S_copy(__p, std::__niter_base(__k1), __k2 - __k1);
 #if __cpp_lib_concepts
- else if constexpr (contiguous_iterator<_Iterator>
-  && is_same_v, _CharT>)
+ else if constexpr (requires {
+  requires contiguous_iterator<_Iterator>;
+  { std::to_address(__k1) }
+-> convertible_to;
+})
{
  const auto __d = __k2 - __k1;
  (void) (__k1 + __d); // See P3349R1
@@ -499,7 +502,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
  else
 #endif
  for (; __k1 != __k2; ++__k1, (void)++__p)
-   traits_type::assign(*__p, *__k1); // These types are off.
+   traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
 #pragma GCC diagnostic pop
 
@@ -527,12 +530,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
static constexpr void
_S_copy_range(pointer __p, _Rg&& __rg, size_type __n)
{
- if constexpr (ranges::contiguous_range<_Rg>
- && is_same_v, _CharT>)
+ if constexpr (requires {
+ requires ranges::contiguous_range<_Rg>;
+ { ranges::data(std::forward<_Rg>(__rg)) }
+   -> convertible_to;
+   })
_S_copy(__p, ranges::data(std::forward<_Rg>(__rg)), __n);
  else
-   for (auto&& __e : __rg)
- traits_type::assign(*__p++, std::forward(__e));
+   {
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+   traits_type::assign(*__p++, static_cast<_CharT>(*__first));
+   }
}
 #endif
 
diff --git a/libstdc++-v3/include/bits/cow_string.h 
b/libstdc++-v3/include/bits/cow_string.h
index b250397151b..f9df2be20be 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -423,7 +423,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2)
{
  for (; __k1 != __k2; ++__k1, (void)++__p)
-   traits_type::assign(*__p, *__k1); // These types are off.
+   traits_type::assign(*__p, static_cast<_CharT>(*__k1));
}
 
   static void
@@ -656,12 +656,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
  reserve(__n);
  pointer __p = _M_data();
- if constexpr (ranges::contiguous_range<_Rg>
- && is_same_v, _CharT>)
+ if constexpr (requires {
+ requires ranges::contiguous_range<_Rg>;
+ { ranges::d

Re: [PATCH] [riscv] vec_dup immediate constants in pred_broadcast expand [PR118182]

2025-04-12 Thread Jeff Law




On 4/12/25 12:41 AM, Alexandre Oliva wrote:


pr118182-2.c fails on gcc-14 because it lacks the late_combine passes,
particularly the one that runs after register allocation.

Even in the trunk, the predicate broadcast for the add reduction is
expanded and register-allocated as _zvfh, taking up an unneeded scalar
register to hold the constant to be vec_duplicated.

It is the late combine pass after register allocation that substitutes
this unneeded scalar register into the vec_duplicate, resolving to the
_zero or _imm insns.

It's easy enough and more efficient to expand pred_broadcast to the
insns that take the already-duplicated vector constant, when the
operands satisfy the predicates of the _zero or _imm insns.

Regression-tested with gcc-14 x86_64-linux-gnu-hosted crosses to
riscv64-elf and riscv32-elf.  Also smoke-tested on trunk, still passing
the pr118182-2.c test with a cross to riscv64-elf.  Ok to install?


for  gcc/ChangeLog

PR target/118182
* config/riscv/vector.md (@pred_broadcast): Expand to
_zero and _imm variants without vec_duplicate.
I'd said this should tend to wait for gcc-16 since it doesn't fix a 
regression.


I will note that what you've found is relatively common in the RISC-V 
port; we've generally been tackling problems with combiner patterns 
rather than looking at whether or not we should be generating better 
code earlier (say at expand time).  My intern and I are working through 
these issues with the basic logical ops now.  This is a blocker to 
removing mvconst_internal.


So just keep it in mind as you're poking around -- what you're finding 
likely will show up elsewhere and I'm supportive of moving this stuff to 
expansion time.


jeff




[PATCH] Add a bootstrap-native build config

2025-04-12 Thread Andi Kleen
From: Andi Kleen 

... that uses -march=native -mtune=native to build a compiler optimized
for the host.

config/ChangeLog:

* bootstrap-native.mk: New file.

gcc/ChangeLog:

* doc/install.texi: Document bootstrap-native.
---
 config/bootstrap-native.mk | 1 +
 gcc/doc/install.texi   | 7 +++
 2 files changed, 8 insertions(+)
 create mode 100644 config/bootstrap-native.mk

diff --git a/config/bootstrap-native.mk b/config/bootstrap-native.mk
new file mode 100644
index 000..a4a3d859408
--- /dev/null
+++ b/config/bootstrap-native.mk
@@ -0,0 +1 @@
+BOOT_CFLAGS := -march=native -mtune=native $(BOOT_CFLAGS)
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 4973f195daf..04a2256b97a 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -3052,6 +3052,13 @@ Removes any @option{-O}-started option from 
@code{BOOT_CFLAGS}, and adds
 @itemx @samp{bootstrap-Og}
 Analogous to @code{bootstrap-O1}.
 
+@item @samp{bootstrap-native}
+@itemx @samp{bootstrap-native}
+Optimize the compiler code for the build host, if supported by the
+architecture. Note this only affects the compiler, not the targeted
+code. If you want the later, choose options suitable to the target you
+are looking for. For example @samp{--with-cpu} would be a good starting point.
+
 @item @samp{bootstrap-lto}
 Enables Link-Time Optimization for host tools during bootstrapping.
 @samp{BUILD_CONFIG=bootstrap-lto} is equivalent to adding
-- 
2.47.1



[Ada] Fix PR ada/119643

2025-04-12 Thread Eric Botcazou
The language says that the profile of a subprogram renaming-as-declaration 
must be mode conformant with that of the renamed subprogram, and that the 
parameter subtypes are taken from the renamed subprogram.

GNAT implements the rule, except when Natural and Positive are involved, which 
may lead to the wrong conclusion that it does not.

Tested on x86-64/Linux, applied on the mainline.


2025-04-12  Eric Botcazou  

PR ada/119643
* sem_ch8.adb (Inherit_Renamed_Profile): Add guard against the
peculiarities of Natural and Positive.


2025-04-12  Eric Botcazou  

* gnat.dg/renaming17.adb: New test.

-- 
Eric Botcazou
diff --git a/gcc/ada/sem_ch8.adb b/gcc/ada/sem_ch8.adb
index d4ab44fee92..0a9ef419db7 100644
--- a/gcc/ada/sem_ch8.adb
+++ b/gcc/ada/sem_ch8.adb
@@ -9314,11 +9314,12 @@ package body Sem_Ch8 is
 
 --  If the new type is a renaming of the old one, as is the case
 --  for actuals in instances, retain its name, to simplify later
---  disambiguation.
+--  disambiguation. Beware of Natural and Positive, see Cstand.
 
 if Nkind (Parent (New_T)) = N_Subtype_Declaration
   and then Is_Entity_Name (Subtype_Indication (Parent (New_T)))
   and then Entity (Subtype_Indication (Parent (New_T))) = Old_T
+  and then Scope (New_T) /= Standard_Standard
 then
null;
 else
-- { dg-do run }

procedure Renaming17 is

  function Incr (V : Integer; I : Integer := 1) return Integer is
(V + I);

  function Incr_Ren (V : Integer; I : Positive := 1) return Positive
renames Incr;

  I : Integer;

begin
  I := Incr_Ren (-3);
  I := Incr_Ren (-3, 2);
  I := Incr_Ren (-3, 0);
end;


Re: [PATCH] c++: improve constexpr call caching [PR115639]

2025-04-12 Thread Jason Merrill

On 4/11/25 4:36 PM, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
GCC 15 perhaps?

-- >8 --

Here checking

   static_assert(0 == big_calc());

takes twice as much time as

   constexpr int ret = big_calc();
   static_assert(0 == ret);

ultimately because in the former, we first constexpr evaluate big_calc()
with mce_unknown (as part of warning-dependent folding from
cp_build_binary_op).  We then constant evaluate it a second time, with
mce_true, during finish_static_assert.  The result of the first
evaluation isn't reused because of the different mce_value.

But the call doesn't depend on mce_value at all here (i.e. there's no if
consteval or __builtin_is_constant_evaluated calls, nested or otherwise)
so we should be able to reuse the result in this case.  Specifically if a
constexpr call with mce_unknown gets successfully evaluated, we can safely
reuse the result during a subsequent mce_true or mce_false evaluation.

This patch implements this by caching a successful mce_unknown call
result into the corresponding mce_true and mce_false slots, so that
such a subsequent evaluation effectively reuses the mce_unknown result.
To make it more convenient to access the cache slot for the same call
with different mce_value, this patch gives each constexpr_call entry
three result slots, one per mce_value, instead of having a distinct
constexpr_call entry for each mce_value.  And we can no longer use
NULL_TREE as the "in progress" result, so instead use unknown_type_node.

After this patch compile time for the above two fragments is the same.

PR c++/115639

gcc/cp/ChangeLog:

* constexpr.cc (struct constexpr_call): Add NSDMIs to each
field.  Replace 'result' data member with 3-element 'results'
array and a 'result' accessor function.  Remove
'manifestly_const_eval' data member.
(constexpr_call_hasher::equal): Adjust after constexpr_call
layout change.
(cxx_eval_call_expression): Likewise.  Define some local
variables closer to their first use.  Use unknown_type_node
instead of NULL_TREE as the "in progress" result.  After
successully evaluating a call with mce_unknown, also cache the
result in the corresponding mce_true and mce_false slots.
---
  gcc/cp/constexpr.cc | 59 +++--
  1 file changed, 35 insertions(+), 24 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0242425370f4..a4fd0d072f65 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1119,20 +1119,22 @@ explain_invalid_constexpr_fn (tree fun)
  
  struct GTY((for_user)) constexpr_call {

/* Description of the constexpr function definition.  */
-  constexpr_fundef *fundef;
+  constexpr_fundef *fundef = nullptr;
/* Parameter bindings environment.  A TREE_VEC of arguments.  */
-  tree bindings;
-  /* Result of the call.
-   NULL means the call is being evaluated.
+  tree bindings = NULL_TREE;
+  /* Result of the call, indexed by the value of
+ constexpr_ctx::manifestly_const_eval.
+   unknown_type_node means the call is being evaluated.
 error_mark_node means that the evaluation was erroneous or otherwise
 uncacheable (e.g. because it depends on the caller).
 Otherwise, the actual value of the call.  */
-  tree result;
+  tree results[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
/* The hash of this call; we remember it here to avoid having to
   recalculate it when expanding the hash table.  */
-  hashval_t hash;
-  /* The value of constexpr_ctx::manifestly_const_eval.  */
-  enum mce_value manifestly_const_eval;
+  hashval_t hash = 0;
+
+  /* The result slot corresponding to the given mce_value.  */
+  tree& result (mce_value mce) { return results[1 + int(mce)]; }
  };
  
  struct constexpr_call_hasher : ggc_ptr_hash

@@ -1427,8 +1429,6 @@ constexpr_call_hasher::equal (constexpr_call *lhs, 
constexpr_call *rhs)
  return true;
if (lhs->hash != rhs->hash)
  return false;
-  if (lhs->manifestly_const_eval != rhs->manifestly_const_eval)
-return false;
if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
  return false;
return cp_tree_equal (lhs->bindings, rhs->bindings);
@@ -2855,9 +2855,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
  {
location_t loc = cp_expr_loc_or_input_loc (t);
tree fun = get_function_named_in_call (t);
-  constexpr_call new_call
-= { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
-  int depth_ok;
  
if (fun == NULL_TREE)

  return cxx_eval_internal_function (ctx, t, lval,
@@ -3099,7 +3096,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
if (DECL_IMMEDIATE_FUNCTION_P (fun))
  {
new_ctx.manifestly_const_eval = mce_true;
-  new_call.manifestly_const_eval = mce_true;
ctx = &new_ctx;
  }
  
@@ -3112,6 +3108,7 @@ cxx_eval_call_expression (const const

Re: [PATCH] c++: improve constexpr prvalue folding [PR116416]

2025-04-12 Thread Jason Merrill

On 4/11/25 4:36 PM, Patrick Palka wrote:

Boostrapped and regtested on x86_64-pc-linux- gnu, does this look OK
for GCC 15 perhaps?

-- >8 --

This patch improves upon r15-6052-g12de1942a0a673 by performing prvalue
folding with mce_false rather than mce_unknown when it's safe to do so
(i.e. the caller passed ff_mce_false), so that we can also fold temporary
initializers that call is_constant_evaluated etc.

In passing I noticed constexpr-prvalue1.C could more precisely verify
the optimization happened by inspecting what the front end spits out
instead of the final assembly.


I'm not sure that specificity is necessary, but OK.


PR c++/116416

gcc/cp/ChangeLog:

* constexpr.cc (maybe_constant_init_1): Generalize type of
of manifestly_const_eval parameter from bool to mce_value.
(maybe_constant_init): Define 3-parameter version taking a
manifestly_const_eval instead of bool parameter.
(cxx_constant_init): Adjust maybe_constant_init_1.
* cp-gimplify.cc (cp_fold_r) : Pass mce_false
to maybe_constant_init during prvalue folding if ff_mce_false is
set.
* cp-tree.h (maybe_constant_init): Declare new overload.

gcc/testsuite/ChangeLog:

* g++.dg/cpp1y/constexpr-prvalue1.C: Adjust to instead inspect
the 'original' dump.
* g++.dg/cpp1y/constexpr-prvalue1a.C: New test.
---
  gcc/cp/constexpr.cc   | 16 +++---
  gcc/cp/cp-gimplify.cc |  4 ++-
  gcc/cp/cp-tree.h  |  1 +
  .../g++.dg/cpp1y/constexpr-prvalue1.C | 11 ---
  .../g++.dg/cpp1y/constexpr-prvalue1a.C| 32 +++
  5 files changed, 53 insertions(+), 11 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp1y/constexpr-prvalue1a.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 497f64f3ceaa..0242425370f4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -9679,7 +9679,7 @@ fold_non_dependent_init (tree t,
  
  static tree

  maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
-  bool manifestly_const_eval)
+  mce_value manifestly_const_eval)
  {
if (!t)
  return t;
@@ -9709,13 +9709,13 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
if (is_static)
-   manifestly_const_eval = true;
+   manifestly_const_eval = mce_true;
  
-  if (cp_unevaluated_operand && !manifestly_const_eval)

+  if (cp_unevaluated_operand && manifestly_const_eval != mce_true)
return fold_to_constant (t);
  
t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,

-   mce_value (manifestly_const_eval),
+   manifestly_const_eval,
false, decl);
  }
if (TREE_CODE (t) == TARGET_EXPR)
@@ -9731,6 +9731,12 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
  
  tree

  maybe_constant_init (tree t, tree decl, bool manifestly_const_eval)
+{
+  return maybe_constant_init_1 (t, decl, true, mce_value 
(manifestly_const_eval));
+}
+
+tree
+maybe_constant_init (tree t, tree decl, mce_value manifestly_const_eval)
  {
return maybe_constant_init_1 (t, decl, true, manifestly_const_eval);
  }
@@ -9740,7 +9746,7 @@ maybe_constant_init (tree t, tree decl, bool 
manifestly_const_eval)
  tree
  cxx_constant_init (tree t, tree decl)
  {
-  return maybe_constant_init_1 (t, decl, false, true);
+  return maybe_constant_init_1 (t, decl, false, mce_true);
  }
  
  #if 0

diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc
index 550cea29dd29..8dfa5ac2b88d 100644
--- a/gcc/cp/cp-gimplify.cc
+++ b/gcc/cp/cp-gimplify.cc
@@ -1480,7 +1480,9 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
  *walk_subtrees = 0;
  if (!flag_no_inline)
{
- tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt));
+ tree folded = maybe_constant_init (init, TARGET_EXPR_SLOT (stmt),
+(data->flags & ff_mce_false
+ ? mce_false : mce_unknown));
  if (folded != init && TREE_CONSTANT (folded))
init = folded;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 927f51b116b3..55f986e25c14 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8837,6 +8837,7 @@ extern void cxx_constant_dtor (tree, 
tree);
  extern tree cxx_constant_init (tree, tree = NULL_TREE);
  extern tree maybe_constant_value  (tree, tree = NULL_TREE, 
mce_value = mce_unknown);
  extern tree maybe_constant_init   (tree, tree = 
NULL_TREE, bool = false)

[PATCH] Wbuiltin-declaration-mismatch-4.c: accept long long in warning for llp64

2025-04-12 Thread Jonathan Yong

Attached patch OK for master branch?
Will push soon if there are no objections.
From a74ce95293fc310557047fa5da6fb9d55e760f61 Mon Sep 17 00:00:00 2001
From: Jonathan Yong <10wa...@gmail.com>
Date: Sun, 13 Apr 2025 02:41:36 +
Subject: [PATCH] Wbuiltin-declaration-mismatch-4.c: accept long long in
 warning for llp64
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

llp64 targets like mingw-w64 will print:
gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c:80:17: warning: ‘memset’ argument 3 promotes to ‘ptrdiff_t’ {aka ‘long long int’} where ‘long long unsigned int’ is expected in a call to built-in function declared without prototype [-
Wbuiltin-declaration-mismatch]
Change the regex pattern to accept it.

Signed-off-by: Jonathan Yong <10wa...@gmail.com>

gcc/testsuite/ChangeLog:

* gcc.dg/Wbuiltin-declaration-mismatch-4.c: Make diagnostic
	accept long long.
---
 gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c
index c48fe5fcf30..09665b4 100644
--- a/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c
+++ b/gcc/testsuite/gcc.dg/Wbuiltin-declaration-mismatch-4.c
@@ -77,9 +77,9 @@ void test_integer_conversion_memset (void *d)
   /* Passing a ptrdiff_t where size_t is expected may not be unsafe
  but because GCC may emits suboptimal code for such calls warning
  for them helps improve efficiency.  */
-  memset (d, 0, diffi);   /* { dg-warning ".memset. argument 3 promotes to .ptrdiff_t. {aka .\(long \)?\(int\)?\(__int20\)?.} where .\(long \)?\(__int20 \)?unsigned\( int\)?. is expected" } */
+  memset (d, 0, diffi);   /* { dg-warning ".memset. argument 3 promotes to .ptrdiff_t. {aka .\(long \)*\(int\)?\(__int20\)?.} where .\(long \)*\(__int20 \)?unsigned\( int\)?. is expected" } */
 
-  memset (d, 0, 2.0); /* { dg-warning ".memset. argument 3 type is .double. where '\(long \)?\(__int20 \)?unsigned\( int\)?' is expected" } */
+  memset (d, 0, 2.0); /* { dg-warning ".memset. argument 3 type is .double. where '\(long \)*\(__int20 \)?unsigned\( int\)?' is expected" } */
 
   /* Verify that the same call as above but to the built-in doesn't
  trigger a warning.  */
-- 
2.49.0



Re: [PATCH] c++: improve constexpr call caching [PR115639]

2025-04-12 Thread Jason Merrill

On 4/12/25 12:20 PM, Patrick Palka wrote:

On Sat, 12 Apr 2025, Jason Merrill wrote:


On 4/11/25 4:36 PM, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
GCC 15 perhaps?

-- >8 --

Here checking

static_assert(0 == big_calc());

takes twice as much time as

constexpr int ret = big_calc();
static_assert(0 == ret);

ultimately because in the former, we first constexpr evaluate big_calc()
with mce_unknown (as part of warning-dependent folding from
cp_build_binary_op).  We then constant evaluate it a second time, with
mce_true, during finish_static_assert.  The result of the first
evaluation isn't reused because of the different mce_value.

But the call doesn't depend on mce_value at all here (i.e. there's no if
consteval or __builtin_is_constant_evaluated calls, nested or otherwise)
so we should be able to reuse the result in this case.  Specifically if a
constexpr call with mce_unknown gets successfully evaluated, we can safely
reuse the result during a subsequent mce_true or mce_false evaluation.

This patch implements this by caching a successful mce_unknown call
result into the corresponding mce_true and mce_false slots, so that
such a subsequent evaluation effectively reuses the mce_unknown result.
To make it more convenient to access the cache slot for the same call
with different mce_value, this patch gives each constexpr_call entry
three result slots, one per mce_value, instead of having a distinct
constexpr_call entry for each mce_value.  And we can no longer use
NULL_TREE as the "in progress" result, so instead use unknown_type_node.

After this patch compile time for the above two fragments is the same.

PR c++/115639

gcc/cp/ChangeLog:

* constexpr.cc (struct constexpr_call): Add NSDMIs to each
field.  Replace 'result' data member with 3-element 'results'
array and a 'result' accessor function.  Remove
'manifestly_const_eval' data member.
(constexpr_call_hasher::equal): Adjust after constexpr_call
layout change.
(cxx_eval_call_expression): Likewise.  Define some local
variables closer to their first use.  Use unknown_type_node
instead of NULL_TREE as the "in progress" result.  After
successully evaluating a call with mce_unknown, also cache the
result in the corresponding mce_true and mce_false slots.
---
   gcc/cp/constexpr.cc | 59 +++--
   1 file changed, 35 insertions(+), 24 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 0242425370f4..a4fd0d072f65 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1119,20 +1119,22 @@ explain_invalid_constexpr_fn (tree fun)
 struct GTY((for_user)) constexpr_call {
 /* Description of the constexpr function definition.  */
-  constexpr_fundef *fundef;
+  constexpr_fundef *fundef = nullptr;
 /* Parameter bindings environment.  A TREE_VEC of arguments.  */
-  tree bindings;
-  /* Result of the call.
-   NULL means the call is being evaluated.
+  tree bindings = NULL_TREE;
+  /* Result of the call, indexed by the value of
+ constexpr_ctx::manifestly_const_eval.
+   unknown_type_node means the call is being evaluated.
  error_mark_node means that the evaluation was erroneous or
otherwise
  uncacheable (e.g. because it depends on the caller).
  Otherwise, the actual value of the call.  */
-  tree result;
+  tree results[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
 /* The hash of this call; we remember it here to avoid having to
recalculate it when expanding the hash table.  */
-  hashval_t hash;
-  /* The value of constexpr_ctx::manifestly_const_eval.  */
-  enum mce_value manifestly_const_eval;
+  hashval_t hash = 0;
+
+  /* The result slot corresponding to the given mce_value.  */
+  tree& result (mce_value mce) { return results[1 + int(mce)]; }
   };
 struct constexpr_call_hasher : ggc_ptr_hash
@@ -1427,8 +1429,6 @@ constexpr_call_hasher::equal (constexpr_call *lhs,
constexpr_call *rhs)
   return true;
 if (lhs->hash != rhs->hash)
   return false;
-  if (lhs->manifestly_const_eval != rhs->manifestly_const_eval)
-return false;
 if (!constexpr_fundef_hasher::equal (lhs->fundef, rhs->fundef))
   return false;
 return cp_tree_equal (lhs->bindings, rhs->bindings);
@@ -2855,9 +2855,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
tree t,
   {
 location_t loc = cp_expr_loc_or_input_loc (t);
 tree fun = get_function_named_in_call (t);
-  constexpr_call new_call
-= { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
-  int depth_ok;
   if (fun == NULL_TREE)
   return cxx_eval_internal_function (ctx, t, lval,
@@ -3099,7 +3096,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
tree t,
 if (DECL_IMMEDIATE_FUNCTION_P (fun))
   {
 new_ctx.manifestly_const_eval = mce_true;
-  new_call.manifestly_const_eval

[patch, libgfortran] PR119502

2025-04-12 Thread Jerry D
The attached patch fixes this bug by adding checks for negative unit 
numbers in CLOSE and OPEN statements.


Regression tested on x86_64_linux_gnu.

OK for trunk

Author: Jerry DeLisle 
Date:   Sat Apr 12 19:51:23 2025 -0700

Fortran: Fix runtime segfault closing negative unit

When closing a UNIT with an invalid negative unit
number, a segfault ensued. This patch adds checks
for these conditions and issues errors.

PR libfortran/119502

libgfortran/ChangeLog:

* io/close.c (st_close): Issue an error and avoid
calling close_share when there is no stream assigned.
* io/open.c (st_open): If there is no stream assigned
to the unit, unlock the unit and issue an error.

gcc/testsuite/ChangeLog:

* gfortran.dg/pr119502.f90: New test.
diff --git a/gcc/testsuite/gfortran.dg/pr119502.f90 b/gcc/testsuite/gfortran.dg/pr119502.f90
new file mode 100644
index 000..80d7c610165
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr119502.f90
@@ -0,0 +1,15 @@
+! { dg-do run }
+
+! PR119502, negative unit numbers are not allowed without using NEWUNIT
+
+program foo
+  integer :: iun = -1
+  integer :: ios
+  open (iun, iostat=ios)
+  if (ios == 0) stop 1
+  write(iun,*, iostat=ios) "This is a test."
+  if (ios == 0) stop 2
+  close (iun, iostat=ios)
+  if (ios == 0) stop 3
+end
+
diff --git a/libgfortran/io/close.c b/libgfortran/io/close.c
index 81223113dc5..41d278c002c 100644
--- a/libgfortran/io/close.c
+++ b/libgfortran/io/close.c
@@ -84,8 +84,17 @@ st_close (st_parameter_close *clp)
 
   if (u != NULL)
 {
-  if (close_share (u) < 0)
-	generate_error (&clp->common, LIBERROR_OS, "Problem in CLOSE");
+  if (u->s == NULL)
+	{
+	  if (u->unit_number < 0)
+	generate_error (&clp->common, LIBERROR_BAD_UNIT,
+			"Unit number is negative with no associated file");
+	  library_end ();
+	  return;
+	}
+  else
+	if (close_share (u) < 0)
+	  generate_error (&clp->common, LIBERROR_OS, "Problem in CLOSE");
   if (u->flags.status == STATUS_SCRATCH)
 	{
 	  if (status == CLOSE_KEEP)
diff --git a/libgfortran/io/open.c b/libgfortran/io/open.c
index 06ddf7f4dc2..e9fb0a7b3b0 100644
--- a/libgfortran/io/open.c
+++ b/libgfortran/io/open.c
@@ -912,6 +912,16 @@ st_open (st_parameter_open *opp)
 	  library_end ();
 	  return;
 	}
+
+	  if (u->s == NULL)
+	{
+	  unlock_unit (u);
+	  generate_error (&opp->common, LIBERROR_BAD_OPTION,
+			"Unit number is negative and unit was not already "
+			"opened with OPEN(NEWUNIT=...)");
+	  library_end ();
+	  return;
+	}
 	}
 
   if (u == NULL)