[PATCH] c++: Clear is_unbraced_* when parsing declaration_seq_opt [PR114917]

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

Currently we incorrectly retain "in_unbraced_linkage_specification_p"
and "in_unbraced_export_declaration_p" when parsing a (braced)
declaration-seq.  This patch ensures that we clear these flags before
parsing the toplevel declarations.

Strictly speaking we don't need to save and restore the flags around the
parsing because there's currently no way to provide new declarations
within the unbraced context after the closing brace, but this patch does
it anyway in case this ever changes and for consistency with other
places where these flags are adjusted.

PR c++/114917

gcc/cp/ChangeLog:

* parser.cc (cp_parser_declaration_seq_opt): Clear
parser->in_unbraced_* flags when parsing toplevel declarations.

gcc/testsuite/ChangeLog:

* g++.dg/modules/export-5_a.C: New test.
* g++.dg/modules/export-5_b.C: New test.
* g++.dg/parse/linkage4.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/parser.cc  | 15 +++
 gcc/testsuite/g++.dg/modules/export-5_a.C | 17 +
 gcc/testsuite/g++.dg/modules/export-5_b.C | 13 +
 gcc/testsuite/g++.dg/parse/linkage4.C | 11 +++
 4 files changed, 56 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/export-5_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/export-5_b.C
 create mode 100644 gcc/testsuite/g++.dg/parse/linkage4.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a2bc6f69000..9a39ed27b23 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -15341,6 +15341,16 @@ cp_parser_module_export (cp_parser *parser)
 static void
 cp_parser_declaration_seq_opt (cp_parser* parser)
 {
+  bool saved_in_unbraced_linkage_specification_p
+= parser->in_unbraced_linkage_specification_p;
+  bool saved_in_unbraced_export_declaration_p
+= parser->in_unbraced_export_declaration_p;
+
+  /* We're not in an unbraced linkage-specification
+ or export-declaration anymore.  */
+  parser->in_unbraced_linkage_specification_p = false;
+  parser->in_unbraced_export_declaration_p = false;
+
   while (true)
 {
   cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -15351,6 +15361,11 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
   else
cp_parser_toplevel_declaration (parser);
 }
+
+  parser->in_unbraced_linkage_specification_p
+= saved_in_unbraced_linkage_specification_p;
+  parser->in_unbraced_export_declaration_p
+= saved_in_unbraced_export_declaration_p;
 }
 
 /* Parse a declaration.  The distinction between name-declaration
diff --git a/gcc/testsuite/g++.dg/modules/export-5_a.C 
b/gcc/testsuite/g++.dg/modules/export-5_a.C
new file mode 100644
index 000..a325591ca8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-5_a.C
@@ -0,0 +1,17 @@
+// PR c++/114917
+// { dg-additional-options "-fmodules-ts" }
+// { dg-module-cmi M }
+
+export module M;
+
+export namespace ns {
+  template  struct S {};
+  template  struct S { using a = int; };
+  template <> struct S { using b = int; };
+  template struct S;
+};
+
+export extern "C++" namespace ns {
+  template  void foo() {}
+  template <> void foo() {}
+}
diff --git a/gcc/testsuite/g++.dg/modules/export-5_b.C 
b/gcc/testsuite/g++.dg/modules/export-5_b.C
new file mode 100644
index 000..cb10e37c7fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/export-5_b.C
@@ -0,0 +1,13 @@
+// PR c++/114917
+// { dg-additional-options "-fmodules-ts" }
+
+import M;
+
+int main() {
+  ns::S::a x{};
+  ns::S::b y{};
+  ns::S z{};
+
+  ns::foo();
+  ns::foo();
+}
diff --git a/gcc/testsuite/g++.dg/parse/linkage4.C 
b/gcc/testsuite/g++.dg/parse/linkage4.C
new file mode 100644
index 000..10fcc77e9d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/linkage4.C
@@ -0,0 +1,11 @@
+// PR c++/114917
+// { dg-do compile }
+
+extern "C++" namespace ns {
+  struct Incomplete;
+  Incomplete foo;  // { dg-error "incomplete type" }
+}
+
+extern "C" extern "C" {
+  static int bar;  // { dg-bogus "invalid" }
+}
-- 
2.43.2



RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD

2024-05-01 Thread Tamar Christina
> -Original Message-
> From: Li, Pan2 
> Sent: Thursday, May 2, 2024 4:11 AM
> To: Tamar Christina ; gcc-patches@gcc.gnu.org
> Cc: juzhe.zh...@rivai.ai; kito.ch...@gmail.com; richard.guent...@gmail.com;
> Liu, Hongtao 
> Subject: RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD
> 
> Thanks Tamar
> 
> > Could you also split off the vectorizer change from scalar recog one? 
> > Typically I
> would structure a change like this as:
> 
> > 1. create types/structures + scalar recogn
> > 2. Vector recog code
> > 3. Backend changes
> 
> Sure thing, will rearrange the patch like this.
> 
> > Is ECF_NOTHROW correct here? At least on most targets I believe the scalar
> version
> > can set flags/throw exceptions if the saturation happens?
> 
> I see, will remove that.
> 
> > Hmm I believe Richi mentioned that he wanted the recognition done in isel?
> 
> > The problem with doing it in match.pd is that it replaces the operations 
> > quite
> > early the pipeline. Did I miss an email perhaps? The early replacement 
> > means we
> > lose optimizations and things such as range calculations etc, since e.g. 
> > ranger
> > doesn't know these internal functions.
> 
> > I think Richi will want this in islet or mult widening but I'll continue 
> > with match.pd
> > review just in case.
> 
> If I understand is correct, Richard suggested try vectorizer patterns first 
> and then
> possible isel.
> Thus, I don't have a try for SAT_ADD in ISEL as vectorizer patterns works 
> well for
> SAT_ADD.
> Let's wait the confirmation from Richard. Below are the original words from
> previous mail for reference.
> 

I think the comment he made was this

> > Given we have saturating integer alu like below, could you help to coach me 
> > the most reasonable way to represent
> > It in scalar as well as vectorize part? Sorry not familiar with this part 
> > and still dig into how it works...
> 
> As in your v2, .SAT_ADD for both sat_uadd and sat_sadd, similar for
> the other cases.
>
> As I said, use vectorizer patterns and possibly do instruction
> selection at ISEL/widen_mult time.

So he was responding for how to do it for the vectorizer and scalar parts.
Remember that the goal is not to introduce new gimple IL that can block other 
optimizations.
The vectorizer already introduces new IL (various IFN) but this is fine as we 
don't track things like ranges for
vector instructions.  So we don't loose any information here.

Now for the scalar, if we do an early replacement like in match.pd we prevent a 
lot of other optimizations
because they don't know what IFN_SAT_ADD does. gimple-isel runs pretty late, 
and so at this point we don't
expect many more optimizations to happen, so it's a safe spot to insert more IL 
with "unknown semantics".

Was that your intention Richi?

Thanks,
Tamar

> >> As I said, use vectorizer patterns and possibly do instruction
> >> selection at ISEL/widen_mult time.
> 
> > The optimize checks in the match.pd file are weird as it seems to check if 
> > we have
> > optimizations enabled?
> 
> > We don't typically need to do this.
> 
> Sure, will remove this.
> 
> > The function has only one caller, you should just inline it into the 
> > pattern.
> 
> Sure thing.
> 
> > Once you inline vect_sat_add_build_call you can do the check for
> > vtype here, which is the cheaper check so perform it early.
> 
> Sure thing.
> 
> Thanks again and will send the v4 with all comments addressed, as well as the 
> test
> results.
> 
> Pan
> 
> -Original Message-
> From: Tamar Christina 
> Sent: Thursday, May 2, 2024 1:06 AM
> To: Li, Pan2 ; gcc-patches@gcc.gnu.org
> Cc: juzhe.zh...@rivai.ai; kito.ch...@gmail.com; richard.guent...@gmail.com;
> Liu, Hongtao 
> Subject: RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD
> 
> Hi,
> 
> > From: Pan Li 
> >
> > Update in v3:
> > * Rebase upstream for conflict.
> >
> > Update in v2:
> > * Fix one failure for x86 bootstrap.
> >
> > Original log:
> >
> > This patch would like to add the middle-end presentation for the
> > saturation add.  Aka set the result of add to the max when overflow.
> > It will take the pattern similar as below.
> >
> > SAT_ADD (x, y) => (x + y) | (-(TYPE)((TYPE)(x + y) < x))
> >
> > Take uint8_t as example, we will have:
> >
> > * SAT_ADD (1, 254)   => 255.
> > * SAT_ADD (1, 255)   => 255.
> > * SAT_ADD (2, 255)   => 255.
> > * SAT_ADD (255, 255) => 255.
> >
> > The patch also implement the SAT_ADD in the riscv backend as
> > the sample for both the scalar and vector.  Given below example:
> >
> > uint64_t sat_add_u64 (uint64_t x, uint64_t y)
> > {
> >   return (x + y) | (- (uint64_t)((uint64_t)(x + y) < x));
> > }
> >
> > Before this patch:
> > uint64_t sat_add_uint64_t (uint64_t x, uint64_t y)
> > {
> >   long unsigned int _1;
> >   _Bool _2;
> >   long unsigned int _3;
> >   long unsigned int _4;
> >   uint64_t _7;
> >   long unsigned int _10;
> >   __complex__ long unsigned int _11;
> >
> > ;;   basic block 2, loop 

RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD

2024-05-01 Thread Li, Pan2
Thanks Tamar

> Could you also split off the vectorizer change from scalar recog one? 
> Typically I would structure a change like this as:

> 1. create types/structures + scalar recogn
> 2. Vector recog code
> 3. Backend changes

Sure thing, will rearrange the patch like this.

> Is ECF_NOTHROW correct here? At least on most targets I believe the scalar 
> version
> can set flags/throw exceptions if the saturation happens?

I see, will remove that.

> Hmm I believe Richi mentioned that he wanted the recognition done in isel?

> The problem with doing it in match.pd is that it replaces the operations quite
> early the pipeline. Did I miss an email perhaps? The early replacement means 
> we
> lose optimizations and things such as range calculations etc, since e.g. 
> ranger
> doesn't know these internal functions.

> I think Richi will want this in islet or mult widening but I'll continue with 
> match.pd
> review just in case.

If I understand is correct, Richard suggested try vectorizer patterns first and 
then possible isel.
Thus, I don't have a try for SAT_ADD in ISEL as vectorizer patterns works well 
for SAT_ADD.
Let's wait the confirmation from Richard. Below are the original words from 
previous mail for reference.

>> As I said, use vectorizer patterns and possibly do instruction
>> selection at ISEL/widen_mult time.

> The optimize checks in the match.pd file are weird as it seems to check if we 
> have
> optimizations enabled?

> We don't typically need to do this.

Sure, will remove this.

> The function has only one caller, you should just inline it into the pattern.

Sure thing.

> Once you inline vect_sat_add_build_call you can do the check for
> vtype here, which is the cheaper check so perform it early.

Sure thing.

Thanks again and will send the v4 with all comments addressed, as well as the 
test results.

Pan

-Original Message-
From: Tamar Christina  
Sent: Thursday, May 2, 2024 1:06 AM
To: Li, Pan2 ; gcc-patches@gcc.gnu.org
Cc: juzhe.zh...@rivai.ai; kito.ch...@gmail.com; richard.guent...@gmail.com; 
Liu, Hongtao 
Subject: RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD

Hi,

> From: Pan Li 
> 
> Update in v3:
> * Rebase upstream for conflict.
> 
> Update in v2:
> * Fix one failure for x86 bootstrap.
> 
> Original log:
> 
> This patch would like to add the middle-end presentation for the
> saturation add.  Aka set the result of add to the max when overflow.
> It will take the pattern similar as below.
> 
> SAT_ADD (x, y) => (x + y) | (-(TYPE)((TYPE)(x + y) < x))
> 
> Take uint8_t as example, we will have:
> 
> * SAT_ADD (1, 254)   => 255.
> * SAT_ADD (1, 255)   => 255.
> * SAT_ADD (2, 255)   => 255.
> * SAT_ADD (255, 255) => 255.
> 
> The patch also implement the SAT_ADD in the riscv backend as
> the sample for both the scalar and vector.  Given below example:
> 
> uint64_t sat_add_u64 (uint64_t x, uint64_t y)
> {
>   return (x + y) | (- (uint64_t)((uint64_t)(x + y) < x));
> }
> 
> Before this patch:
> uint64_t sat_add_uint64_t (uint64_t x, uint64_t y)
> {
>   long unsigned int _1;
>   _Bool _2;
>   long unsigned int _3;
>   long unsigned int _4;
>   uint64_t _7;
>   long unsigned int _10;
>   __complex__ long unsigned int _11;
> 
> ;;   basic block 2, loop depth 0
> ;;pred:   ENTRY
>   _11 = .ADD_OVERFLOW (x_5(D), y_6(D));
>   _1 = REALPART_EXPR <_11>;
>   _10 = IMAGPART_EXPR <_11>;
>   _2 = _10 != 0;
>   _3 = (long unsigned int) _2;
>   _4 = -_3;
>   _7 = _1 | _4;
>   return _7;
> ;;succ:   EXIT
> 
> }
> 
> After this patch:
> uint64_t sat_add_uint64_t (uint64_t x, uint64_t y)
> {
>   uint64_t _7;
> 
> ;;   basic block 2, loop depth 0
> ;;pred:   ENTRY
>   _7 = .SAT_ADD (x_5(D), y_6(D)); [tail call]
>   return _7;
> ;;succ:   EXIT
> }
> 
> For vectorize, we leverage the existing vect pattern recog to find
> the pattern similar to scalar and let the vectorizer to perform
> the rest part for standard name usadd3 in vector mode.
> The riscv vector backend have insn "Vector Single-Width Saturating
> Add and Subtract" which can be leveraged when expand the usadd3
> in vector mode.  For example:
> 
> void vec_sat_add_u64 (uint64_t *out, uint64_t *x, uint64_t *y, unsigned n)
> {
>   unsigned i;
> 
>   for (i = 0; i < n; i++)
> out[i] = (x[i] + y[i]) | (- (uint64_t)((uint64_t)(x[i] + y[i]) < x[i]));
> }
> 
> Before this patch:
> void vec_sat_add_u64 (uint64_t *out, uint64_t *x, uint64_t *y, unsigned n)
> {
>   ...
>   _80 = .SELECT_VL (ivtmp_78, POLY_INT_CST [2, 2]);
>   ivtmp_58 = _80 * 8;
>   vect__4.7_61 = .MASK_LEN_LOAD (vectp_x.5_59, 64B, { -1, ... }, _80, 0);
>   vect__6.10_65 = .MASK_LEN_LOAD (vectp_y.8_63, 64B, { -1, ... }, _80, 0);
>   vect__7.11_66 = vect__4.7_61 + vect__6.10_65;
>   mask__8.12_67 = vect__4.7_61 > vect__7.11_66;
>   vect__12.15_72 = .VCOND_MASK (mask__8.12_67, { 18446744073709551615,
> ... }, vect__7.11_66);
>   .MASK_LEN_STORE (vectp_out.16_74, 64B, { -1, ... }, _80, 0, vect__12.15_72);
>   

Re: [COMMITTED] Reduce startup costs for Value_Range.

2024-05-01 Thread Andrew Pinski
On Wed, May 1, 2024 at 7:40 PM Ian Lance Taylor  wrote:
>
> On Wed, May 1, 2024 at 12:43 AM Aldy Hernandez  wrote:
> >
> > gcc/ChangeLog:
> >
> > * ipa-fnsummary.cc (evaluate_properties_for_edge): Initialize 
> > Value_Range's.
> > * value-range.h (class Value_Range): Add a buffer and remove
> > m_irange and m_frange.
> > (Value_Range::Value_Range): Call init.
> > (Value_Range::set_type): Same.
> > (Value_Range::init): Use in place new to initialize buffer.
> > (Value_Range::operator=): Tidy.
>
>
> I'm seeing a crash building on sparc-sun-solaris2.11 that may be due
> to this change.  The crash occurs in stage 1, the first time the newly
> built compiler is used.
>
> ./xgcc -B./ -B/var/gcc/iant/install/sparc-sun-solaris2.11/bin/
> -isystem /var/gcc/iant/install/sparc-sun-solaris2.11/include -isystem
> /var/gcc/iant/install/sparc-sun-solaris2.11/sys-include
> -L/var/gcc/iant/bootstrap/gcc/../ld  -xc -nostdinc /dev/null -S -o
> /dev/null -fself-test=../../gcc/gcc/testsuite/selftests
> In function ‘test_fn’:
> cc1: internal compiler error: Bus Error
> 0x1c7db03 crash_signal
> ../../gcc/gcc/toplev.cc:319
> 0x104a82c void wi::copy generic_wide_int >
> >(wide_int_storage&, generic_wide_int false> > const&)
> ../../gcc/gcc/wide-int.h:2191
> 0x1049da3 wide_int_storage&
> wide_int_storage::operator=(wi::hwi_with_prec
> const&)
> ../../gcc/gcc/wide-int.h:1247
> 0x104929b generic_wide_int&
> generic_wide_int::operator=(wi::hwi_with_prec
> const&)
> ../../gcc/gcc/wide-int.h:1002
> 0x104757f irange_bitmask::set_unknown(unsigned int)
> ../../gcc/gcc/value-range.h:163
> 0x1047b6f irange::set_varying(tree_node*)
> ../../gcc/gcc/value-range.h:1067
> 0x1774d1b Value_Range::set_varying(tree_node*)
> ../../gcc/gcc/value-range.h:720
> 0x1aef213 range_cast(vrange&, tree_node*)
> ../../gcc/gcc/range-op.h:248
> 0x1ada517 operator_lshift::op1_range(irange&, tree_node*, irange
> const&, irange const&, relation_trio) const
> ../../gcc/gcc/range-op.cc:2706
> 0x1aeaa6b range_op_lshift_tests
> ../../gcc/gcc/range-op.cc:4750
> 0x1aee20f selftest::range_op_tests()
> ../../gcc/gcc/range-op.cc:4887
> 0x2dfaa37 test_ranges
> ../../gcc/gcc/function-tests.cc:585
> 0x2dfb337 selftest::function_tests_cc_tests()
> ../../gcc/gcc/function-tests.cc:681
> 0x308a027 selftest::run_tests()
> ../../gcc/gcc/selftest-run-tests.cc:108
> 0x1c833ef toplev::run_self_tests()
> ../../gcc/gcc/toplev.cc:2213
> Please submit a full bug report, with preprocessed source (by using
> -freport-bug).
> Please include the complete backtrace with any bug report.
> See  for instructions.
> make: *** [../../gcc/gcc/c/Make-lang.in:153: s-selftest-c] Error 1

This was also reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114912

The same question applies really, what compiler are you using to
compile GCC with? I suspect this is making a difference. It might also
be the sparc compiler that both of you two are using is causing wrong
code with some more complex C++ code even though it is at -O0.
The adding of the deconstructor to Value_Range might be causing the
structure to become a "non-POD" and different argument passing and it
was broken even at -O0 (this is just a guess).

Thanks,
Andrew Pinski

>
> Ian


Re: [committed] [RISC-V] Improve floor, ceil & related operations for RISC-V

2024-05-01 Thread Jeff Law




On 5/1/24 12:44 PM, Patrick O'Neill wrote:


It also introduced:

FAIL: gcc.target/riscv/rvv/autovec/unop/math-nearbyint-run-2.c execution 
test


on rv32gcv newlib/linux.
I think I see what's going on here as well.  Need to ponder this one a 
bit longer, but I'm confident I'll be able to sort it out tomorrow.


jeff


Re: [COMMITTED] Reduce startup costs for Value_Range.

2024-05-01 Thread Ian Lance Taylor
On Wed, May 1, 2024 at 12:43 AM Aldy Hernandez  wrote:
>
> gcc/ChangeLog:
>
> * ipa-fnsummary.cc (evaluate_properties_for_edge): Initialize 
> Value_Range's.
> * value-range.h (class Value_Range): Add a buffer and remove
> m_irange and m_frange.
> (Value_Range::Value_Range): Call init.
> (Value_Range::set_type): Same.
> (Value_Range::init): Use in place new to initialize buffer.
> (Value_Range::operator=): Tidy.


I'm seeing a crash building on sparc-sun-solaris2.11 that may be due
to this change.  The crash occurs in stage 1, the first time the newly
built compiler is used.

./xgcc -B./ -B/var/gcc/iant/install/sparc-sun-solaris2.11/bin/
-isystem /var/gcc/iant/install/sparc-sun-solaris2.11/include -isystem
/var/gcc/iant/install/sparc-sun-solaris2.11/sys-include
-L/var/gcc/iant/bootstrap/gcc/../ld  -xc -nostdinc /dev/null -S -o
/dev/null -fself-test=../../gcc/gcc/testsuite/selftests
In function ‘test_fn’:
cc1: internal compiler error: Bus Error
0x1c7db03 crash_signal
../../gcc/gcc/toplev.cc:319
0x104a82c void wi::copy >
>(wide_int_storage&, generic_wide_int > const&)
../../gcc/gcc/wide-int.h:2191
0x1049da3 wide_int_storage&
wide_int_storage::operator=(wi::hwi_with_prec
const&)
../../gcc/gcc/wide-int.h:1247
0x104929b generic_wide_int&
generic_wide_int::operator=(wi::hwi_with_prec
const&)
../../gcc/gcc/wide-int.h:1002
0x104757f irange_bitmask::set_unknown(unsigned int)
../../gcc/gcc/value-range.h:163
0x1047b6f irange::set_varying(tree_node*)
../../gcc/gcc/value-range.h:1067
0x1774d1b Value_Range::set_varying(tree_node*)
../../gcc/gcc/value-range.h:720
0x1aef213 range_cast(vrange&, tree_node*)
../../gcc/gcc/range-op.h:248
0x1ada517 operator_lshift::op1_range(irange&, tree_node*, irange
const&, irange const&, relation_trio) const
../../gcc/gcc/range-op.cc:2706
0x1aeaa6b range_op_lshift_tests
../../gcc/gcc/range-op.cc:4750
0x1aee20f selftest::range_op_tests()
../../gcc/gcc/range-op.cc:4887
0x2dfaa37 test_ranges
../../gcc/gcc/function-tests.cc:585
0x2dfb337 selftest::function_tests_cc_tests()
../../gcc/gcc/function-tests.cc:681
0x308a027 selftest::run_tests()
../../gcc/gcc/selftest-run-tests.cc:108
0x1c833ef toplev::run_self_tests()
../../gcc/gcc/toplev.cc:2213
Please submit a full bug report, with preprocessed source (by using
-freport-bug).
Please include the complete backtrace with any bug report.
See  for instructions.
make: *** [../../gcc/gcc/c/Make-lang.in:153: s-selftest-c] Error 1

Ian


[PATCH v2] c++/modules: Fix dangling pointer with imported_temploid_friends

2024-05-01 Thread Nathaniel Shead
On Thu, May 02, 2024 at 12:15:44AM +1000, Nathaniel Shead wrote:
> On Wed, May 01, 2024 at 09:57:38AM -0400, Patrick Palka wrote:
> > 
> > On Wed, 1 May 2024, Nathaniel Shead wrote:
> > 
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
> > > later 14.2)?  I don't think making it a GTY root is necessary but I felt
> > > perhaps better to be safe than sorry.
> > > 
> > > Potentially another approach would be to use DECL_UID instead like how
> > > entity_map does; would that be preferable?
> > > 
> > > -- >8 --
> > > 
> > > I got notified by Linaro CI and by checking testresults that there seems
> > > to be some occasional failures in tpl-friend-4_b.C on some architectures
> > > and standards modes since r15-59-gb5f6a56940e708.  I haven't been able
> > > to reproduce but looking at the backtrace I suspect the issue is that
> > > we're adding to the 'imported_temploid_friend' map a decl that is
> > > ultimately discarded, which then has its address reused by a later decl
> > > causing a failure in the assert in 'set_originating_module'.
> > > 
> > > This patch attempts to fix the issue in two ways: by ensuring that we
> > > only store the decl if we know it's a new decl (and hence won't be
> > > discarded), and by making the imported_temploid_friends map a GTY root
> > > so that even if the decl does get discarded later the address isn't
> > > reused.
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > >   * module.cc (imported_temploid_friends): Mark GTY, and...
> > >   (init_modules): ...allocate from GGC.
> > >   (trees_in::decl_value): Only write to imported_temploid_friends
> > >   for new decls.
> > > 
> > > Signed-off-by: Nathaniel Shead 
> > > ---
> > >  gcc/cp/module.cc | 7 ---
> > >  1 file changed, 4 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > > index 5b8ff5bc483..37d38bb9654 100644
> > > --- a/gcc/cp/module.cc
> > > +++ b/gcc/cp/module.cc
> > > @@ -2731,7 +2731,7 @@ static keyed_map_t *keyed_table;
> > > need to be attached to the same module as the temploid.  This maps
> > > these decls to the temploid they are instantiated them, as there is
> > > no other easy way to get this information.  */
> > > -static hash_map *imported_temploid_friends;
> > > +static GTY(()) hash_map *imported_temploid_friends;
> > >  
> > >  //
> > >  /* Tree streaming.   The tree streaming is very specific to the tree
> > > @@ -8327,7 +8327,8 @@ trees_in::decl_value ()
> > >if (TREE_CODE (inner) == FUNCTION_DECL
> > >|| TREE_CODE (inner) == TYPE_DECL)
> > >  if (tree owner = tree_node ())
> > > -  imported_temploid_friends->put (decl, owner);
> > > +  if (is_new)
> > > + imported_temploid_friends->put (decl, owner);
> > 
> > Hmm, I'm not seeing this code path getting reached for tpl-friend-4_b.C.
> > It seems we're instead adding to imported_temploid_friends from
> > propagate_defining_module, during tsubst_friend_function.
> > 
> > What seems to be happening is that we we first tsubst_friend_function
> > 'foo' from TPL, and then we tsubst_friend_function 'foo' from DEF,
> > which ends up calling duplicate_decls, which ggc_frees this 'foo'
> > redeclaration that is still present in the imported_temploid_friends map.
> > 
> > So I don't think marking imported_temploid_friends as a GC root would
> > help with this situation.  If we want to keep imported_temploid_friends
> > as a tree -> tree map, I think we just need to ensure that a decl
> > is removed from the map upon getting ggc_free'd from e.g.  duplicate_decls.
> > 
> > But it seems simpler to use DECL_UID as the key instead, since those
> > never get reused even after the decl gets ggc_free'd IIUC.
> > 
> 
> Ah right, thanks for digging into that further.  Yup OK, I think
> probably the DECL_UID route feels safer to me then in case there are
> other places where a decl might be explicitly freed.
> 
> Looking at tree.cc it looks like the relevant function is
> 'allocate_decl_uid' which shouldn't reuse UIDs until 2^32 decls have
> been created, so we should be safe on the reuse front.
> 
> I'll draft and test a patch for that tomorrow morning.
> 

Here's that patch. Bootstrapped and regtested on x86_64-pc-linux-gnu, OK
for trunk/14.2?

-- >8 --

I got notified by Linaro CI and by checking testresults that there seems
to be some occasional failures in tpl-friend-4_b.C on some architectures
and standards modes since r15-59-gb5f6a56940e708.  I haven't been able
to reproduce but looking at the backtrace I suspect the issue is that
we're adding to the 'imported_temploid_friend' map a decl that is
ultimately discarded, which then has its address reused by a later decl
causing a failure in the assert in 'set_originating_module'.

This patch fixes the problem by using DECL_UID as the map key instead of
the tree directly, much like with entity_map, since even if a
declaration gets deallocated the 

[PATCH] c++/modules: Stream unmergeable temporaries by value again [PR114856]

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk/14.2?

Another alternative would be to stream such !DECL_NAME temporaries with
a merge key of MK_unique rather than attempting to find the matching
(nonexistant) field of the class context.

-- >8 --

In r14-9266-g2823b4d96d9ec4 I gave all temporary vars a DECL_CONTEXT,
including those at namespace or global scope, so that they could be
properly merged across importers.  However, not all of these temporary
vars are actually supposed to be mergeable.

For instance, in the attached testcase we have an unnamed temporary var
used in the NSDMI of a class member, which cannot properly merged -- but
it also doesn't need to be, as it'll be thrown away when the class type
itself is merged anyway.

This patch reverts the change made above and instead makes a weaker
adjustment that only causes temporary vars with linkage have a
DECL_CONTEXT to merge from.  This way these unnamed, "unmergeable"
temporaries are properly streamed by value again.

PR c++/114856

gcc/cp/ChangeLog:

* call.cc (make_temporary_var_for_ref_to_temp): Set context for
temporaries with linkage.
* init.cc (create_temporary_var): Revert to only set context
when in a function decl.

gcc/testsuite/ChangeLog:

* g++.dg/modules/pr114856.h: New test.
* g++.dg/modules/pr114856_a.H: New test.
* g++.dg/modules/pr114856_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/call.cc|  1 +
 gcc/cp/init.cc|  2 +-
 gcc/testsuite/g++.dg/modules/pr114856.h   | 12 
 gcc/testsuite/g++.dg/modules/pr114856_a.H |  5 +
 gcc/testsuite/g++.dg/modules/pr114856_b.C |  5 +
 5 files changed, 24 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/pr114856.h
 create mode 100644 gcc/testsuite/g++.dg/modules/pr114856_a.H
 create mode 100644 gcc/testsuite/g++.dg/modules/pr114856_b.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index dbdd7c29fe8..3b8889ac301 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -13799,6 +13799,7 @@ make_temporary_var_for_ref_to_temp (tree decl, tree 
type)
 
   tree name = mangle_ref_init_variable (decl);
   DECL_NAME (var) = name;
+  DECL_CONTEXT (var) = current_scope ();
   SET_DECL_ASSEMBLER_NAME (var, name);
 }
   else
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index a93ce00800c..e758a8c8568 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -4287,7 +4287,7 @@ create_temporary_var (tree type)
   TREE_USED (decl) = 1;
   DECL_ARTIFICIAL (decl) = 1;
   DECL_IGNORED_P (decl) = 1;
-  DECL_CONTEXT (decl) = current_scope ();
+  DECL_CONTEXT (decl) = current_function_decl;
 
   return decl;
 }
diff --git a/gcc/testsuite/g++.dg/modules/pr114856.h 
b/gcc/testsuite/g++.dg/modules/pr114856.h
new file mode 100644
index 000..b1a3c2cd834
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr114856.h
@@ -0,0 +1,12 @@
+// PR c++/114856
+
+#include 
+struct A {
+  ~A();
+};
+struct V {
+  V(std::initializer_list);
+};
+struct data {
+  V v{{}};
+};
diff --git a/gcc/testsuite/g++.dg/modules/pr114856_a.H 
b/gcc/testsuite/g++.dg/modules/pr114856_a.H
new file mode 100644
index 000..6195277dbde
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr114856_a.H
@@ -0,0 +1,5 @@
+// PR c++/114856
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+#include "pr114856.h"
diff --git a/gcc/testsuite/g++.dg/modules/pr114856_b.C 
b/gcc/testsuite/g++.dg/modules/pr114856_b.C
new file mode 100644
index 000..f81dc8b81d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr114856_b.C
@@ -0,0 +1,5 @@
+// PR c++/114856
+// { dg-additional-options "-fmodules-ts" }
+
+#include "pr114856.h"
+import "pr114856_a.H";
-- 
2.43.2



[pushed] doc: Describe limitations re Ada, D, and Go on FreeBSD

2024-05-01 Thread Gerald Pfeifer
This should address the majority of issues left from Rainer's report 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112959 .  I pushed this 
for now.

Rainer, thank you very much for your report and all the details. I am 
sorry our documentation was not up-to-date.

It would be great could you have a look at what is in install.texi now and 
advise whether that covers things properly. And any suggestions on how to 
improve.

Gerald


gcc:
PR target/69374
PR target/112959
* doc/install.texi (Specific) <*-*-freebsd*>: The Ada and D
run-time libraries are broken on i386 which also can affect
64-bit builds. Go is broken.
---
 gcc/doc/install.texi | 8 
 1 file changed, 8 insertions(+)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index b1d28dcb03b..9f2e427be68 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -4099,6 +4099,14 @@ version found in the @file{devel/binutils} port. This 
also has been
 known to enable additional features and improve overall testsuite
 results.
 
+@c Bugs 112958 and 112957
+Ada and D (or rather their respective libraries) are broken on
+FreeBSD/i386. This also affects building 32-bit libraries on
+FreeBSD/amd64, so configure with @option{--disable-multilib}
+there in case you are building one of these front ends.
+
+Go (or rather libgo) is generally broken on FreeBSD.
+
 @html
 
 @end html
-- 
2.44.0


[PATCH] Fix auto deduction for template specialization scopes [114915].

2024-05-01 Thread Seyed Sajad Kahani
When deducing auto for `adc_return_type`, `adc_variable_type`, and 
`adc_decomp_type` contexts (at the usage time), we try to resolve the outermost 
template arguments to be used for satisfaction. This is done by one of the 
following, depending on the scope:

1. Checking the `DECL_TEMPLATE_INFO` of the current function scope and 
extracting DECL_TI_ARGS from it for function scope deductions (pt.cc:31236).
2. Checking the `DECL_TEMPLATE_INFO` of the declaration (alongside with other 
conditions) for non-function scope variable declaration deductions 
(decl.cc:8527).

Then, we do not retrieve the deeper layers of the template arguments; instead, 
we fill the missing levels with dummy levels (pt.cc:31260).

The problem (that is shown in PR114915) is that we do not consider the case 
where the deduction happens in a template specialization scope. In this case, 
the type is not dependent on the outermost template arguments (which are the 
specialization arguments). Yet, we still resolve the outermost template 
arguments, and then the number of layers in the template arguments exceeds the 
number of levels in the type. This causes the missing levels to be negative. 
This leads to the rejection of valid code and ICEs (like segfault) in the 
release mode. In the debug mode, it is possible to show as an assertion failure 
(when creating a tree_vec with a negative size).
The code that generates the issue is added to the test suite as 
`g++.dg/cpp2a/concepts-placeholder14.C`.

This patch fixes the issue by checking that the template usage, whose arguments 
are going to be used for satisfaction, is not a partial or explicit 
specialization (and therefore it is an implicit or explicit instantiation). 
This check is done in the two only places that affect the `outer_targs` for the 
mentioned contexts.

One might ask why this is not implemented as a simple `missing_level > 0` 
check. The reason is that the recovery from the negative `missing_levels` will 
not be easy, and it is not clear how to recover from it. Therefore, it is 
better to prevent it from happening.
---
 gcc/cp/decl.cc|  1 +
 gcc/cp/pt.cc  | 16 ++-
 .../g++.dg/cpp2a/concepts-placeholder14.C | 20 +++
 3 files changed, 32 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder14.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 65ab64885..7e51f926e 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -8527,6 +8527,7 @@ cp_finish_decl (tree decl, tree init, bool 
init_const_expr_p,
   if (PLACEHOLDER_TYPE_CONSTRAINTS_INFO (auto_node)
  && DECL_LANG_SPECIFIC (decl)
  && DECL_TEMPLATE_INFO (decl)
+ && DECL_USE_TEMPLATE (decl) != 2
  && !DECL_FUNCTION_SCOPE_P (decl))
/* The outer template arguments might be needed for satisfaction.
   (For function scope variables, do_auto_deduction will obtain the
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 3b2106dd3..fd646d873 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -31044,7 +31044,8 @@ unparenthesized_id_or_class_member_access_p (tree init)
OUTER_TARGS is used during template argument deduction (context == 
adc_unify)
to properly substitute the result.  It's also used in the adc_unify and
adc_requirement contexts to communicate the necessary template arguments
-   to satisfaction.  OUTER_TARGS is ignored in other contexts.
+   to satisfaction.  OUTER_TARGS will be used for other contexts if it is a
+   function scope deduction. Otherwise it is ignored.
 
Additionally for adc_unify contexts TMPL is the template for which TYPE
is a template parameter type.
@@ -31235,8 +31236,11 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
if (tree fn = current_function_decl)
  if (DECL_TEMPLATE_INFO (fn) || LAMBDA_FUNCTION_P (fn))
{
- outer_targs = DECL_TEMPLATE_INFO (fn)
-   ? DECL_TI_ARGS (fn) : NULL_TREE;
+ outer_targs = NULL_TREE; 
+ if (DECL_TEMPLATE_INFO (fn) && DECL_USE_TEMPLATE (fn) != 2)
+ {
+ outer_targs = DECL_TI_ARGS (fn);
+ }
  if (LAMBDA_FUNCTION_P (fn))
{
  /* As in satisfy_declaration_constraints.  */
@@ -31260,8 +31264,10 @@ do_auto_deduction (tree type, tree init, tree 
auto_node,
 these missing levels, but this hack otherwise allows us to handle a
 large subset of possible constraints (including all non-dependent
 constraints).  */
-  if (int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node)
-   - TMPL_ARGS_DEPTH (full_targs)))
+  int missing_levels = (TEMPLATE_TYPE_ORIG_LEVEL (auto_node)
+   - TMPL_ARGS_DEPTH (full_targs));
+
+  if (missing_levels > 0)
{
  tree dummy_levels = make_tree_vec (missing_levels);

Re: [PATCH] c++: problematic assert in reference_binding [PR113141]

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Patrick Palka wrote:

> On Wed, 1 May 2024, Jason Merrill wrote:
> 
> > On 4/12/24 13:22, Patrick Palka wrote:
> > > On Fri, 12 Apr 2024, Jason Merrill wrote:
> > > 
> > > > On 3/26/24 09:44, Patrick Palka wrote:
> > > > > On Thu, 7 Mar 2024, Jason Merrill wrote:
> > > > > 
> > > > > > On 1/29/24 17:42, Patrick Palka wrote:
> > > > > > > On Mon, 29 Jan 2024, Patrick Palka wrote:
> > > > > > > 
> > > > > > > > On Fri, 26 Jan 2024, Jason Merrill wrote:
> > > > > > > > 
> > > > > > > > > On 1/26/24 17:11, Jason Merrill wrote:
> > > > > > > > > > On 1/26/24 16:52, Jason Merrill wrote:
> > > > > > > > > > > On 1/25/24 14:18, Patrick Palka wrote:
> > > > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does
> > > > > > > > > > > > this
> > > > > > > > > > > > look
> > > > > > > > > > > > OK for trunk/13?  This isn't a very satisfactory fix, 
> > > > > > > > > > > > but
> > > > > > > > > > > > at
> > > > > > > > > > > > least
> > > > > > > > > > > > it safely fixes these testcases I guess.  Note that
> > > > > > > > > > > > there's
> > > > > > > > > > > > implementation disagreement about the second testcase, 
> > > > > > > > > > > > GCC
> > > > > > > > > > > > always
> > > > > > > > > > > > accepted it but Clang/MSVC/icc reject it.
> > > > > > > > > > > 
> > > > > > > > > > > Because of trying to initialize int& from {c}; removing 
> > > > > > > > > > > the
> > > > > > > > > > > extra
> > > > > > > > > > > braces
> > > > > > > > > > > makes it work everywhore.
> > > > > > > > > > > 
> > > > > > > > > > > https://eel.is/c++draft/dcl.init#list-3.10 says that we
> > > > > > > > > > > always
> > > > > > > > > > > generate a
> > > > > > > > > > > prvalue in this case, so perhaps we shouldn't recalculate 
> > > > > > > > > > > if
> > > > > > > > > > > the
> > > > > > > > > > > initializer is an init-list?
> > > > > > > > > > 
> > > > > > > > > > ...but it seems bad to silently bind a const int& to a 
> > > > > > > > > > prvalue
> > > > > > > > > > instead
> > > > > > > > > > of
> > > > > > > > > > directly to the reference returned by the operator, as clang
> > > > > > > > > > does
> > > > > > > > > > if
> > > > > > > > > > we add
> > > > > > > > > > const to the second testcase, so I think there's a defect in
> > > > > > > > > > the
> > > > > > > > > > standard
> > > > > > > > > > here.
> > > > > > > > > 
> > > > > > > > > Perhaps bullet 3.9 should change to "...its referenced type is
> > > > > > > > > reference-related to E or scalar, ..."
> > > > > > > > > 
> > > > > > > > > > Maybe for now also disable the maybe_valid heuristics in the
> > > > > > > > > > case
> > > > > > > > > > of
> > > > > > > > > > an
> > > > > > > > > > init-list?
> > > > > > > > > > 
> > > > > > > > > > > The first testcase is special because it's a C-style cast;
> > > > > > > > > > > seems
> > > > > > > > > > > like the
> > > > > > > > > > > maybe_valid = false heuristics should be disabled if
> > > > > > > > > > > c_cast_p.
> > > > > > > > 
> > > > > > > > Thanks a lot for the pointers.  IIUC c_cast_p and
> > > > > > > > LOOKUP_SHORTCUT_BAD_CONVS
> > > > > > > > should already be mutually exclusive, since the latter is set 
> > > > > > > > only
> > > > > > > > when
> > > > > > > > computing argument conversions, so it shouldn't be necessary to
> > > > > > > > check
> > > > > > > > c_cast_p.
> > > > > > > > 
> > > > > > > > I suppose we could disable the heuristic for init-lists, but 
> > > > > > > > after
> > > > > > > > some
> > > > > > > > digging I noticed that the heuristics were originally in same 
> > > > > > > > spot
> > > > > > > > they
> > > > > > > > are now until r5-601-gd02f620dc0bb3b moved them to get checked
> > > > > > > > after
> > > > > > > > the recursive recalculation case in reference_binding, 
> > > > > > > > returning a
> > > > > > > > bad
> > > > > > > > conversion instead of NULL.  (Then in 
> > > > > > > > r13-1755-g68f37670eff0b872 I
> > > > > > > > moved
> > > > > > > > them back; IIRC that's why I felt confident that moving the 
> > > > > > > > checks
> > > > > > > > was
> > > > > > > > safe.)
> > > > > > > > Thus we didn't always accept the second testcase, we only 
> > > > > > > > started
> > > > > > > > doing so
> > > > > > > > in
> > > > > > > > GCC 5: https://godbolt.org/z/6nsEW14fh (sorry for missing this 
> > > > > > > > and
> > > > > > > > saying
> > > > > > > > we
> > > > > > > > always accepted it)
> > > > > > > > 
> > > > > > > > And indeed the current order of checks seems consistent with 
> > > > > > > > that
> > > > > > > > of
> > > > > > > > [dcl.init.ref]/5.  So I wonder if we don't instead want to
> > > > > > > > "complete"
> > > > > > > > the NULL-to-bad-conversion adjustment in r5-601-gd02f620dc0bb3b
> > > > > > > > and
> > > > > > > > do:
> > > > > > > > 
> > > > > > > > gcc/cp/ChangeLog:
> > > > > > > > 
> > > > > > > > * call.cc (reference_binding): Set bad_p according to
> > > > > > > > maybe_valid_p in the recursive case as well.  

Re: [committed] [RISC-V] Improve floor, ceil & related operations for RISC-V

2024-05-01 Thread Jeff Law




On 5/1/24 12:44 PM, Patrick O'Neill wrote:

Hi Jeff,


It looks like this patch's gcc.target/riscv/round_64.c testcase doesn't 
pass when run with newlib.
So I expected this would ultimately end up being a case where certain 
builtins aren't enabled when we're using a newlib based C library and 
that's exactly what happens here.


Essentially all the "function_c99_misc" routines are disabled for 
simplifications.  So we're presented with this in forwprop:



__attribute__((noclone, noinline))
float convert_float_to_float_round (float N)
{
  double _1;
  double _2;
  float _4;

;;   basic block 2, loop depth 0, maybe hot
;;prev block 0, next block 1, flags: (NEW, VISITED)
;;pred:   ENTRY (FALLTHRU,EXECUTABLE)
  _1 = (double) N_3(D);
  _2 = round (_1);
  _4 = (float) _2;
  return _4;
;;succ:   EXIT j.c:12:10

}


The test relies on the optimizer to realize that's just roundf and 
convert it to:


__attribute__((noclone, noinline))
float convert_float_to_float_round (float N)
{
  float _6;

;;   basic block 2, loop depth 0, maybe hot
;;prev block 0, next block 1, flags: (NEW, VISITED)
;;pred:   ENTRY (FALLTHRU,EXECUTABLE)
  _6 = __builtin_roundf (N_3(D));
  return _6;
;;succ:   EXIT (EXECUTABLE) z.c:12:10

}


Failure to do that conversion will result in different code generation 
in the end and thus all those scan-asm failures.  Thankfully we have a 
preexisting way to deal with this in the testsuite.






It also introduced:

FAIL: gcc.target/riscv/rvv/autovec/unop/math-nearbyint-run-2.c execution 
test


on rv32gcv newlib/linux.
I'll have to look at this next, but it could well end up being the same 
issue under the hood.


jeff


Re: [PATCH 2/2] c++: remove lookup_template_class's entering_scope flag

2024-05-01 Thread Jason Merrill

On 5/1/24 13:40, Patrick Palka wrote:

On Wed, 1 May 2024, Jason Merrill wrote:


On 5/1/24 12:41, Patrick Palka wrote:

On Fri, 2 Feb 2024, Patrick Palka wrote:


Bootstrapped and regtested on x86_64-pc-linux, does this look like
an improvement?  This is not a bugfix and barely related to the previous
patch, but the previous patch's new use of entering_scope=true motivated
me to submit this patch since it seems like a nice simplification.


Ping, now that stage 1 is open.


Thanks for the ping.  The earlier message isn't showing up in Thunderbird for
some reason, though I see it in the gmail web interface...


Ah, weird.  No worries, this patch was very much stage 1 material anyway.




@@ -16771,9 +16722,10 @@ tsubst (tree t, tree args, tsubst_flags_t
complain, tree in_decl)
ctx = TREE_VEC_ELT (ctx, 0);
  }
else
- ctx = tsubst_aggr_type (ctx, args,
- complain | tf_qualifying_scope,
- in_decl, /*entering_scope=*/1);
+ {
+   ctx = tsubst_scope (ctx, args, complain, in_decl);


Why is this one tsubst_scope while the others are all plain tsubst?


Ah, just because the call to tsubst_aggr_type being replace passes
tf_qualifying_scope already, so we might as well use tsubst_scope
as shorthand.


Do we want a tsubst_entering_scope function?


Which is just shorthand for tsubst + adjust_type_for_entering_scope?


That's what I was thinking.


Sure, though I was wondering if we eventually might want to get rid of
the distinction between the primary template type A and the generic
instantiation A, and we could treat this as an incremental step
towards that (then we'd just eventually remove the
adjust_type_for_entering_scope calls and keep the tsubst calls).


I don't think we want that; having the distinction helps to avoid 
wrongly looking up members of the primary template in contexts that 
shouldn't be able to.


Jason



Re: [PATCH] c++: problematic assert in reference_binding [PR113141]

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Jason Merrill wrote:

> On 4/12/24 13:22, Patrick Palka wrote:
> > On Fri, 12 Apr 2024, Jason Merrill wrote:
> > 
> > > On 3/26/24 09:44, Patrick Palka wrote:
> > > > On Thu, 7 Mar 2024, Jason Merrill wrote:
> > > > 
> > > > > On 1/29/24 17:42, Patrick Palka wrote:
> > > > > > On Mon, 29 Jan 2024, Patrick Palka wrote:
> > > > > > 
> > > > > > > On Fri, 26 Jan 2024, Jason Merrill wrote:
> > > > > > > 
> > > > > > > > On 1/26/24 17:11, Jason Merrill wrote:
> > > > > > > > > On 1/26/24 16:52, Jason Merrill wrote:
> > > > > > > > > > On 1/25/24 14:18, Patrick Palka wrote:
> > > > > > > > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does
> > > > > > > > > > > this
> > > > > > > > > > > look
> > > > > > > > > > > OK for trunk/13?  This isn't a very satisfactory fix, but
> > > > > > > > > > > at
> > > > > > > > > > > least
> > > > > > > > > > > it safely fixes these testcases I guess.  Note that
> > > > > > > > > > > there's
> > > > > > > > > > > implementation disagreement about the second testcase, GCC
> > > > > > > > > > > always
> > > > > > > > > > > accepted it but Clang/MSVC/icc reject it.
> > > > > > > > > > 
> > > > > > > > > > Because of trying to initialize int& from {c}; removing the
> > > > > > > > > > extra
> > > > > > > > > > braces
> > > > > > > > > > makes it work everywhore.
> > > > > > > > > > 
> > > > > > > > > > https://eel.is/c++draft/dcl.init#list-3.10 says that we
> > > > > > > > > > always
> > > > > > > > > > generate a
> > > > > > > > > > prvalue in this case, so perhaps we shouldn't recalculate if
> > > > > > > > > > the
> > > > > > > > > > initializer is an init-list?
> > > > > > > > > 
> > > > > > > > > ...but it seems bad to silently bind a const int& to a prvalue
> > > > > > > > > instead
> > > > > > > > > of
> > > > > > > > > directly to the reference returned by the operator, as clang
> > > > > > > > > does
> > > > > > > > > if
> > > > > > > > > we add
> > > > > > > > > const to the second testcase, so I think there's a defect in
> > > > > > > > > the
> > > > > > > > > standard
> > > > > > > > > here.
> > > > > > > > 
> > > > > > > > Perhaps bullet 3.9 should change to "...its referenced type is
> > > > > > > > reference-related to E or scalar, ..."
> > > > > > > > 
> > > > > > > > > Maybe for now also disable the maybe_valid heuristics in the
> > > > > > > > > case
> > > > > > > > > of
> > > > > > > > > an
> > > > > > > > > init-list?
> > > > > > > > > 
> > > > > > > > > > The first testcase is special because it's a C-style cast;
> > > > > > > > > > seems
> > > > > > > > > > like the
> > > > > > > > > > maybe_valid = false heuristics should be disabled if
> > > > > > > > > > c_cast_p.
> > > > > > > 
> > > > > > > Thanks a lot for the pointers.  IIUC c_cast_p and
> > > > > > > LOOKUP_SHORTCUT_BAD_CONVS
> > > > > > > should already be mutually exclusive, since the latter is set only
> > > > > > > when
> > > > > > > computing argument conversions, so it shouldn't be necessary to
> > > > > > > check
> > > > > > > c_cast_p.
> > > > > > > 
> > > > > > > I suppose we could disable the heuristic for init-lists, but after
> > > > > > > some
> > > > > > > digging I noticed that the heuristics were originally in same spot
> > > > > > > they
> > > > > > > are now until r5-601-gd02f620dc0bb3b moved them to get checked
> > > > > > > after
> > > > > > > the recursive recalculation case in reference_binding, returning a
> > > > > > > bad
> > > > > > > conversion instead of NULL.  (Then in r13-1755-g68f37670eff0b872 I
> > > > > > > moved
> > > > > > > them back; IIRC that's why I felt confident that moving the checks
> > > > > > > was
> > > > > > > safe.)
> > > > > > > Thus we didn't always accept the second testcase, we only started
> > > > > > > doing so
> > > > > > > in
> > > > > > > GCC 5: https://godbolt.org/z/6nsEW14fh (sorry for missing this and
> > > > > > > saying
> > > > > > > we
> > > > > > > always accepted it)
> > > > > > > 
> > > > > > > And indeed the current order of checks seems consistent with that
> > > > > > > of
> > > > > > > [dcl.init.ref]/5.  So I wonder if we don't instead want to
> > > > > > > "complete"
> > > > > > > the NULL-to-bad-conversion adjustment in r5-601-gd02f620dc0bb3b
> > > > > > > and
> > > > > > > do:
> > > > > > > 
> > > > > > > gcc/cp/ChangeLog:
> > > > > > > 
> > > > > > >   * call.cc (reference_binding): Set bad_p according to
> > > > > > >   maybe_valid_p in the recursive case as well.  Remove
> > > > > > >   redundant gcc_assert.
> > > > > > > 
> > > > > > > diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
> > > > > > > index 9de0d77c423..c4158b2af37 100644
> > > > > > > --- a/gcc/cp/call.cc
> > > > > > > +++ b/gcc/cp/call.cc
> > > > > > > @@ -2033,8 +2033,8 @@ reference_binding (tree rto, tree rfrom,
> > > > > > > tree
> > > > > > > expr,
> > > > > > > bool c_cast_p, int flags,
> > > > > > >  sflags, complain);
> > > > > > >   if (!new_second)
> > > > > > > 

Re: [PATCH 2/2] c++: remove lookup_template_class's entering_scope flag

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Jason Merrill wrote:

> On 5/1/24 12:41, Patrick Palka wrote:
> > On Fri, 2 Feb 2024, Patrick Palka wrote:
> > 
> > > Bootstrapped and regtested on x86_64-pc-linux, does this look like
> > > an improvement?  This is not a bugfix and barely related to the previous
> > > patch, but the previous patch's new use of entering_scope=true motivated
> > > me to submit this patch since it seems like a nice simplification.
> > 
> > Ping, now that stage 1 is open.
> 
> Thanks for the ping.  The earlier message isn't showing up in Thunderbird for
> some reason, though I see it in the gmail web interface...

Ah, weird.  No worries, this patch was very much stage 1 material anyway.

> 
> > > @@ -16771,9 +16722,10 @@ tsubst (tree t, tree args, tsubst_flags_t
> > > complain, tree in_decl)
> > >   ctx = TREE_VEC_ELT (ctx, 0);
> > > }
> > >   else
> > > -   ctx = tsubst_aggr_type (ctx, args,
> > > -   complain | tf_qualifying_scope,
> > > -   in_decl, /*entering_scope=*/1);
> > > +   {
> > > + ctx = tsubst_scope (ctx, args, complain, in_decl);
> 
> Why is this one tsubst_scope while the others are all plain tsubst?

Ah, just because the call to tsubst_aggr_type being replace passes
tf_qualifying_scope already, so we might as well use tsubst_scope
as shorthand.

> 
> Do we want a tsubst_entering_scope function?

Which is just shorthand for tsubst + adjust_type_for_entering_scope?
Sure, though I was wondering if we eventually might want to get rid of
the distinction between the primary template type A and the generic
instantiation A, and we could treat this as an incremental step
towards that (then we'd just eventually remove the
adjust_type_for_entering_scope calls and keep the tsubst calls).

> 
> > > + ctx = adjust_type_for_entering_scope (ctx);
> 
> 



Re: [PATCH] c++: problematic assert in reference_binding [PR113141]

2024-05-01 Thread Jason Merrill

On 4/12/24 13:22, Patrick Palka wrote:

On Fri, 12 Apr 2024, Jason Merrill wrote:


On 3/26/24 09:44, Patrick Palka wrote:

On Thu, 7 Mar 2024, Jason Merrill wrote:


On 1/29/24 17:42, Patrick Palka wrote:

On Mon, 29 Jan 2024, Patrick Palka wrote:


On Fri, 26 Jan 2024, Jason Merrill wrote:


On 1/26/24 17:11, Jason Merrill wrote:

On 1/26/24 16:52, Jason Merrill wrote:

On 1/25/24 14:18, Patrick Palka wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this
look
OK for trunk/13?  This isn't a very satisfactory fix, but at
least
it safely fixes these testcases I guess.  Note that there's
implementation disagreement about the second testcase, GCC
always
accepted it but Clang/MSVC/icc reject it.


Because of trying to initialize int& from {c}; removing the
extra
braces
makes it work everywhore.

https://eel.is/c++draft/dcl.init#list-3.10 says that we always
generate a
prvalue in this case, so perhaps we shouldn't recalculate if the
initializer is an init-list?


...but it seems bad to silently bind a const int& to a prvalue
instead
of
directly to the reference returned by the operator, as clang does
if
we add
const to the second testcase, so I think there's a defect in the
standard
here.


Perhaps bullet 3.9 should change to "...its referenced type is
reference-related to E or scalar, ..."


Maybe for now also disable the maybe_valid heuristics in the case
of
an
init-list?


The first testcase is special because it's a C-style cast; seems
like the
maybe_valid = false heuristics should be disabled if c_cast_p.


Thanks a lot for the pointers.  IIUC c_cast_p and
LOOKUP_SHORTCUT_BAD_CONVS
should already be mutually exclusive, since the latter is set only
when
computing argument conversions, so it shouldn't be necessary to check
c_cast_p.

I suppose we could disable the heuristic for init-lists, but after
some
digging I noticed that the heuristics were originally in same spot
they
are now until r5-601-gd02f620dc0bb3b moved them to get checked after
the recursive recalculation case in reference_binding, returning a bad
conversion instead of NULL.  (Then in r13-1755-g68f37670eff0b872 I
moved
them back; IIRC that's why I felt confident that moving the checks was
safe.)
Thus we didn't always accept the second testcase, we only started
doing so
in
GCC 5: https://godbolt.org/z/6nsEW14fh (sorry for missing this and
saying
we
always accepted it)

And indeed the current order of checks seems consistent with that of
[dcl.init.ref]/5.  So I wonder if we don't instead want to "complete"
the NULL-to-bad-conversion adjustment in r5-601-gd02f620dc0bb3b and
do:

gcc/cp/ChangeLog:

* call.cc (reference_binding): Set bad_p according to
maybe_valid_p in the recursive case as well.  Remove
redundant gcc_assert.

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 9de0d77c423..c4158b2af37 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -2033,8 +2033,8 @@ reference_binding (tree rto, tree rfrom, tree
expr,
bool c_cast_p, int flags,
   sflags, complain);
if (!new_second)
  return bad_direct_conv ? bad_direct_conv : nullptr;
+   t->bad_p = !maybe_valid_p;


Oops, that should be |= not =.


Perhaps bullet 3.9 should change to "...its referenced type is
reference-related to E or scalar, ..."

conv = merge_conversion_sequences (t, new_second);
-   gcc_assert (maybe_valid_p || conv->bad_p);
return conv;
  }
}

This'd mean we'd go back to rejecting the second testcase (only the
call, not the direct-init, interestingly enough), but that seems to be


In the second testcase, with the above fix initialize_reference silently
returns error_mark_node for the direct-init without issuing a
diagnostic, because in the error path convert_like doesn't find anything
wrong with the bad conversion.  So more changes need to be made if we
want to set bad_p in the recursive case of reference_binding it seems;
dunno if that's the path we want to go down?

On the other hand, disabling the badness checks in certain cases seems
to be undesirable as well, since AFAICT their current position is
consistent with [dcl.init.ref]/5?

So I wonder if we should just go with the safest thing at this stage,
which would be the original patch that removes the problematic assert?


I still think the assert is correct, and the problem is that maybe_valid_p
is
wrong; these cases turn out to be valid, so maybe_valid_p should be true.


I'm afraid then I don't know how we can statically identify these cases
without actually performing the conversion, in light of the recursion :/
Do you mind taking this PR?  I don't feel well-versed enough with the
reference binding rules to tackle this adequately..


That ended up being a surprisingly deep dive, but I've now checked in separate
fixes for the two cases.


Very interesting, thanks a lot.


...but I don't think my fixes are suitable for GCC 13, so would you 
apply your original 

Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Jason Merrill

On 5/1/24 12:11, Patrick Palka wrote:

On Wed, 1 May 2024, Jason Merrill wrote:


On 5/1/24 08:54, Patrick Palka wrote:

On Thu, 2 May 2024, Nathaniel Shead wrote:


On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:

On Wed, 1 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When calling instantiate_pending_templates at end of parsing, any new
functions that are instantiated from this point have their module
purview set based on the current value of module_kind.

This is unideal, however, as the modules code will then treat these
instantiations as reachable and cause large swathes of the GMF to be
emitted into the module CMI, despite no code in the actual module
purview referencing it.

This patch fixes this by also remembering the value of module_kind
when
the instantiation was deferred, and restoring it when doing this
deferred instantiation.  That way newly instantiated declarations
appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
instantiation was required, meaning that GMF entities won't be counted
as reachable unless referenced by an actually reachable entity.

Note that purviewness and attachment etc. is generally only determined
by the base template: this is purely for determining whether a
specialisation was declared in the module purview and hence whether it
should be streamed out.  See the comment on
'set_instantiating_module'.

PR c++/114630
PR c++/114795

gcc/cp/ChangeLog:

* cp-tree.h (struct tinst_level): Add field for tracking
module_kind.
* pt.cc (push_tinst_level_loc): Cache module_kind in
new_level.
(reopen_tinst_level): Restore module_kind from level.
(instantiate_pending_templates): Save and restore module_kind
so
it isn't affected by reopen_tinst_level.


LGTM.  Another approach is to instantiate all so-far deferred
instantiations and vtables once we reach the start of the module
purview, but your approach is much cleaner.

Note that deferred instantiation can induce more deferred instantiation,
but your approach will do the right thing here (module_kind will be
inherited from the point of instantiation).

What if an instantiation is needed from both the GMF and the module
purview?  Then IIUC it'll be instantiated as if from the GMF, which
seems right to me.



Hm..., so I believe it'll be marked according to whichever instantiates
it "first", so if e.g. deferred from GMF and then instantiated
non-deferred from purview it'll be marked purview (and the deferred
instantiation will be skipped as it's already instantiated).  This could
mean it gets unnecessarily emitted if it only got instantiated because
it got used in e.g. a non-inline function body, I suppose; but that's
true in general actually, at the moment.


FWIW I think the most relevant situation where we need to instantiate
immediately and can't defer until EOF is during constexpr evaluation of
a variable initializer.  (We also immediately instantiate variable
template specializations, and function template specializations with
deduced return type, but in these cases we'd always instantiate from the
first use, i.e. from the GMF in this scenario.)

So I guess a testcase for this situation could be something like:

  module;
  template constexpr int f(T t) { return t; }
  template int f(int);

  export module foo;
  constexpr int w = f(0);
  // f ideally shouldn't be emitted in the CMI?


Does the explicit instantiation change that at all?  Either way it seams like
f and f aren't decl-reachable from w if we determine that after constant
evaluation.


Currently due to the bug in question we handle this as if the explicit
instantiation was performed from the module purview:

   module;
   template constexpr int f(T t) { return t; }

   export module foo;
   template int f(int);
   constexpr int w = f(0);

I think we do want to emit f in that case?


Agreed, because f is decl-reachable from the explicit instantiation in 
the module purview.


I was suggesting that there's no effective difference between explicit 
instantiation in the GMF and implicit instantiation.


Jason



Re: [PATCH 2/2] c++: remove lookup_template_class's entering_scope flag

2024-05-01 Thread Jason Merrill

On 5/1/24 12:41, Patrick Palka wrote:

On Fri, 2 Feb 2024, Patrick Palka wrote:


Bootstrapped and regtested on x86_64-pc-linux, does this look like
an improvement?  This is not a bugfix and barely related to the previous
patch, but the previous patch's new use of entering_scope=true motivated
me to submit this patch since it seems like a nice simplification.


Ping, now that stage 1 is open.


Thanks for the ping.  The earlier message isn't showing up in 
Thunderbird for some reason, though I see it in the gmail web interface...



@@ -16771,9 +16722,10 @@ tsubst (tree t, tree args, tsubst_flags_t complain, 
tree in_decl)
ctx = TREE_VEC_ELT (ctx, 0);
  }
else
- ctx = tsubst_aggr_type (ctx, args,
- complain | tf_qualifying_scope,
- in_decl, /*entering_scope=*/1);
+ {
+   ctx = tsubst_scope (ctx, args, complain, in_decl);


Why is this one tsubst_scope while the others are all plain tsubst?

Do we want a tsubst_entering_scope function?


+   ctx = adjust_type_for_entering_scope (ctx);




Re: [PATCH] libgcc: Rename __trunchfbf2 to __extendhfbf2

2024-05-01 Thread Jakub Jelinek
On Wed, May 01, 2024 at 12:55:25PM -0700, H.J. Lu wrote:
> Since bfloat16 has the same range as float32, _Float16 to bfloat16
> conversion is an extension, not a truncation.  Rename trunchfbf2.c
> to extendhfbf2.c to provide __extendhfbf2, instead of __trunchfbf2.
> 
> Since _Float16 to bfloat16 conversion never worked from the day one,
> the same libgcc version of __trunchfbf2 is used with __extendhfbf2 so
> that this can be backported to release branches all the way where
> __trunchfbf2 was added.

This is wrong.
First of all, it is ABI incompatible change, we can't do that.
And second, neither _Float16 is a subset of __bf16 nor the other way,
so both extend and trunc names are equally wrong.

Jakub



Re: [committed] [RISC-V] Improve floor, ceil & related operations for RISC-V

2024-05-01 Thread Jeff Law




On 5/1/24 12:44 PM, Patrick O'Neill wrote:

Hi Jeff,


It looks like this patch's gcc.target/riscv/round_64.c testcase doesn't 
pass when run with newlib.
Looks like a testsuite error as much as anything.  The test relies on 
the gimple optimizers to propagate the input paramters to their use 
points and transform (for example) a ceil into ceilf.  That's not 
happening with newlib.


Pondering the best approach to fix...

Jeff



[PATCH] libgcc: Rename __trunchfbf2 to __extendhfbf2

2024-05-01 Thread H.J. Lu
Since bfloat16 has the same range as float32, _Float16 to bfloat16
conversion is an extension, not a truncation.  Rename trunchfbf2.c
to extendhfbf2.c to provide __extendhfbf2, instead of __trunchfbf2.

Since _Float16 to bfloat16 conversion never worked from the day one,
the same libgcc version of __trunchfbf2 is used with __extendhfbf2 so
that this can be backported to release branches all the way where
__trunchfbf2 was added.

gcc/testsuite/

PR libgcc/114907
* gcc.dg/pr114907-1.c: New test.
* gcc.dg/pr114907-2.c: Likewise.

libgcc/

PR libgcc/114907
* config/aarch64/libgcc-softfp.ver (__trunchfbf2): Renamed to ...
(__extendhfbf2): This.
* config/aarch64/t-softfp (softfp_extensions): Add hfbf.
(softfp_truncations): Remove hfbf.
* config/i386/libgcc-darwin.ver (__trunchfbf2): Renamed to ...
(__extendhfbf2): This.
* config/i386/libgcc-glibc.ver (__trunchfbf2): Renamed to ...
(__extendhfbf2): This.
* config/i386/libgcc-sol2.ver (__trunchfbf2): Renamed to ...
(__extendhfbf2): This.
* config/i386/t-softfp (softfp_extensions): Add hfbf.
(softfp_truncations): Remove hfbf.
(CFLAGS-trunchfbf2.c): Renamed to ...
(CFLAGS-extendhfbf2.c): This.
* soft-fp/trunchfbf2.c: Renamed to ...
* soft-fp/extendhfbf2.c: This.
(__trunchfbf2): Renamed to ...
(__extendhfbf2): This.
---
 gcc/testsuite/gcc.dg/pr114907-1.c | 21 +++
 gcc/testsuite/gcc.dg/pr114907-2.c | 17 +++
 libgcc/config/aarch64/libgcc-softfp.ver   |  2 +-
 libgcc/config/aarch64/t-softfp|  4 ++--
 libgcc/config/i386/libgcc-darwin.ver  |  2 +-
 libgcc/config/i386/libgcc-glibc.ver   |  2 +-
 libgcc/config/i386/libgcc-sol2.ver|  2 +-
 libgcc/config/i386/t-softfp   |  6 +++---
 .../soft-fp/{trunchfbf2.c => extendhfbf2.c}   |  6 +++---
 9 files changed, 50 insertions(+), 12 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr114907-1.c
 create mode 100644 gcc/testsuite/gcc.dg/pr114907-2.c
 rename libgcc/soft-fp/{trunchfbf2.c => extendhfbf2.c} (94%)

diff --git a/gcc/testsuite/gcc.dg/pr114907-1.c 
b/gcc/testsuite/gcc.dg/pr114907-1.c
new file mode 100644
index 000..9f6219d5e88
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114907-1.c
@@ -0,0 +1,21 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+
+__bf16 bfa, bfb, bfc, bfd, bfe, bff;
+_Float16 f16a, f16b;
+float f32a, f32b;
+double da, db;
+
+int
+main (void)
+{
+  bfa = f16a;
+  f16b = bfb;
+  bfc = f32a;
+  f32b = bfd;
+  bfe = da;
+  db = bff;
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr114907-2.c 
b/gcc/testsuite/gcc.dg/pr114907-2.c
new file mode 100644
index 000..41cc88f0652
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114907-2.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-O0" } */
+/* { dg-add-options bfloat16 } */
+/* { dg-add-options __float128 } */
+/* { dg-require-effective-target bfloat16_runtime } */
+/* { dg-require-effective-target __float128 } */
+
+__bf16 bfa, bfb;
+__float128 fa, fb;
+
+int
+main (void)
+{
+  bfa = fa;
+  fb = bfb;
+  return 0;
+}
diff --git a/libgcc/config/aarch64/libgcc-softfp.ver 
b/libgcc/config/aarch64/libgcc-softfp.ver
index 9ba857036ab..d6e427cbf7e 100644
--- a/libgcc/config/aarch64/libgcc-softfp.ver
+++ b/libgcc/config/aarch64/libgcc-softfp.ver
@@ -30,6 +30,7 @@ GCC_11.0 {
 %inherit GCC_13.0.0 GCC_11.0.0
 GCC_13.0.0 {
   __extendbfsf2
+  __extendhfbf2
   __floatdibf
   __floattibf
   __floatundibf
@@ -37,7 +38,6 @@ GCC_13.0.0 {
   __truncdfbf2
   __truncsfbf2
   __trunctfbf2
-  __trunchfbf2
 }
 
 %inherit GCC_14.0.0 GCC_13.0.0
diff --git a/libgcc/config/aarch64/t-softfp b/libgcc/config/aarch64/t-softfp
index 80e7e77a545..5c7e6dbc5b5 100644
--- a/libgcc/config/aarch64/t-softfp
+++ b/libgcc/config/aarch64/t-softfp
@@ -1,7 +1,7 @@
 softfp_float_modes := tf
 softfp_int_modes := si di ti
-softfp_extensions := sftf dftf hftf bfsf
-softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf hfbf
+softfp_extensions := sftf dftf hftf bfsf hfbf
+softfp_truncations := tfsf tfdf tfhf tfbf dfbf sfbf
 softfp_exclude_libgcc2 := n
 softfp_extras += fixhfti fixunshfti floattihf floatuntihf \
 floatdibf floatundibf floattibf floatuntibf \
diff --git a/libgcc/config/i386/libgcc-darwin.ver 
b/libgcc/config/i386/libgcc-darwin.ver
index 06560d6b47f..1e7efb828ed 100644
--- a/libgcc/config/i386/libgcc-darwin.ver
+++ b/libgcc/config/i386/libgcc-darwin.ver
@@ -29,13 +29,13 @@ GCC_12.0.0 {
 GCC_14.0.0 {
   # Added to GCC_13.0.0 in i386/libgcc-glibc.ver.
   __extendbfsf2
+  __extendhfbf2
   __floattibf
   __floatuntibf
   __truncdfbf2
   __truncsfbf2
   __trunctfbf2
   __truncxfbf2
-  __trunchfbf2
   # Added to GCC_14.0.0 in i386/libgcc-glibc.ver.
   __fixxfbitint
   __fixtfbitint
diff 

[PATCH] libstdc++: Fix handling of incomplete UTF-8 sequences in _Unicode_view

2024-05-01 Thread Jonathan Wakely
Tested x86_64-linux.

I'm considering making the increment of __to_incr conditional:

if constexpr (!random_access_iterator<_Iter>)
  ++__to_incr;

and then when we call _M_update using _M_curr() - __g._M_orig for the
number of characters consumed. I should benchmark that to see if it
makes any measurable difference though.

-- >8 --

Eddie Nolan reported to me that _Unicode_view was not correctly
implementing the substitution of ill-formed subsequences with U+FFFD,
due to failing to increment the counter when the iterator reaches the
end of the sequence before a multibyte sequence is complete.  As a
result, the incomplete sequence was not completely consumed, and then
the remaining character was treated as another ill-formed sequence,
giving two U+FFFD characters instead of one.

To avoid similar mistakes in future, this change introduces a lambda
that increments the iterator and the counter together. This ensures the
counter is always incremented when the iterator is incremented, so that
we always know how many characters have been consumed.

libstdc++-v3/ChangeLog:

* include/bits/unicode.h (_Unicode_view::_M_read_utf8): Ensure
count of characters consumed is correct when the end of the
input is reached unexpectedly.
* testsuite/ext/unicode/view.cc: Test incomplete UTF-8
sequences.
---
 libstdc++-v3/include/bits/unicode.h| 24 ++
 libstdc++-v3/testsuite/ext/unicode/view.cc |  7 +++
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/bits/unicode.h 
b/libstdc++-v3/include/bits/unicode.h
index 29813b743dc..46238143fb6 100644
--- a/libstdc++-v3/include/bits/unicode.h
+++ b/libstdc++-v3/include/bits/unicode.h
@@ -261,9 +261,13 @@ namespace __unicode
   {
_Guard<_Iter> __g{this, _M_curr()};
char32_t __c{};
-   uint8_t __u = *_M_curr()++;
const uint8_t __lo_bound = 0x80, __hi_bound = 0xBF;
+   uint8_t __u = *_M_curr()++;
uint8_t __to_incr = 1;
+   auto __incr = [&, this] {
+ ++__to_incr;
+ return ++_M_curr();
+   };
 
if (__u <= 0x7F) [[likely]]  // 0x00 to 0x7F
  __c = __u;
@@ -281,8 +285,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
else if (__u <= 0xEF) // 0xE0 to 0xEF
@@ -295,11 +298,10 @@ namespace __unicode
 
if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
@@ -308,8 +310,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
  }
@@ -323,21 +324,19 @@ namespace __unicode
 
if (__u < __lo_bound_2 || __u > __hi_bound_2) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
if (__u < __lo_bound || __u > __hi_bound) [[unlikely]]
  __c = _S_error();
-   else if (++_M_curr() == _M_last) [[unlikely]]
+   else if (__incr() == _M_last) [[unlikely]]
  __c = _S_error();
else
  {
-   ++__to_incr;
__c = (__c << 6) | (__u & 0x3F);
__u = *_M_curr();
 
@@ -346,8 +345,7 @@ namespace __unicode
else
  {
__c = (__c << 6) | (__u & 0x3F);
-   ++_M_curr();
-   ++__to_incr;
+   __incr();
  }
  }
  }
diff --git a/libstdc++-v3/testsuite/ext/unicode/view.cc 
b/libstdc++-v3/testsuite/ext/unicode/view.cc
index ee23b0b1d8a..6f3c099bd84 100644
--- a/libstdc++-v3/testsuite/ext/unicode/view.cc
+++ b/libstdc++-v3/testsuite/ext/unicode/view.cc
@@ -55,6 +55,13 @@ test_illformed_utf8()
   VERIFY( std::ranges::equal(v5, 
u8"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41\uFFFD\uFFFD\x42"sv) );
   uc::_Utf8_view v6("\xe1\x80\xe2\xf0\x91\x92\xf1\xbf\x41"sv); // Table 3-11
   VERIFY( std::ranges::equal(v6, u8"\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv) );
+
+  uc::_Utf32_view v7("\xe1\x80"sv);
+  VERIFY( std::ranges::equal(v7, 

Re: [PATCH 2/2] c++: remove lookup_template_class's entering_scope flag

2024-05-01 Thread Patrick Palka
On Fri, 2 Feb 2024, Patrick Palka wrote:

> Bootstrapped and regtested on x86_64-pc-linux, does this look like
> an improvement?  This is not a bugfix and barely related to the previous
> patch, but the previous patch's new use of entering_scope=true motivated
> me to submit this patch since it seems like a nice simplification.

Ping, now that stage 1 is open.

> 
> -- >8 --
> 
> lookup_template_class's entering_scope flag controls whether to prefer
> returning the primary template type A instead of the corresponding
> implicit instantiation A.  When we want to set this flag as part of
> substitution, we need to use tsubst_aggr_type which also takes the flag,
> but this separate entry point to substitution turned out to be subtly
> problematic because it doesn't reuse typedefs like tsubst does, which
> r13-4729-gbe124477b38a71 fixed in a way that respects the flag after the
> fact, by adjusting the entering_scope=false result of
> lookup_template_class as if entering_scope=true was passed.
> 
> But if that's possible then it means lookup_template_class's the
> entering_scope flag is not necessary after all -- we can just do the
> after-the-fact adjustment everywhere that we currently pass
> entering_scope=true to it and tsubst_aggr_type.
> 
> To that end, this patch replaces this flag with an adjustment function
> adjust_type_for_entering_scope, to be used whereever we currently need
> the entering_scope=true behavior.  This means we can also get rid of
> tsubst_aggr_type, since the only reason we needed this entry point
> was to be able to pass entering_scope=true to lookup_template_class.
> 
> gcc/cp/ChangeLog:
> 
>   * coroutines.cc (instantiate_coro_traits): Adjust call to
>   lookup_template_class.
>   (instantiate_coro_handle_for_promise_type): Likewise.
>   * cp-tree.h (adjust_type_for_entering_scope): Declare.
>   (lookup_template_class): Adjust declaration.
>   * decl.cc (make_typename_type): Adjust call to
>   lookup_template_class. Likewise.
>   (get_tuple_size): Likewise.
>   (get_tuple_element_type): Likewise.
>   * pt.cc (adjust_type_for_entering_scope): Define.
>   (lookup_template_class): Remove entering_scope parameter.
>   Replace tsubst_aggr_type call with tsubst followed by
>   adjust_type_for_entering_scope.
>   (tsubst_aggr_type): Remove.
>   (tsubst_aggr_type_1): Inline into tsubst.
>   (tsubst_function_decl): Replace tsubst_aggr_type call
>   with tsubst followed by adjust_type_for_entering_scope.
>   (tsubst_template_decl): Likewise.
>   (tsubst_decl): Likewise.
>   (tsubst) :
>   Inlined from tsubst_aggr_type_1.
>   : Adjust calls to
>   lookup_template_class.
>   : Replace tsubst_aggr_type call with
>   tsubst tsubst_scope followed by adjust_type_for_entering_scope.
>   : Replace tsubst_aggr_type
>   call with tsubst followed by adjust_type_for_entering_scope.
>   Increment processing_template_decl when substituting the
>   context.
>   (tsubst_baselink): Replace tsubst_aggr_type call with tsubst
>   followed by adjust_type_for_entering_scope.
>   (tsubst_expr) : Replace tsubst_aggr_type
>   call with tsubst followed by adjust_type_for_entering_scope.
>   : Likewise.
>   (instantiate_template): Likewise.
>   (resolve_typename_type): Adjust lookup_template_class call
>   and call adjust_type_for_entering_scope afterward.
>   (listify): Adjust lookup_template_class call.
>   (alias_ctad_tweaks): Likewise.
>   * semantics.cc (finish_template_type): Adjust lookup_template_class
>   call and maybe call adjust_type_for_entering_scope afterward.
> ---
>  gcc/cp/coroutines.cc |   4 +-
>  gcc/cp/cp-tree.h |   3 +-
>  gcc/cp/decl.cc   |   4 +-
>  gcc/cp/pt.cc | 212 +--
>  gcc/cp/semantics.cc  |   4 +-
>  5 files changed, 91 insertions(+), 136 deletions(-)
> 
> diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
> index 3194c911e8c..8dab173d5cb 100644
> --- a/gcc/cp/coroutines.cc
> +++ b/gcc/cp/coroutines.cc
> @@ -353,7 +353,7 @@ instantiate_coro_traits (tree fndecl, location_t kw)
>tree traits_class
>  = lookup_template_class (coro_traits_templ, targ,
>/*in_decl=*/NULL_TREE, /*context=*/NULL_TREE,
> -  /*entering scope=*/false, tf_warning_or_error);
> +  tf_warning_or_error);
>  
>if (traits_class == error_mark_node)
>  {
> @@ -400,7 +400,7 @@ instantiate_coro_handle_for_promise_type (location_t kw, 
> tree promise_type)
>  = lookup_template_class (coro_handle_identifier, targ,
>/* in_decl=*/NULL_TREE,
>/* context=*/std_node,
> -  /* entering scope=*/false, tf_warning_or_error);
> +  tf_warning_or_error);
>  
>if (handle_type == error_mark_node)
>  {
> diff --git 

[PATCH 4/6] btf: refactor and simplify implementation

2024-05-01 Thread David Faust
This patch heavily refactors btfout.cc to take advantage of the
structural changes in the prior commits.

Now that inter-type references are internally stored as simply pointers,
all the painful, brittle, confusing infrastructure that was used in the
process of converting CTF type IDs to BTF type IDs can be thrown out.
This greatly simplifies the entire process of converting from CTF to
BTF, making the code cleaner, easier to read, and easier to maintain.

In addition, we no longer need to worry about destructive changes in
internal data structures used commonly by CTF and BTF, which allows
deleting several ancillary data structures previously used in btfout.cc.

This is nearly transparent, but a few improvements have also been made:

 1) BTF_KIND_FUNC records are now _always_ constructed at early_finish,
allowing us to construct records even for functions which are later
inlined by optimizations. DATASEC entries for functions are only
constructed at late_finish, to avoid incorrectly generating entries
for functions which get inlined.

 2) BTF_KIND_VAR records and DATASEC entries for them are now always
constructed at (late) finish, which avoids cases where we could
incorrectly create records for variables which were completely
optimized away. This fixes PR debug/113566.

 3) Some additional assembler comments have been added with more
information for debugging.

gcc/
* btfout.cc (struct btf_datasec_entry): New.
(struct btf_datasec): Add `id' member.  Change `entries' to use
new struct btf_datasec_entry.
(func_map): New hash_map.
(max_translated_id): New.
(btf_var_ids, btf_id_map, holes, voids, num_vars_added)
(num_types_added, num_types_created): Delete.
(btf_absolute_var_id, btf_relative_var_id, btf_absolute_func_id)
(btf_relative_func_id, btf_absolute_datasec_id, init_btf_id_map)
(get_btf_id, set_btf_id, btf_emit_id_p): Delete.
(btf_removed_type_p): Delete.
(btf_dtd_kind, btf_emit_type_p): New helpers.
(btf_fwd_to_enum_p, btf_calc_num_vbytes): Use them.
(btf_collect_datasec): Delete.
(btf_dtd_postprocess_cb, btf_dvd_emit_preprocess_cb)
(btf_dtd_emit_preprocess_cb, btf_emit_preprocess): Delete.
(btf_dmd_representable_bitfield_p): Adapt to type reference changes
and delete now-unused ctfc argument.
(btf_asm_datasec_type_ref): Delete.
(btf_asm_type_ref): Adapt to type reference changes, simplify.
(btf_asm_type): Likewise. Mark struct/union types with bitfield
members.
(btf_asm_array): Adapt to data structure changes.
(btf_asm_varent): Likewise.
(btf_asm_sou_member): Likewise. Ensure non-bitfield members are
correctly re-encoded if struct or union contains any bitfield.
(btf_asm_func_arg, btf_asm_func_type, btf_asm_datasec_entry)
(btf_asm_datasec_type): Adapt to data structure changes.
(output_btf_header): Adapt to other changes, simplify type
length calculation, add info to assembler comments.
(output_btf_vars): Adapt to other changes.
(output_btf_strs): Fix overlong lines.
(output_asm_btf_sou_fields, output_asm_btf_enum_list)
(output_asm_btf_func_args_list, output_asm_btf_vlen_bytes)
(output_asm_btf_type, output_btf_types, output_btf_func_types)
(output_btf_datasec_types): Adapt to other changes.
(btf_init_postprocess): Delete.
(btf_output): Change to only perform output.
(btf_early_add_const_void, btf_early_add_func_records): New.
(btf_early_finish): Use them here. New.
(btf_datasec_push_entry): Adapt to data structure changes.
(btf_datasec_add_func, btf_datasec_add_var): New.
(btf_late_add_func_datasec_entries): New.
(btf_emit_variable_p): New helper.
(btf_late_add_vars): Use it here. New.
(btf_type_list_cb, btf_late_collect_translated_types): New.
(btf_late_assign_func_ids, btf_late_assign_var_ids)
(btf_late_assign_datasec_ids): New.
(btf_finish): Remove unused argument. Call new btf_late*
functions and btf_output.
(btf_finalize): Adapt to data structure changes.
* ctfc.h (struct ctf_dtdef): Convert existing boolean flags to
BOOL_BITFIELD and reorder.
(struct ctf_dvdef): Add dvd_id member.
(btf_finish): Remove argument from prototype.
(get_btf_id): Delete prototype.
(funcs_traverse_callback, traverse_btf_func_types): Add an
explanatory comment.
* dwarf2ctf.cc (ctf_debug_finish): Remove unused argument.
* dwarf2ctf.h: Analogous change.
* dwarf2out.cc: Likewise.
---
 gcc/btfout.cc| 1261 +++---
 gcc/ctfc.h   |   17 +-
 gcc/dwarf2ctf.cc |4 +-
 gcc/dwarf2ctf.h  |2 +-
 gcc/dwarf2out.cc |2 +-
 5 files changed, 543 insertions(+), 743 

[PATCH 3/6] ctf: use pointers instead of IDs internally

2024-05-01 Thread David Faust
This patch replaces all inter-type references in the ctfc internal data
structures with pointers, rather than the references-by-ID which were
used previously.

A couple of small updates in the BPF backend are included to make it
compatible with the change.

This change is only to the in-memory representation of various CTF
structures to make them easier to work with in various cases.  It is
outwardly transparent; there is no change in emitted CTF.

gcc/
* ctfc.h (struct ctf_dtdef): Add forward declaration.
(struct ctf_arinfo, struct ctf_funcinfo, struct ctf_sliceinfo)
(struct ctf_itype, struct ctf_dmdef, struct ctf_func_arg)
(struct ctf_dvdef): Use pointers instead of type IDs for
references to other types.
(struct ctf_dtdef): Add ref_type member.
(ctf_type_exists): Use pointer instead of type ID.
(ctf_add_reftype, ctf_add_enum, ctf_add_slice, ctf_add_float)
(ctf_add_integer, ctf_add_unknown, ctf_add_pointer)
(ctf_add_array, ctf_add_forward, ctf_add_typedef)
(ctf_add_function, ctf_add_sou, ctf_add_enumerator)
(ctf_add_variable): Likewise. Return pointer instead of ID.
(ctf_lookup_tree_type): Return pointer to type instead of ID.
* ctfc.cc: Analogous changes.
* ctfout.cc (ctf_asm_type, ctf_asm_slice, ctf_asm_varent)
(ctf_asm_sou_lmember, ctf_asm_sou_member, ctf_asm_func_arg)
(output_ctf_objt_info): Adapt to changes.
* dwarf2ctf.cc (gen_ctf_type, gen_ctf_void_type)
(gen_ctf_unknown_type, gen_ctf_base_type, gen_ctf_pointer_type)
(gen_ctf_subrange_type, gen_ctf_array_type, gen_ctf_typedef)
(gen_ctf_modifier_type, gen_ctf_sou_type, gen_ctf_function_type)
(gen_ctf_enumeration_type, gen_ctf_variable, gen_ctf_function)
(gen_ctf_type, ctf_do_die): Likewise.
* config/bpf/btfext-out.cc (struct btf_ext_core_reloc): Use
pointer instead of type ID.
(bpf_core_reloc_add, bpf_core_get_sou_member_index)
(output_btfext_core_sections): Adapt to above changes.
* config/bpf/core-builtins.cc (process_type): Likewise.
---
 gcc/config/bpf/btfext-out.cc|  12 +-
 gcc/config/bpf/core-builtins.cc |   3 +-
 gcc/ctfc.cc | 137 +-
 gcc/ctfc.h  |  61 
 gcc/ctfout.cc   |  19 +--
 gcc/dwarf2ctf.cc| 244 +++-
 6 files changed, 233 insertions(+), 243 deletions(-)

diff --git a/gcc/config/bpf/btfext-out.cc b/gcc/config/bpf/btfext-out.cc
index 7ec438fd1d1..ce596e33643 100644
--- a/gcc/config/bpf/btfext-out.cc
+++ b/gcc/config/bpf/btfext-out.cc
@@ -134,7 +134,7 @@ struct GTY ((chain_next ("%h.next"))) btf_ext_lineinfo
 
 /* Internal representation of a BPF CO-RE relocation record.  */
 struct GTY ((chain_next ("%h.next"))) btf_ext_core_reloc {
-  unsigned int bpfcr_type; /* BTF type ID of container.  */
+  ctf_dtdef_ref bpfcr_type;/* BTF type of container.  */
   unsigned int  bpfcr_astr_off;/* Offset of access string in 
.BTF
   string table.  */
   rtx_code_label * bpfcr_insn_label;   /* RTX label attached to instruction
@@ -296,13 +296,14 @@ bpf_core_reloc_add (const tree type, const char * 
section_name,
   struct btf_ext_core_reloc *bpfcr = bpf_create_core_reloc (section_name, 
);
 
   ctf_container_ref ctfc = ctf_get_tu_ctfc ();
+  ctf_dtdef_ref dtd = ctf_lookup_tree_type (ctfc, type);
 
   /* Buffer the access string in the auxiliary strtab.  */
   bpfcr->bpfcr_astr_off = 0;
   gcc_assert (accessor != NULL);
   bpfcr->bpfcr_astr_off = btf_ext_add_string (accessor);
 
-  bpfcr->bpfcr_type = get_btf_id (ctf_lookup_tree_type (ctfc, type));
+  bpfcr->bpfcr_type = dtd;
   bpfcr->bpfcr_insn_label = label;
   bpfcr->bpfcr_kind = kind;
 
@@ -341,7 +342,7 @@ bpf_core_get_sou_member_index (ctf_container_ref ctfc, 
const tree node)
   for (dmd = dtd->dtd_u.dtu_members;
dmd != NULL; dmd = (ctf_dmdef_t *) ctf_dmd_list_next (dmd))
 {
- bool field_has_btf = get_btf_id (dmd->dmd_type) <= BTF_MAX_TYPE;
+ bool field_has_btf = (dmd->dmd_type && dmd->dmd_type->dtd_type <= 
BTF_MAX_TYPE);
 
  if (field == node)
return field_has_btf ? i : -1;
@@ -574,8 +575,9 @@ output_btfext_core_sections (void)
 false);
  char *str = xstrdup (pp_formatted_text ());
 
- dw2_asm_output_data (4, bpfcr->bpfcr_type, "bpfcr_type (%s)",
-  str);
+ uint32_t type_id =
+   bpfcr->bpfcr_type ? bpfcr->bpfcr_type->dtd_type : 0;
+ dw2_asm_output_data (4, type_id, "bpfcr_type (%s)", str);
  dw2_asm_output_data (4, bpfcr->bpfcr_astr_off + str_aux_off,
   "bpfcr_astr_off (\"%s\")",
   bpfcr->info.accessor_str);

[PATCH 5/6] btf: add -fprune-btf option

2024-05-01 Thread David Faust
This patch adds a new option, -fprune-btf, to control BTF debug info
generation.

As the name implies, this option enables a kind of "pruning" of the BTF
information before it is emitted.  When enabled, rather than emitting
all type information translated from DWARF, only information for types
directly used in the source program is emitted.

The primary purpose of this pruning is to reduce the amount of
unnecessary BTF information emitted, especially for BPF programs.  It is
very common for BPF programs to incldue Linux kernel internal headers in
order to have access to kernel data structures.  However, doing so often
has the side effect of also adding type definitions for a large number
of types which are not actually used by nor relevant to the program.
In these cases, -fprune-btf commonly reduces the size of the resulting
BTF information by approximately 10x.  This both slims down the size of
the resulting object and reduces the time required by the BPF loader to
verify the program and its BTF information.

Note that the pruning implemented in this patch follows the same rules
as the BTF pruning performed unconditionally by LLVM's BPF backend when
generating BTF.  In particular, the main sources of pruning are:

  1) Only generate BTF for types used by variables and functions at
 the file scope.

  2) Avoid emitting full BTF for struct and union types which are only
 pointed-to by members of other struct/union types.  In these cases,
 the full BTF_KIND_STRUCT or BTF_KIND_UNION which would normally
 be emitted is replaced with a BTF_KIND_FWD, as though the
 underlying type was a forward-declared struct or union type.

gcc/
* btfout.cc (btf_minimal_types): New hash set.
(struct btf_fixup): New.
(fixups, forwards): New vecs.
(btf_output): Calculate num_types depending on flag_prune_btf.
(btf_early_finsih): New initialization for flag_prune_btf.
(btf_mark_full_type_used): Likewise.
(btf_minimal_add_type): New function.
(btf_minimal_type_list_cb): Likewise.
(btf_late_collect_pruned_types): Likewise.
(btf_late_add_vars): Handle special case for variables in ".maps"
section when generating BTF for BPF CO-RE target.
(btf_late_finish): Use btf_late_collect_pruned_types when
flag_prune_btf in effect.  Move some initialization to btf_early_finish.
(btf_finalize): Additional deallocation for flag_prune_btf.
* common.opt (fprune-btf): New flag.
* ctfc.cc (init_ctf_strtable): Make non-static.
* ctfc.h (struct ctf_dtdef): Add visited_children_p boolean flag.
(init_ctf_strtable, ctfc_delete_strtab): Make extern.
* doc/invoke.texi (Debugging Options): Document -fprune-btf.

gcc/testsuite/
* gcc.dg/debug/btf/btf-prune-1.c: New test.
* gcc.dg/debug/btf/btf-prune-2.c: Likewise.
* gcc.dg/debug/btf/btf-prune-3.c: Likewise.
---
 gcc/btfout.cc| 394 ++-
 gcc/common.opt   |   4 +
 gcc/ctfc.cc  |   2 +-
 gcc/ctfc.h   |   5 +
 gcc/doc/invoke.texi  |  20 +
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-1.c |  25 ++
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-2.c |  33 ++
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-3.c |  35 ++
 8 files changed, 511 insertions(+), 7 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-3.c

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 0af0bd39fc7..93d56492bbe 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -833,7 +833,10 @@ output_btf_types (ctf_container_ref ctfc)
 {
   size_t i;
   size_t num_types;
-  num_types = ctfc->ctfc_types->elements ();
+  if (flag_prune_btf)
+num_types = max_translated_id;
+  else
+num_types = ctfc->ctfc_types->elements ();
 
   if (num_types)
 {
@@ -962,6 +965,211 @@ btf_early_add_func_records (ctf_container_ref ctfc)
 }
 }
 
+/* The set of types used directly in the source program, and any types manually
+   marked as used.  This is the set of types which will be emitted when
+   pruning (-fprune-btf) is enabled.  */
+static GTY (()) hash_set *btf_minimal_types;
+
+/* Fixup used to avoid unnecessary pointer chasing for types.  A fixup is
+   created when a structure or union member is a pointer to another struct
+   or union type.  In such cases, avoid emitting full type information for
+   the pointee struct or union type (which may be quite large), unless that
+   type is used directly elsewhere.  */
+struct btf_fixup
+{
+  ctf_dtdef_ref pointer_dtd; /* Type node to which the fixup is applied.  */
+  ctf_dtdef_ref pointee_dtd; /* Original type node referred to by pointer_dtd.
+   If this concrete type is not otherwise used,
+  

[PATCH 6/6] bpf,btf: enable BTF pruning by default for BPF

2024-05-01 Thread David Faust
This patch enables -fprune-btf by default in the BPF backend when
generating BTF information, and fixes BPF CO-RE generation when using
-fprune-btf.

When generating BPF CO-RE information, we must ensure that types used
in CO-RE relocations always have sufficient BTF information emited so
that the CO-RE relocations can be processed by a BPF loader.  The BTF
pruning algorithm on its own does not have sufficient information to
determine which types are used in a BPF CO-RE relocation, so this
information must be supplied by the BPF backend, using a new
btf_mark_type_used function.

Co-authored-by: Cupertino Miranda 

gcc/
* btfout.cc (btf_mark_type_used): New.
* ctfc.h (btf_mark_type_used): Declare it here.
* config/bpf/bpf.cc (bpf_option_override): Enable -fprune-btf
by default if -gbtf is enabled.
* config/bpf/bcore-builtins.cc (extra_fn): New typedef.
(compute_field_expr): Add callback parameter, and call it if supplied.
Fix computation for MEM_REF.
(mark_component_type_as_used): New.
(bpf_mark_types_as_used): Likewise.
(bpf_expand_core_builtin): Call here.
* doc/invoke.texi (Debugging Options): Note that -fprune-btf is
enabled by default for BPF target when generating BTF.

gcc/testsuite/
* gcc.dg/debug/btf/btf-variables-5.c: Add -fno-prune-btf to dg-options.
---
 gcc/btfout.cc | 22 ++
 gcc/config/bpf/bpf.cc |  5 ++
 gcc/config/bpf/core-builtins.cc   | 70 +--
 gcc/ctfc.h|  1 +
 gcc/doc/invoke.texi   |  3 +
 .../gcc.dg/debug/btf/btf-variables-5.c|  2 +-
 6 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 93d56492bbe..da2c9d35be9 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -1539,6 +1539,28 @@ btf_late_assign_datasec_ids (ctf_container_ref ctfc)
 }
 }
 
+
+/* Manually mark that type T is used to ensure it will not be pruned.
+   Used by the BPF backend when generating BPF CO-RE to mark types used
+   in CO-RE relocations.  */
+
+void
+btf_mark_type_used (tree t)
+{
+  /* If we are not going to prune anyway, this is a no-op.  */
+  if (!flag_prune_btf)
+return;
+
+  gcc_assert (TYPE_P (t));
+  ctf_container_ref ctfc = ctf_get_tu_ctfc ();
+  ctf_dtdef_ref dtd = ctf_lookup_tree_type (ctfc, t);
+
+  if (!dtd)
+return;
+
+  btf_minimal_add_type (ctfc, dtd, false, false);
+}
+
 /* Callback used for assembling the only-used-types list.  Note that this is
the same as btf_type_list_cb above, but the hash_set traverse requires a
different function signature.  */
diff --git a/gcc/config/bpf/bpf.cc b/gcc/config/bpf/bpf.cc
index e6ea211a2c6..75303ce8f46 100644
--- a/gcc/config/bpf/bpf.cc
+++ b/gcc/config/bpf/bpf.cc
@@ -221,6 +221,11 @@ bpf_option_override (void)
   && !(target_flags_explicit & MASK_BPF_CORE))
 target_flags |= MASK_BPF_CORE;
 
+  /* -gbtf implies -fprune-btf for BPF target.  */
+  if (btf_debuginfo_p ())
+SET_OPTION_IF_UNSET (_options, _options_set,
+flag_prune_btf, true);
+
   /* Determine available features from ISA setting (-mcpu=).  */
   if (bpf_has_jmpext == -1)
 bpf_has_jmpext = (bpf_isa >= ISA_V2);
diff --git a/gcc/config/bpf/core-builtins.cc b/gcc/config/bpf/core-builtins.cc
index d5a7de825ad..1b91b1c0d25 100644
--- a/gcc/config/bpf/core-builtins.cc
+++ b/gcc/config/bpf/core-builtins.cc
@@ -624,13 +624,20 @@ bpf_core_get_index (const tree node, bool *valid)
 
ALLOW_ENTRY_CAST is an input arguments and specifies if the function should
consider as valid expressions in which NODE entry is a cast expression (or
-   tree code nop_expr).  */
+   tree code nop_expr).
+
+   EXTRA_FN is a callback function to allow extra functionality with this
+   function traversal. Currently used for marking used type during expand
+   pass.  */
+
+typedef void (*extra_fn) (tree);
 
 static unsigned char
 compute_field_expr (tree node, unsigned int *accessors,
bool *valid,
tree *access_node,
-   bool allow_entry_cast = true)
+   bool allow_entry_cast = true,
+   extra_fn callback = NULL)
 {
   unsigned char n = 0;
   unsigned int fake_accessors[MAX_NR_ACCESSORS];
@@ -647,6 +654,9 @@ compute_field_expr (tree node, unsigned int *accessors,
 
   *access_node = node;
 
+  if (callback != NULL)
+callback (node);
+
   switch (TREE_CODE (node))
 {
 case INDIRECT_REF:
@@ -664,17 +674,19 @@ compute_field_expr (tree node, unsigned int *accessors,
 case COMPONENT_REF:
   n = compute_field_expr (TREE_OPERAND (node, 0), accessors,
  valid,
- access_node, false);
+ access_node, false, callback);
   accessors[n] = bpf_core_get_index (TREE_OPERAND (node, 1), valid);

[PATCH 1/6] ctf, btf: restructure CTF/BTF emission

2024-05-01 Thread David Faust
This commit makes some structural changes to the CTF/BTF debug info
emission.  In particular:

 a) CTF is new always fully generated and emitted before any
BTF-related procedures are run.  This means that BTF-related
functions can change, even irreversibly, the shared in-memory
representation used by the two formats without issue.

 b) BTF generation has fewer entry points, and is cleanly divided
into early_finish and finish.

 c) BTF is now always emitted at finish (called from dwarf2out_finish),
rather than being emitted at early_finish for targets other than
BPF CO-RE.  Note that this change alone does not alter the contents
of BTF at all, regardless of whether it would have previously been
emitted at early_finish or finish.

The changes are transparent to both CTF and BTF emission.

gcc/
* btfout.cc (btf_init_postprocess): Rename to...
(btf_early_finish): ...this.
(btf_output): Rename to...
(btf_finish): ...this.
* ctfc.h: Analogous changes.
* dwarf2ctf.cc (ctf_debug_early_finish): Conditionally call
btf_early_finish or ctf_finalize as appropriate.
(ctf_debug_finish): Always call btf_finish here if generating
BTF info.
(ctf_debug_finalize, ctf_debug_init_postprocess): Delete.
* dwarf2out.cc (dwarf2out_early_finish): Remove call to
ctf_debug_init_postprocess.
---
 gcc/btfout.cc| 28 +
 gcc/ctfc.h   |  4 ++--
 gcc/dwarf2ctf.cc | 54 +++-
 gcc/dwarf2out.cc |  2 --
 4 files changed, 42 insertions(+), 46 deletions(-)

diff --git a/gcc/btfout.cc b/gcc/btfout.cc
index 07f066a4706..1b6a9ed811f 100644
--- a/gcc/btfout.cc
+++ b/gcc/btfout.cc
@@ -1491,6 +1491,34 @@ btf_finalize (void)
   tu_ctfc = NULL;
 }
 
+/* Initial entry point of BTF generation, called at early_finish () after
+   CTF information has possibly been output.  Translate all CTF information
+   to BTF, and do any processing that must be done early, such as creating
+   BTF_KIND_FUNC records.  */
+
+void
+btf_early_finish (void)
+{
+  btf_init_postprocess ();
+}
+
+/* Late entry point for BTF generation, called from dwarf2out_finish ().
+   Complete and emit BTF information.  */
+
+void
+btf_finish (const char * filename)
+{
+  btf_output (filename);
+
+  /* If compiling for BPF with CO-RE info, we cannot deallocate until after
+ CO-RE information is created, which happens very late in BPF backend.
+ Therefore, the deallocation (i.e. btf_finalize ()) is delayed until
+ TARGET_ASM_FILE_END for BPF CO-RE.  */
+  if (!btf_with_core_debuginfo_p ())
+btf_finalize ();
+}
+
+
 /* Traversal function for all BTF_KIND_FUNC type records.  */
 
 bool
diff --git a/gcc/ctfc.h b/gcc/ctfc.h
index fa188bf2f5a..e7bd93901cf 100644
--- a/gcc/ctfc.h
+++ b/gcc/ctfc.h
@@ -384,8 +384,8 @@ extern void ctf_init (void);
 extern void ctf_output (const char * filename);
 extern void ctf_finalize (void);
 
-extern void btf_output (const char * filename);
-extern void btf_init_postprocess (void);
+extern void btf_early_finish (void);
+extern void btf_finish (const char * filename);
 extern void btf_finalize (void);
 
 extern ctf_container_ref ctf_get_tu_ctfc (void);
diff --git a/gcc/dwarf2ctf.cc b/gcc/dwarf2ctf.cc
index dc59569fe56..ec94982e4b1 100644
--- a/gcc/dwarf2ctf.cc
+++ b/gcc/dwarf2ctf.cc
@@ -933,30 +933,6 @@ gen_ctf_type (ctf_container_ref ctfc, dw_die_ref die)
   return type_id;
 }
 
-/* Prepare for output and write out the CTF debug information.  */
-
-static void
-ctf_debug_finalize (const char *filename, bool btf)
-{
-  if (btf)
-{
-  btf_output (filename);
-  /* btf_finalize when compiling BPF applciations gets deallocated by the
-BPF target in bpf_file_end.  */
-  if (btf_debuginfo_p () && !btf_with_core_debuginfo_p ())
-   btf_finalize ();
-}
-
-  else
-{
-  /* Emit the collected CTF information.  */
-  ctf_output (filename);
-
-  /* Reset the CTF state.  */
-  ctf_finalize ();
-}
-}
-
 bool
 ctf_do_die (dw_die_ref die)
 {
@@ -996,27 +972,21 @@ ctf_debug_init (void)
   add_name_attribute (ctf_unknown_die, "unknown");
 }
 
-/* Preprocess the CTF debug information after initialization.  */
-
-void
-ctf_debug_init_postprocess (bool btf)
-{
-  /* Only BTF requires postprocessing right after init.  */
-  if (btf)
-btf_init_postprocess ();
-}
-
 /* Early finish CTF/BTF debug info.  */
 
 void
 ctf_debug_early_finish (const char * filename)
 {
-  /* Emit CTF debug info early always.  */
-  if (ctf_debug_info_level > CTFINFO_LEVEL_NONE
-  /* Emit BTF debug info early if CO-RE relocations are not
-required.  */
-  || (btf_debuginfo_p () && !btf_with_core_debuginfo_p ()))
-ctf_debug_finalize (filename, btf_debuginfo_p ());
+  /* Emit the collected CTF information.  */
+  if (ctf_debug_info_level > CTFINFO_LEVEL_NONE)
+ctf_output (filename);
+
+  if (btf_debuginfo_p ())
+

[PATCH 0/6] btf: refactor and add pruning option

2024-05-01 Thread David Faust
This patch series signficantly refactors the BTF generation in gcc,
making it simpler and easier to understand, extend and maintain.

It also introduces an optional algorithm to "prune" BTF information
before emission.  This pruning is meant to be used for BPF programs,
to alleviate the massive bloating of BPF progams caused by including
Linux kernel internal headers.  The pruning is designed to be almost
equivalent to that performed unconditionally by the LLVM BPF backend
when generating BTF information, for compatibility purposes.

While the changes are fairly significant, there is very little actual
change in emitted BTF information (unless pruning is enabled), other
than bug fixes and additions to the assembler debug comments.

Patch 1 restructures the emission of CTF and BTF information, with the
result that CTF is always completely generated and emitted before any
BTF-related procedures are run.

Patch 2 takes advantage of that change, and removes the restriction on
generating both CTF and BTF in the same compiler run, allowing for any
combinaion of -gdwarf, -gctf and -gbtf.

Patch 3 changes the data structures shared by CTF and BTF to use
pointers rather than type IDs for all inter-type references.  This
change is completely transparent to both CTF and BTF.

Patch 4 heavily refactors btfout.cc to take advantage of the prior
changes and significantly simplify the BTF implementation.  The changes
are nearly transparent, however some small but important improvements
are also made possible by the refactor, such as fixing PR113566.

Patch 5 adds a new option to perform pruning of the BTF information
before emission.  This is intended to be used for BPF programs which
often include kernel headers, and in many cases reduces the size of
the resulting BTF information by a factor of 10.

Patch 6 makes BTF pruning work with BPF CO-RE, and enables the pruning
by default in the BPF backend.

Tested on x86_64-linux-gnu, and on x86_64-linux-gnu host for
bpf-unknown-none target.

Also heavily tested with Linux kernel BPF selftests.
No known regressions.

David Faust (6):
  ctf, btf: restructure CTF/BTF emission
  opts: allow any combination of DWARF, CTF, BTF
  ctf: use pointers instead of IDs internally
  btf: refactor and simplify implementation
  btf: add -fprune-btf option
  bpf,btf: enable BTF pruning by default for BPF

 gcc/btfout.cc | 1645 ++---
 gcc/common.opt|4 +
 gcc/config/bpf/bpf.cc |5 +
 gcc/config/bpf/btfext-out.cc  |   12 +-
 gcc/config/bpf/core-builtins.cc   |   73 +-
 gcc/ctfc.cc   |  139 +-
 gcc/ctfc.h|   86 +-
 gcc/ctfout.cc |   19 +-
 gcc/doc/invoke.texi   |   23 +
 gcc/dwarf2ctf.cc  |  300 ++-
 gcc/dwarf2ctf.h   |2 +-
 gcc/dwarf2out.cc  |4 +-
 gcc/opts.cc   |   19 +-
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-1.c  |   25 +
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-2.c  |   33 +
 gcc/testsuite/gcc.dg/debug/btf/btf-prune-3.c  |   35 +
 .../gcc.dg/debug/btf/btf-variables-5.c|2 +-
 17 files changed, 1399 insertions(+), 1027 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-1.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-2.c
 create mode 100644 gcc/testsuite/gcc.dg/debug/btf/btf-prune-3.c

-- 
2.43.0



[PATCH 2/6] opts: allow any combination of DWARF, CTF, BTF

2024-05-01 Thread David Faust
Previously it was not supported to generate both CTF and BTF debug info
in the same compiler run, as both formats made incompatible changes to
the same internal data structures.

With the structural change in the prior patch, in particular the
guarantee that CTF will always be fully emitted before any BTF
translation occurs, there is no longer anything preventing generation
of both CTF and BTF at the same time.  This patch changes option parsing
to allow any combination of -gdwarf, -gctf, and -gbtf at the same time.

gcc/
* opts.cc (set_debug_level): Allow any combination of -gdwarf,
-gctf and -gbtf at the same time.
---
 gcc/opts.cc | 19 ++-
 1 file changed, 6 insertions(+), 13 deletions(-)

diff --git a/gcc/opts.cc b/gcc/opts.cc
index 600e0ea..0a00eb6e2da 100644
--- a/gcc/opts.cc
+++ b/gcc/opts.cc
@@ -3488,21 +3488,14 @@ set_debug_level (uint32_t dinfo, int extended, const 
char *arg,
 }
   else
 {
-  /* Make and retain the choice if both CTF and DWARF debug info are to
-be generated.  */
-  if (((dinfo == DWARF2_DEBUG) || (dinfo == CTF_DEBUG))
+  /* Any combination of DWARF, CTF and BTF is allowed together.  */
+  if (((dinfo == DWARF2_DEBUG) || (dinfo == CTF_DEBUG) || (dinfo == 
BTF_DEBUG))
  && ((opts->x_write_symbols == (DWARF2_DEBUG|CTF_DEBUG))
+ || (opts->x_write_symbols == (DWARF2_DEBUG|BTF_DEBUG))
+ || (opts->x_write_symbols == (CTF_DEBUG|BTF_DEBUG))
  || (opts->x_write_symbols == DWARF2_DEBUG)
- || (opts->x_write_symbols == CTF_DEBUG)))
-   {
- opts->x_write_symbols |= dinfo;
- opts_set->x_write_symbols |= dinfo;
-   }
-  /* However, CTF and BTF are not allowed together at this time.  */
-  else if (((dinfo == DWARF2_DEBUG) || (dinfo == BTF_DEBUG))
-  && ((opts->x_write_symbols == (DWARF2_DEBUG|BTF_DEBUG))
-  || (opts->x_write_symbols == DWARF2_DEBUG)
-  || (opts->x_write_symbols == BTF_DEBUG)))
+ || (opts->x_write_symbols == CTF_DEBUG)
+ || (opts->x_write_symbols == BTF_DEBUG)))
{
  opts->x_write_symbols |= dinfo;
  opts_set->x_write_symbols |= dinfo;
-- 
2.43.0



Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Jason Merrill wrote:

> On 5/1/24 08:54, Patrick Palka wrote:
> > On Thu, 2 May 2024, Nathaniel Shead wrote:
> > 
> > > On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:
> > > > On Wed, 1 May 2024, Nathaniel Shead wrote:
> > > > 
> > > > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > > > > 
> > > > > -- >8 --
> > > > > 
> > > > > When calling instantiate_pending_templates at end of parsing, any new
> > > > > functions that are instantiated from this point have their module
> > > > > purview set based on the current value of module_kind.
> > > > > 
> > > > > This is unideal, however, as the modules code will then treat these
> > > > > instantiations as reachable and cause large swathes of the GMF to be
> > > > > emitted into the module CMI, despite no code in the actual module
> > > > > purview referencing it.
> > > > > 
> > > > > This patch fixes this by also remembering the value of module_kind
> > > > > when
> > > > > the instantiation was deferred, and restoring it when doing this
> > > > > deferred instantiation.  That way newly instantiated declarations
> > > > > appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
> > > > > instantiation was required, meaning that GMF entities won't be counted
> > > > > as reachable unless referenced by an actually reachable entity.
> > > > > 
> > > > > Note that purviewness and attachment etc. is generally only determined
> > > > > by the base template: this is purely for determining whether a
> > > > > specialisation was declared in the module purview and hence whether it
> > > > > should be streamed out.  See the comment on
> > > > > 'set_instantiating_module'.
> > > > > 
> > > > >   PR c++/114630
> > > > >   PR c++/114795
> > > > > 
> > > > > gcc/cp/ChangeLog:
> > > > > 
> > > > >   * cp-tree.h (struct tinst_level): Add field for tracking
> > > > >   module_kind.
> > > > >   * pt.cc (push_tinst_level_loc): Cache module_kind in
> > > > > new_level.
> > > > >   (reopen_tinst_level): Restore module_kind from level.
> > > > >   (instantiate_pending_templates): Save and restore module_kind
> > > > > so
> > > > >   it isn't affected by reopen_tinst_level.
> > > > 
> > > > LGTM.  Another approach is to instantiate all so-far deferred
> > > > instantiations and vtables once we reach the start of the module
> > > > purview, but your approach is much cleaner.
> > > > 
> > > > Note that deferred instantiation can induce more deferred instantiation,
> > > > but your approach will do the right thing here (module_kind will be
> > > > inherited from the point of instantiation).
> > > > 
> > > > What if an instantiation is needed from both the GMF and the module
> > > > purview?  Then IIUC it'll be instantiated as if from the GMF, which
> > > > seems right to me.
> > > > 
> > > 
> > > Hm..., so I believe it'll be marked according to whichever instantiates
> > > it "first", so if e.g. deferred from GMF and then instantiated
> > > non-deferred from purview it'll be marked purview (and the deferred
> > > instantiation will be skipped as it's already instantiated).  This could
> > > mean it gets unnecessarily emitted if it only got instantiated because
> > > it got used in e.g. a non-inline function body, I suppose; but that's
> > > true in general actually, at the moment.
> > 
> > FWIW I think the most relevant situation where we need to instantiate
> > immediately and can't defer until EOF is during constexpr evaluation of
> > a variable initializer.  (We also immediately instantiate variable
> > template specializations, and function template specializations with
> > deduced return type, but in these cases we'd always instantiate from the
> > first use, i.e. from the GMF in this scenario.)
> > 
> > So I guess a testcase for this situation could be something like:
> > 
> >  module;
> >  template constexpr int f(T t) { return t; }
> >  template int f(int);
> > 
> >  export module foo;
> >  constexpr int w = f(0);
> >  // f ideally shouldn't be emitted in the CMI?
> 
> Does the explicit instantiation change that at all?  Either way it seams like
> f and f aren't decl-reachable from w if we determine that after constant
> evaluation.

Currently due to the bug in question we handle this as if the explicit
instantiation was performed from the module purview:

  module;
  template constexpr int f(T t) { return t; }

  export module foo;
  template int f(int);
  constexpr int w = f(0);

I think we do want to emit f in that case?



Re: [committed] [RISC-V] Improve floor, ceil & related operations for RISC-V

2024-05-01 Thread Jeff Law




On 5/1/24 12:44 PM, Patrick O'Neill wrote:

Hi Jeff,


It looks like this patch's gcc.target/riscv/round_64.c testcase doesn't 
pass when run with newlib.


It also introduced:

FAIL: gcc.target/riscv/rvv/autovec/unop/math-nearbyint-run-2.c execution 
test


on rv32gcv newlib/linux.


Precommit with a few targets: https://github.com/ewlu/gcc-precommit-ci/ 
issues/1454


Postcommit with all targets: https://github.com/patrick-rivos/gcc- 
postcommit-ci/issues/853


Untrimmed postcommit output: https://github.com/patrick-rivos/gcc- 
postcommit-ci/actions/runs/8899731577/job/24456991643#step:8:132

Thanks.  I'll dive in.

jeff



[pushed] c++: drop in-charge for dtors without vbases

2024-05-01 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

Constructors and destructors use the in-charge parameter to decide whether
they're responsible for recursing into virtual bases.  Historically all
destructors had this parameter in order to also distinguish the deleting
destructor.  But r151673 in GCC 4.5 changed the deleting destructor to just
call the complete destructor and then operator delete, making the in-charge
parameter no longer relevant for destructors in classes without virtual
bases.  Having it causes confusion in constexpr evaluation, which assumes
that clones will have the same parameters as the cloned 'tor.

gcc/cp/ChangeLog:

* cp-tree.h (base_ctor_identifier): Adjust comment.
* call.cc (in_charge_arg_for_name): Abort on deleting dtor.
* decl2.cc (maybe_retrofit_in_chrg): Don't add it for
destructors without vbases, either.
* constexpr.cc (cxx_eval_call_expression): Remove workaround.

gcc/testsuite/ChangeLog:

* g++.dg/debug/dwarf2/array-3.C: No more 'int' for in-chrg parm.
* g++.dg/debug/dwarf2/array-4.C: Likewise.
---
 gcc/cp/cp-tree.h|  3 +--
 gcc/cp/call.cc  |  4 +++-
 gcc/cp/constexpr.cc | 20 +++-
 gcc/cp/decl2.cc | 12 
 gcc/testsuite/g++.dg/debug/dwarf2/array-3.C |  6 +++---
 gcc/testsuite/g++.dg/debug/dwarf2/array-4.C |  2 +-
 6 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1938ada0268..5d1bd6ba493 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -289,8 +289,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 /* The name of a constructor that does not construct virtual base classes.  */
 #define base_ctor_identifier   
cp_global_trees[CPTI_BASE_CTOR_IDENTIFIER]
 /* The name of a destructor that takes an in-charge parameter to
-   decide whether or not to destroy virtual base classes and whether
-   or not to delete the object.  */
+   decide whether or not to destroy virtual base classes.  */
 #define dtor_identifier
cp_global_trees[CPTI_DTOR_IDENTIFIER]
 /* The name of a destructor that destroys virtual base classes.  */
 #define complete_dtor_identifier   
cp_global_trees[CPTI_COMPLETE_DTOR_IDENTIFIER]
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index dbdd7c29fe8..7c4ecf08c4b 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -11167,7 +11167,9 @@ in_charge_arg_for_name (tree name)
   if (name == complete_dtor_identifier)
return integer_two_node;
   else if (name == deleting_dtor_identifier)
-   return integer_three_node;
+   /* The deleting dtor should now be handled by
+  build_delete_destructor_body.  */
+   gcc_unreachable ();
   gcc_checking_assert (name == base_dtor_identifier);
 }
 
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 8078b31544d..50f799d7ff7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3243,19 +3243,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
  ctx->global->put_value (remapped, arg);
  remapped = DECL_CHAIN (remapped);
}
- for (; remapped; remapped = TREE_CHAIN (remapped))
-   if (DECL_NAME (remapped) == in_charge_identifier)
- {
-   /* FIXME destructors unnecessarily have in-charge parameters
-  even in classes without vbases, map it to 0 for now.  */
-   gcc_assert (!CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun)));
-   ctx->global->put_value (remapped, integer_zero_node);
- }
-   else
- {
-   gcc_assert (seen_error ());
-   *non_constant_p = true;
- }
+ if (remapped)
+   {
+ /* We shouldn't have any parms without args, but fail gracefully
+in error recovery.  */
+ gcc_checking_assert (seen_error ());
+ *non_constant_p = true;
+   }
  /* Add the RESULT_DECL to the values map, too.  */
  gcc_assert (!DECL_BY_REFERENCE (res));
  ctx->global->put_value (res, NULL_TREE);
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 806a2a4bc69..b8dc55b51d9 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -275,11 +275,8 @@ build_artificial_parm (tree fn, tree name, tree type)
   return parm;
 }
 
-/* Constructors for types with virtual baseclasses need an "in-charge" flag
-   saying whether this constructor is responsible for initialization of
-   virtual baseclasses or not.  All destructors also need this "in-charge"
-   flag, which additionally determines whether or not the destructor should
-   free the memory for the object.
+/* 'structors for types with virtual baseclasses need an "in-charge" flag
+   saying whether this function is responsible for virtual baseclasses or not.
 
This 

Re: [PATCH] c++: Implement C++26 P2573R2 - = delete("should have a reason"); [PR114458]

2024-05-01 Thread Jason Merrill

On 5/1/24 23:33, Jakub Jelinek wrote:


The following patch implements the C++26 P2573R2
= delete("should have a reason"); paper.
I've tried to avoid increasing compile time memory for it when it isn't
used (e.g. by adding a new lang_decl tree member), so the reason is
represented as STRING_CST in DECL_INITIAL (which normally is for
DECL_DELETED_FN error_mark_node) and to differentiate this delete("reason")
initializer from some bogus attempt to initialize a function with "reason"
using the RID_DELETE identifier as TREE_TYPE of the STRING_CST, as nothing
needs to care about the type of the reason.  If preferred it could
be say TREE_LIST with the reason STRING_CST and RID_DELETE identifier or
something similar instead, but that would need more compile time memory when
it is used.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?


Please add a comment about this representation to the definition of 
DECL_DELETED_FN.  OK with that change.



2024-05-01  Jakub Jelinek  

PR c++/114458
gcc/c-family/
* c-cppbuiltin.cc (c_cpp_builtins): Predefine
__cpp_deleted_function=202403L for C++26.
gcc/cp/ChangeLog
* parser.cc (cp_parser_pure_specifier): Implement C++26 P2573R2
- = delete("should have a reason");.  Parse deleted-function-body.
* decl.cc (duplicate_decls): Copy DECL_INITIAL from DECL_DELETED_FN
olddecl to newdecl if it is a STRING_CST.
(cp_finish_decl): Handle deleted init with a reason.
* decl2.cc: Include "escaped_string.h".
(grokfield): Handle deleted init with a reason.
(mark_used): Emit DECL_DELETED_FN reason in the message if any.
gcc/testsuite/
* g++.dg/cpp26/feat-cxx26.C (__cpp_deleted_function): Add test.
* g++.dg/cpp26/delete-reason1.C: New test.
* g++.dg/cpp26/delete-reason2.C: New test.
* g++.dg/parse/error65.C (f1): Adjust expected diagnostics.

--- gcc/c-family/c-cppbuiltin.cc.jj 2024-04-30 08:57:07.359039013 +0200
+++ gcc/c-family/c-cppbuiltin.cc2024-04-30 19:16:45.069542205 +0200
@@ -1092,6 +1092,7 @@ c_cpp_builtins (cpp_reader *pfile)
  cpp_define (pfile, "__cpp_static_assert=202306L");
  cpp_define (pfile, "__cpp_placeholder_variables=202306L");
  cpp_define (pfile, "__cpp_structured_bindings=202403L");
+ cpp_define (pfile, "__cpp_deleted_function=202403L");
}
if (flag_concepts)
  {
--- gcc/cp/parser.cc.jj 2024-04-30 08:57:07.349039147 +0200
+++ gcc/cp/parser.cc2024-04-30 16:47:01.427952875 +0200
@@ -28573,6 +28573,27 @@ cp_parser_pure_specifier (cp_parser* par
|| token->keyword == RID_DELETE)
  {
maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+   {
+ if (cxx_dialect >= cxx11 && cxx_dialect < cxx26)
+   pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+OPT_Wc__26_extensions,
+"% reason only available with "
+"%<-std=c++2c%> or %<-std=gnu++2c%>");
+
+ /* Consume the `('.  */
+ matching_parens parens;
+ parens.consume_open (parser);
+ tree reason = cp_parser_unevaluated_string_literal (parser);
+ /* Consume the `)'.  */
+ parens.require_close (parser);
+ if (TREE_CODE (reason) == STRING_CST)
+   {
+ TREE_TYPE (reason) = token->u.value;
+ return reason;
+   }
+   }
+
return token->u.value;
  }
  
--- gcc/cp/decl.cc.jj	2024-04-30 08:55:26.172389593 +0200

+++ gcc/cp/decl.cc  2024-04-30 19:01:32.316543498 +0200
@@ -2410,6 +2410,10 @@ duplicate_decls (tree newdecl, tree oldd
"previous declaration of %qD", olddecl);
}
  DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl);
+ if (DECL_DELETED_FN (olddecl)
+ && DECL_INITIAL (olddecl)
+ && TREE_CODE (DECL_INITIAL (olddecl)) == STRING_CST)
+   DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
}
  }
  
@@ -8587,17 +8591,20 @@ cp_finish_decl (tree decl, tree init, bo

if (init && TREE_CODE (decl) == FUNCTION_DECL)
  {
tree clone;
-  if (init == ridpointers[(int)RID_DELETE])
+  if (init == ridpointers[(int)RID_DELETE]
+ || (TREE_CODE (init) == STRING_CST
+ && TREE_TYPE (init) == ridpointers[(int)RID_DELETE]))
{
  /* FIXME check this is 1st decl.  */
  DECL_DELETED_FN (decl) = 1;
  DECL_DECLARED_INLINE_P (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
+ DECL_INITIAL (decl)
+   = TREE_CODE (init) == STRING_CST ? init : error_mark_node;
  FOR_EACH_CLONE (clone, decl)
{
  DECL_DELETED_FN (clone) = 1;
  DECL_DECLARED_INLINE_P (clone) = 1;
- DECL_INITIAL (clone) = error_mark_node;
+ DECL_INITIAL (clone) 

[committed] [RISC-V] Trivial pattern cleanup

2024-05-01 Thread Jeff Law


As I was reviewing and cleaning up some internal work, I noticed a 
particular idiom being used elsewhere in the RISC-V backend.


Specifically the use of explicit subregs when an adjustment to the 
match_operand would be sufficient.


Let's take this example from the and-not splitter:


 (define_split
   [(set (match_operand:X 0 "register_operand")
(and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand")
  (subreg:QI (match_operand:X 2 
"register_operand") 0)))
   (const_int 1)))]



Note the explicit subreg.  We can instead use a match_operand with 
QImode.  This ever-so-slightly simplifies the machine description.


It also means that if we have a QImode object lying around (say we 
loaded it from memory in QImode), we can use it directly rather than 
first extending it to X, then truncing to QI.  So we end up with simpler 
RTL and in rare cases improve the code we generate.


When used in a define_split or define_insn_and_split we need to make 
suitable adjustments to the split RTL.


Bootstrapped a while back.  Just re-tested with a cross.

Pushing to the trunk & coordination branch.

jeffcommit 76ca6e1f8b1524b82a871ce29cf58c79e5e77e2b
Author: Jeff Law 
Date:   Wed May 1 12:43:37 2024 -0600

[committed] [RISC-V] Trivial pattern cleanup

As I was reviewing and cleaning up some internal work, I noticed a 
particular
idiom being used elsewhere in the RISC-V backend.

Specifically the use of explicit subregs when an adjustment to the
match_operand would be sufficient.

Let's take this example from the and-not splitter:

>  (define_split
>[(set (match_operand:X 0 "register_operand")
> (and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand")
>   (subreg:QI (match_operand:X 2 
"register_operand") 0)))
>(const_int 1)))]

Note the explicit subreg.  We can instead use a match_operand with QImode.
This ever-so-slightly simplifies the machine description.

It also means that if we have a QImode object lying around (say we loaded it
from memory in QImode), we can use it directly rather than first extending 
it
to X, then truncing to QI.  So we end up with simpler RTL and in rare cases
improve the code we generate.

When used in a define_split or define_insn_and_split we need to make 
suitable
adjustments to the split RTL.

Bootstrapped a while back.  Just re-tested with a cross.

gcc/
* config/riscv/bitmanip.md (splitter to use w-form division): Remove
explicit subregs.
(zero extended bitfield extraction): Similarly.
* config/riscv/thead.md (*th_memidx_operand): Similarly.

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index ccda25c01c1..ad3ad758959 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -50,11 +50,11 @@ (define_split
(sign_extend:DI (div:SI (plus:SI (ashift:SI (subreg:SI 
(match_operand:DI 1 "register_operand") 0)
(match_operand:QI 2 
"imm123_operand"))
 (subreg:SI (match_operand:DI 3 
"register_operand") 0))
-   (subreg:SI (match_operand:DI 4 
"register_operand") 0
+   (match_operand:SI 4 "register_operand"
(clobber (match_operand:DI 5 "register_operand"))]
   "TARGET_64BIT && TARGET_ZBA"
[(set (match_dup 5) (plus:DI (ashift:DI (match_dup 1) (match_dup 2)) 
(match_dup 3)))
-(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) 
(subreg:SI (match_dup 4) 0])
+(set (match_dup 0) (sign_extend:DI (div:SI (subreg:SI (match_dup 5) 0) 
(match_dup 4])
 
 ; Zba does not provide W-forms of sh[123]add(.uw)?, which leads to an
 ; interesting irregularity: we can generate a signed 32-bit result
@@ -722,13 +722,14 @@ (define_insn "*bexti"
 (define_split
   [(set (match_operand:X 0 "register_operand")
(and:X (not:X (lshiftrt:X (match_operand:X 1 "register_operand")
- (subreg:QI (match_operand:X 2 
"register_operand") 0)))
+ (match_operand:QI 2 "register_operand")))
   (const_int 1)))]
   "TARGET_ZBS"
   [(set (match_dup 0) (zero_extract:X (match_dup 1)
  (const_int 1)
  (match_dup 2)))
-   (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))])
+   (set (match_dup 0) (xor:X (match_dup 0) (const_int 1)))]
+  "operands[2] = gen_lowpart (mode, operands[2]);")
 
 ;; We can create a polarity-reversed mask (i.e. bit N -> { set = 0, clear = -1 
})
 ;; using a bext(i) followed by an addi instruction.
diff --git a/gcc/config/riscv/thead.md b/gcc/config/riscv/thead.md
index 5c7d4beb1b6..a47fe6f28b8 100644
--- 

Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Jason Merrill

On 5/1/24 08:54, Patrick Palka wrote:

On Thu, 2 May 2024, Nathaniel Shead wrote:


On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:

On Wed, 1 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When calling instantiate_pending_templates at end of parsing, any new
functions that are instantiated from this point have their module
purview set based on the current value of module_kind.

This is unideal, however, as the modules code will then treat these
instantiations as reachable and cause large swathes of the GMF to be
emitted into the module CMI, despite no code in the actual module
purview referencing it.

This patch fixes this by also remembering the value of module_kind when
the instantiation was deferred, and restoring it when doing this
deferred instantiation.  That way newly instantiated declarations
appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
instantiation was required, meaning that GMF entities won't be counted
as reachable unless referenced by an actually reachable entity.

Note that purviewness and attachment etc. is generally only determined
by the base template: this is purely for determining whether a
specialisation was declared in the module purview and hence whether it
should be streamed out.  See the comment on 'set_instantiating_module'.

PR c++/114630
PR c++/114795

gcc/cp/ChangeLog:

* cp-tree.h (struct tinst_level): Add field for tracking
module_kind.
* pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
(reopen_tinst_level): Restore module_kind from level.
(instantiate_pending_templates): Save and restore module_kind so
it isn't affected by reopen_tinst_level.


LGTM.  Another approach is to instantiate all so-far deferred
instantiations and vtables once we reach the start of the module
purview, but your approach is much cleaner.

Note that deferred instantiation can induce more deferred instantiation,
but your approach will do the right thing here (module_kind will be
inherited from the point of instantiation).

What if an instantiation is needed from both the GMF and the module
purview?  Then IIUC it'll be instantiated as if from the GMF, which
seems right to me.



Hm..., so I believe it'll be marked according to whichever instantiates
it "first", so if e.g. deferred from GMF and then instantiated
non-deferred from purview it'll be marked purview (and the deferred
instantiation will be skipped as it's already instantiated).  This could
mean it gets unnecessarily emitted if it only got instantiated because
it got used in e.g. a non-inline function body, I suppose; but that's
true in general actually, at the moment.


FWIW I think the most relevant situation where we need to instantiate
immediately and can't defer until EOF is during constexpr evaluation of
a variable initializer.  (We also immediately instantiate variable
template specializations, and function template specializations with
deduced return type, but in these cases we'd always instantiate from the
first use, i.e. from the GMF in this scenario.)

So I guess a testcase for this situation could be something like:

 module;
 template constexpr int f(T t) { return t; }
 template int f(int);

 export module foo;
 constexpr int w = f(0);
 // f ideally shouldn't be emitted in the CMI?


Does the explicit instantiation change that at all?  Either way it seams 
like f and f aren't decl-reachable from w if we determine that 
after constant evaluation.


Jason



Re: [committed] [RISC-V] Improve floor, ceil & related operations for RISC-V

2024-05-01 Thread Patrick O'Neill

Hi Jeff,


It looks like this patch's gcc.target/riscv/round_64.c testcase doesn't 
pass when run with newlib.


It also introduced:

FAIL: gcc.target/riscv/rvv/autovec/unop/math-nearbyint-run-2.c execution 
test


on rv32gcv newlib/linux.


Precommit with a few targets: 
https://github.com/ewlu/gcc-precommit-ci/issues/1454


Postcommit with all targets: 
https://github.com/patrick-rivos/gcc-postcommit-ci/issues/853


Untrimmed postcommit output: 
https://github.com/patrick-rivos/gcc-postcommit-ci/actions/runs/8899731577/job/24456991643#step:8:132



Thanks,

Patrick


On 4/30/24 08:46, Jeff Law wrote:

This is almost exclusively Jivan's work.  His original post:



https://www.mail-archive.com/gcc-patches@gcc.gnu.org/msg336483.html





This patch is primarily meant to improve the code we generate for FP 
rounding such as ceil/floor.  It also addresses some unnecessary sign 
extensions in the same areas.


RISC-V's FP conversions have a bit of undesirable behavior that make 
them non-suitable as-is for ceil/floor and other related functions. 
These deficiencies are addressed in the Zfa extension, but there's no 
reason not to pick up a nice improvement when we can.


Basically we can still use the basic FP conversions for floor/ceil and 
friends when we don't care about inexact exceptions by checking for 
the special cases first, then emitting the conversion when the special 
cases don't apply.  That's still much faster than calling into glibc.


The redundant sign extensions are eliminated using the same trick 
Jivan added last year, just in a few more places ;-)


This eliminates roughly 10% of the dynamic instruction count for 
imagick.  But more importantly it's about a 17% performance 
improvement for that workload within spec.


This has been bootstrapped as well as regression tested in a cross 
environment.  It's also successfully built & run specint/specfp 
correctly.


Pushing to the trunk and the coordination branch momentarily.


Jeff


[committed] [RISC-V] Fix detection of store pair fusion cases

2024-05-01 Thread Jeff Law


We've got the ability to count the number of store pair fusions 
happening in the front-end of the pipeline.  When comparing some code 
from last year vs the current trunk we saw a fairly dramatic drop.


The problem is the store pair fusion detection code was actively harmful 
due to a minor bug in checking offsets.   So instead of pairing up 8 
byte stores such as sp+0 with sp+8, it tried to pair up sp+8 and sp+16.


Given uarch sensitivity I didn't try to pull together a testcase.  But 
we could certainly see the undesirable behavior in benchmarks as 
simplistic as dhrystone up through spec2017.


Anyway, bootstrapped a while back.  Also verified through our 
performance counters that store pair fusion rates are back up. 
Regression tested with crosses a few minutes ago.




Pushing to the trunk and coordination branch.

jeffcommit fad93e7617ce1aafb006983a71b6edc9ae1eb2d1
Author: Jeff Law 
Date:   Wed May 1 11:28:41 2024 -0600

[committed] [RISC-V] Fix detection of store pair fusion cases

We've got the ability to count the number of store pair fusions happening in
the front-end of the pipeline.  When comparing some code from last year vs 
the
current trunk we saw a fairly dramatic drop.

The problem is the store pair fusion detection code was actively harmful 
due to
a minor bug in checking offsets.   So instead of pairing up 8 byte stores 
such
as sp+0 with sp+8, it tried to pair up sp+8 and sp+16.

Given uarch sensitivity I didn't try to pull together a testcase.  But we 
could
certainly see the undesirable behavior in benchmarks as simplistic as 
dhrystone
up through spec2017.

Anyway, bootstrapped a while back.  Also verified through our performance
counters that store pair fusion rates are back up.  Regression tested with
crosses a few minutes ago.

gcc/
* config/riscv/riscv.cc (riscv_macro_fusion_pair_p): Break out
tests for easier debugging in store pair fusion case.  Fix offset
check in same.

diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 0f62b295b96..24d1ead3902 100644
--- a/gcc/config/riscv/riscv.cc
+++ b/gcc/config/riscv/riscv.cc
@@ -8874,26 +8874,43 @@ riscv_macro_fusion_pair_p (rtx_insn *prev, rtx_insn 
*curr)
  extract_base_offset_in_addr (SET_DEST (prev_set), _prev, 
_prev);
  extract_base_offset_in_addr (SET_DEST (curr_set), _curr, 
_curr);
 
- /* The two stores must be contained within opposite halves of the same
-16 byte aligned block of memory.  We know that the stack pointer 
and
-the frame pointer have suitable alignment.  So we just need to 
check
-the offsets of the two stores for suitable alignment.
-
-Originally the thought was to check MEM_ALIGN, but that was 
reporting
-incorrect alignments, even for SP/FP accesses, so we gave up on 
that
-approach.  */
- if (base_prev != NULL_RTX
- && base_curr != NULL_RTX
- && REG_P (base_prev)
- && REG_P (base_curr)
- && REGNO (base_prev) == REGNO (base_curr)
- && (REGNO (base_prev) == STACK_POINTER_REGNUM
- || REGNO (base_prev) == HARD_FRAME_POINTER_REGNUM)
- && ((INTVAL (offset_prev) == INTVAL (offset_curr) + 8
-  && (INTVAL (offset_prev) % 16) == 0)
- || ((INTVAL (offset_curr) == INTVAL (offset_prev) + 8)
- && (INTVAL (offset_curr) % 16) == 0)))
-   return true;
+ /* Fail if we did not find both bases.  */
+ if (base_prev == NULL_RTX || base_curr == NULL_RTX)
+   return false;
+
+ /* Fail if either base is not a register.  */
+ if (!REG_P (base_prev) || !REG_P (base_curr))
+   return false;
+
+ /* Fail if the bases are not the same register.  */
+ if (REGNO (base_prev) != REGNO (base_curr))
+   return false;
+
+ /* Originally the thought was to check MEM_ALIGN, but that was
+reporting incorrect alignments, even for SP/FP accesses, so we
+gave up on that approach.  Instead just check for stack/hfp
+which we know are aligned.  */
+ if (REGNO (base_prev) != STACK_POINTER_REGNUM
+ && REGNO (base_prev) != HARD_FRAME_POINTER_REGNUM)
+   return false;
+
+ /* The two stores must be contained within opposite halves of the
+same 16 byte aligned block of memory.  We know that the stack
+pointer and the frame pointer have suitable alignment.  So we
+just need to check the offsets of the two stores for suitable
+alignment.  */
+ /* Get the smaller offset into OFFSET_PREV.  */
+ if (INTVAL (offset_prev) > INTVAL (offset_curr))
+   std::swap (offset_prev, offset_curr);
+
+ /* If the smaller offset (OFFSET_PREV) is not 16 byte aligned,
+  

RE: [PATCH v3] Internal-fn: Introduce new internal function SAT_ADD

2024-05-01 Thread Tamar Christina
Hi,

> From: Pan Li 
> 
> Update in v3:
> * Rebase upstream for conflict.
> 
> Update in v2:
> * Fix one failure for x86 bootstrap.
> 
> Original log:
> 
> This patch would like to add the middle-end presentation for the
> saturation add.  Aka set the result of add to the max when overflow.
> It will take the pattern similar as below.
> 
> SAT_ADD (x, y) => (x + y) | (-(TYPE)((TYPE)(x + y) < x))
> 
> Take uint8_t as example, we will have:
> 
> * SAT_ADD (1, 254)   => 255.
> * SAT_ADD (1, 255)   => 255.
> * SAT_ADD (2, 255)   => 255.
> * SAT_ADD (255, 255) => 255.
> 
> The patch also implement the SAT_ADD in the riscv backend as
> the sample for both the scalar and vector.  Given below example:
> 
> uint64_t sat_add_u64 (uint64_t x, uint64_t y)
> {
>   return (x + y) | (- (uint64_t)((uint64_t)(x + y) < x));
> }
> 
> Before this patch:
> uint64_t sat_add_uint64_t (uint64_t x, uint64_t y)
> {
>   long unsigned int _1;
>   _Bool _2;
>   long unsigned int _3;
>   long unsigned int _4;
>   uint64_t _7;
>   long unsigned int _10;
>   __complex__ long unsigned int _11;
> 
> ;;   basic block 2, loop depth 0
> ;;pred:   ENTRY
>   _11 = .ADD_OVERFLOW (x_5(D), y_6(D));
>   _1 = REALPART_EXPR <_11>;
>   _10 = IMAGPART_EXPR <_11>;
>   _2 = _10 != 0;
>   _3 = (long unsigned int) _2;
>   _4 = -_3;
>   _7 = _1 | _4;
>   return _7;
> ;;succ:   EXIT
> 
> }
> 
> After this patch:
> uint64_t sat_add_uint64_t (uint64_t x, uint64_t y)
> {
>   uint64_t _7;
> 
> ;;   basic block 2, loop depth 0
> ;;pred:   ENTRY
>   _7 = .SAT_ADD (x_5(D), y_6(D)); [tail call]
>   return _7;
> ;;succ:   EXIT
> }
> 
> For vectorize, we leverage the existing vect pattern recog to find
> the pattern similar to scalar and let the vectorizer to perform
> the rest part for standard name usadd3 in vector mode.
> The riscv vector backend have insn "Vector Single-Width Saturating
> Add and Subtract" which can be leveraged when expand the usadd3
> in vector mode.  For example:
> 
> void vec_sat_add_u64 (uint64_t *out, uint64_t *x, uint64_t *y, unsigned n)
> {
>   unsigned i;
> 
>   for (i = 0; i < n; i++)
> out[i] = (x[i] + y[i]) | (- (uint64_t)((uint64_t)(x[i] + y[i]) < x[i]));
> }
> 
> Before this patch:
> void vec_sat_add_u64 (uint64_t *out, uint64_t *x, uint64_t *y, unsigned n)
> {
>   ...
>   _80 = .SELECT_VL (ivtmp_78, POLY_INT_CST [2, 2]);
>   ivtmp_58 = _80 * 8;
>   vect__4.7_61 = .MASK_LEN_LOAD (vectp_x.5_59, 64B, { -1, ... }, _80, 0);
>   vect__6.10_65 = .MASK_LEN_LOAD (vectp_y.8_63, 64B, { -1, ... }, _80, 0);
>   vect__7.11_66 = vect__4.7_61 + vect__6.10_65;
>   mask__8.12_67 = vect__4.7_61 > vect__7.11_66;
>   vect__12.15_72 = .VCOND_MASK (mask__8.12_67, { 18446744073709551615,
> ... }, vect__7.11_66);
>   .MASK_LEN_STORE (vectp_out.16_74, 64B, { -1, ... }, _80, 0, vect__12.15_72);
>   vectp_x.5_60 = vectp_x.5_59 + ivtmp_58;
>   vectp_y.8_64 = vectp_y.8_63 + ivtmp_58;
>   vectp_out.16_75 = vectp_out.16_74 + ivtmp_58;
>   ivtmp_79 = ivtmp_78 - _80;
>   ...
> }
> 
> vec_sat_add_u64:
>   ...
>   vsetvli a5,a3,e64,m1,ta,ma
>   vle64.v v0,0(a1)
>   vle64.v v1,0(a2)
>   sllia4,a5,3
>   sub a3,a3,a5
>   add a1,a1,a4
>   add a2,a2,a4
>   vadd.vv v1,v0,v1
>   vmsgtu.vv   v0,v0,v1
>   vmerge.vim  v1,v1,-1,v0
>   vse64.v v1,0(a0)
>   ...
> 
> After this patch:
> void vec_sat_add_u64 (uint64_t *out, uint64_t *x, uint64_t *y, unsigned n)
> {
>   ...
>   _62 = .SELECT_VL (ivtmp_60, POLY_INT_CST [2, 2]);
>   ivtmp_46 = _62 * 8;
>   vect__4.7_49 = .MASK_LEN_LOAD (vectp_x.5_47, 64B, { -1, ... }, _62, 0);
>   vect__6.10_53 = .MASK_LEN_LOAD (vectp_y.8_51, 64B, { -1, ... }, _62, 0);
>   vect__12.11_54 = .SAT_ADD (vect__4.7_49, vect__6.10_53);
>   .MASK_LEN_STORE (vectp_out.12_56, 64B, { -1, ... }, _62, 0, vect__12.11_54);
>   ...
> }
> 
> vec_sat_add_u64:
>   ...
>   vsetvli a5,a3,e64,m1,ta,ma
>   vle64.v v1,0(a1)
>   vle64.v v2,0(a2)
>   sllia4,a5,3
>   sub a3,a3,a5
>   add a1,a1,a4
>   add a2,a2,a4
>   vsaddu.vv   v1,v1,v2
>   vse64.v v1,0(a0)
>   ...
> 
> To limit the patch size for review, only unsigned version of
> usadd3 are involved here. The signed version will be covered
> in the underlying patch(es).
> 
> The below test suites are passed for this patch.
> * The riscv fully regression tests.
> * The aarch64 fully regression tests.
> * The x86 bootstrap tests.
> * The x86 fully regression tests.
> 
>   PR target/51492
>   PR target/112600
> 
> gcc/ChangeLog:
> 
>   * config/riscv/autovec.md (usadd3): New pattern expand
>   for unsigned SAT_ADD vector.
>   * config/riscv/riscv-protos.h (riscv_expand_usadd): New func
>   decl to expand usadd3 pattern.
>   (expand_vec_usadd): Ditto but for vector.
>   * config/riscv/riscv-v.cc (emit_vec_saddu): New func impl to
>   emit the vsadd insn.
>   (expand_vec_usadd): New func impl to expand usadd3 for
>   vector.
>   * config/riscv/riscv.cc (riscv_expand_usadd): New func impl
>   to 

[PATCH v5 4/4] Update the C/C++ FEs routine

2024-05-01 Thread Qing Zhao
"add_flexible_array_elts_to_size" C++ FE routine "layout_var_decl"  to handle
 the cases when the DECL is union.

Add testing cases to test the _bos for flexible array members in unions
or alone in structures.

gcc/c/ChangeLog:

* c-decl.cc (add_flexible_array_elts_to_size): Handle the cases
when the DECL is union.

gcc/cp/ChangeLog:

* decl.cc (layout_var_decl): Handle the cases when the DECL is
union with a flexible array member initializer.

gcc/testsuite/ChangeLog:

* c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test.
* c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.
---
 gcc/c/c-decl.cc   | 29 ++--
 gcc/cp/decl.cc| 32 +++--
 .../fam-in-union-alone-in-struct-bos-1.c  | 66 +++
 .../fam-in-union-alone-in-struct-bos.c| 45 +
 4 files changed, 159 insertions(+), 13 deletions(-)
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 947f3cd589eb..5d571621d915 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5337,8 +5337,9 @@ zero_length_array_type_p (const_tree type)
 }
 
 /* INIT is a constructor that forms DECL's initializer.  If the final
-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
+   element initializes a flexible array field, adjust the size of the
+   DECL with the initializer based on whether the DECL is a union or
+   a structure.  */
 
 static void
 add_flexible_array_elts_to_size (tree decl, tree init)
@@ -5353,10 +5354,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
   if (flexible_array_member_type_p (type))
 {
   complete_array_type (, elt, false);
-  DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-  DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+  /* For a structure, add the size of the initializer to the DECL's
+size.  */
+  if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
+  /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+  else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
 }
 }
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9a91c6f80da1..78e21b05296c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6555,8 +6555,9 @@ layout_var_decl (tree decl)
}
 }
 
-  /* If the final element initializes a flexible array field, add the size of
- that initializer to DECL's size.  */
+  /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure.  */
   if (type != error_mark_node
   && DECL_INITIAL (decl)
   && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6577,11 +6578,28 @@ layout_var_decl (tree decl)
  && TREE_CODE (vtype) == ARRAY_TYPE
  && COMPLETE_TYPE_P (vtype))
{
- DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
- DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
- TYPE_SIZE_UNIT (vtype));
+ /* For a structure, add the size of the initializer to the DECL's
+size.  */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+   }
+ /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+ else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+

[PATCH v5 3/4] Add testing cases for flexible array members in unions and alone in structures.

2024-05-01 Thread Qing Zhao
gcc/testsuite/ChangeLog:

* c-c++-common/fam-in-union-alone-in-struct-1.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-2.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-3.c: New testcase.
---
 .../fam-in-union-alone-in-struct-1.c  | 52 +++
 .../fam-in-union-alone-in-struct-2.c  | 51 ++
 .../fam-in-union-alone-in-struct-3.c  | 36 +
 3 files changed, 139 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c

diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
new file mode 100644
index ..7d4721aa95ac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
@@ -0,0 +1,52 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do run} */
+/* { dg-options "-Wpedantic" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-1 } */
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+struct only_fam {
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+int main ()
+{
+  if (sizeof (union with_fam_1) != sizeof (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_2) != __alignof__ (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_3) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam_2) != sizeof (int))
+__builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
new file mode 100644
index ..3743f9e7dac5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
@@ -0,0 +1,51 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures: initialization  */
+/* { dg-do run} */
+/* { dg-options "-O2" } */
+
+union with_fam_1 {
+  int a;
+  int b[]; 
+} with_fam_1_v = {.b = {1, 2, 3, 4}};
+
+union with_fam_2 {
+  int a;
+  char b[];  
+} with_fam_2_v = {.a = 0x1f2f3f4f};
+
+union with_fam_3 {
+  char a[];  
+  int b[];  
+} with_fam_3_v = {.b = {0x1f2f3f4f, 0x5f6f7f7f}};
+
+struct only_fam {
+  int b[]; 
+} only_fam_v = {{7, 11}};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[]; 
+} only_fam_2_v = {{7, 11}};
+
+int main ()
+{
+  if (with_fam_1_v.b[3] != 4
+  || with_fam_1_v.b[0] != 1)
+__builtin_abort ();
+  if (with_fam_2_v.b[3] != 0x1f
+  || with_fam_2_v.b[0] != 0x4f)
+__builtin_abort ();
+  if (with_fam_3_v.a[0] != 0x4f
+  || with_fam_3_v.a[7] != 0x5f)
+__builtin_abort ();
+  if (only_fam_v.b[0] != 7
+  || only_fam_v.b[1] != 11)
+__builtin_abort ();
+  if (only_fam_2_v.b[0] != 7
+  || only_fam_2_v.b[1] != 11)
+__builtin_abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
new file mode 100644
index ..dd36fa01306d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
@@ -0,0 +1,36 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+  /* { dg-error "in an otherwise empty" "" { target c++ } .-1 } */
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};

[PATCH v5 2/4] C and C++ FE changes

2024-05-01 Thread Qing Zhao
 to support flexible array members
 in unions and alone in structures. Adjust testcases for flexible array member
 in union and alone in structure extension.

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Change errors to pedwarns for the cases
flexible array members in union or alone in structures.

gcc/cp/ChangeLog:

* class.cc (diagnose_flexarrays): Change error to pdewarn for the case
flexible array members alone in structures.
* decl.cc (grokdeclarator): Change error to pdewarn for the case
flexible array members in unions.

gcc/ChangeLog:

* stor-layout.cc (place_union_field): Use zero sizes for flexible array
member fields.

gcc/testsuite/ChangeLog:

* c-c++-common/builtin-clear-padding-3.c: Adjust testcase.
* g++.dg/ext/flexary12.C: Likewise.
* g++.dg/ext/flexary19.C: Likewise.
* g++.dg/ext/flexary2.C: Likewise.
* g++.dg/ext/flexary3.C: Likewise.
* g++.dg/ext/flexary36.C: Likewise.
* g++.dg/ext/flexary4.C: Likewise.
* g++.dg/ext/flexary5.C: Likewise.
* g++.dg/ext/flexary8.C: Likewise.
* g++.dg/torture/pr64280.C: Likewise.
* gcc.dg/20050620-1.c: Likewise.
* gcc.dg/940510-1.c: Likewise.
---
 gcc/c/c-decl.cc   | 16 ++
 gcc/cp/class.cc   | 11 ++--
 gcc/cp/decl.cc|  7 ++-
 gcc/stor-layout.cc|  9 +++-
 .../c-c++-common/builtin-clear-padding-3.c| 10 ++--
 gcc/testsuite/g++.dg/ext/flexary12.C  |  6 +--
 gcc/testsuite/g++.dg/ext/flexary19.C  | 42 +++
 gcc/testsuite/g++.dg/ext/flexary2.C   |  2 +-
 gcc/testsuite/g++.dg/ext/flexary3.C   |  2 +-
 gcc/testsuite/g++.dg/ext/flexary36.C  |  2 +-
 gcc/testsuite/g++.dg/ext/flexary4.C   | 54 +--
 gcc/testsuite/g++.dg/ext/flexary5.C   |  4 +-
 gcc/testsuite/g++.dg/ext/flexary8.C   |  8 +--
 gcc/testsuite/g++.dg/torture/pr64280.C|  2 +-
 gcc/testsuite/gcc.dg/20050620-1.c |  2 +-
 gcc/testsuite/gcc.dg/940510-1.c   |  4 +-
 16 files changed, 91 insertions(+), 90 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 345090dae38b..947f3cd589eb 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9471,11 +9471,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   if (flexible_array_member_type_p (TREE_TYPE (x)))
{
  if (TREE_CODE (t) == UNION_TYPE)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in union");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in union is a GCC extension");
  else if (!is_last_field)
{
  error_at (DECL_SOURCE_LOCATION (x),
@@ -9483,12 +9480,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
  TREE_TYPE (x) = error_mark_node;
}
  else if (!saw_named_field)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in a struct with no named "
-   "members");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in a struct with no named "
+"members is a GCC extension");
}
 
   if (pedantic && TREE_CODE (t) == RECORD_TYPE
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 5f258729940b..0c8afb72550f 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -7624,6 +7624,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   bool diagd = false;
 
   const char *msg = 0;
+  const char *msg_fam = 0;
 
   if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
 {
@@ -7649,15 +7650,19 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   if (fmem->after[0])
msg = G_("flexible array member %qD not at end of %q#T");
   else if (!fmem->first)
-   msg = G_("flexible array member %qD in an otherwise empty %q#T");
+   msg_fam = G_("flexible array member %qD in an otherwise"
+" empty %q#T is a GCC extension");
 
-  if (msg)
+  if (msg || msg_fam)
{
  location_t loc = DECL_SOURCE_LOCATION (fmem->array);
  diagd = true;
 
  auto_diagnostic_group d;
- error_at (loc, msg, fmem->array, t);
+ if (msg)
+   error_at (loc, msg, fmem->array, t);
+ else
+   pedwarn (loc, OPT_Wpedantic, msg_fam, fmem->array, t);
 
  /* In the unlikely event that the member following the flexible
 array member is declared in a different class, or the member
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 

[PATCH v5 1/4] Allow flexible array members in unions and alone in structures [PR53548]

2024-05-01 Thread Qing Zhao
The request for GCC to accept that the C99 flexible array member can be
in a union or alone in a structure has been made a long time ago around 2012
for supporting several practical cases including glibc.

A GCC PR has been opened for such request at that time:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53548

However, this PR was closed as WONTFIX around 2015 due to the following reason:

"there is an existing extension that makes the requested functionality possible"
i.e GCC fully supported that the zero-length array can be in a union or alone
in a structure for a long time. (though I didn't see any official documentation
on such extension)

It's reasonable to close PR53548 at that time since zero-length array extension
can be used for such purpose.

However, since GCC13, in order to improve the C/C++ security, we introduced
-fstrict-flex-arrays=n to gradually eliminate the "fake flexible array"
usages from C/C++ source code. As a result, zero-length arrays eventually
will be replaced by C99 flexiable array member completely.

Therefore, GCC needs to explicitly allow such extensions directly for C99
flexible arrays, since flexable array member in unions or alone in structs
are common code patterns in active use by the Linux kernel (and other projects).

For example, these do not error by default with GCC:

union one {
  int a;
  int b[0];
};

union two {
  int a;
  struct {
struct { } __empty;
int b[];
  };
};

But these do:

union three {
  int a;
  int b[];
};

struct four {
  int b[];
}

Clang has supported such extensions since March, 2024
https://github.com/llvm/llvm-project/pull/84428

GCC should also support such extensions. This will allow for
a seamless transition for code bases away from zero-length arrays without
losing existing code patterns.

gcc/ChangeLog:

* doc/extend.texi: Add documentation for Flexible Array Members in
Unions and Flexible Array Members alone in Structures.
---
 gcc/doc/extend.texi | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7b54a241a7bf..94a77d7ef39c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -42,6 +42,8 @@ extensions, accepted by GCC in C90 mode and in C++.
 * Named Address Spaces::Named address spaces.
 * Zero Length:: Zero-length arrays.
 * Empty Structures::Structures with no members.
+* Flexible Array Members in Unions::  Unions with Flexible Array Members.
+* Flexible Array Members alone in Structures::  Structures with only Flexible 
Array Members.
 * Variable Length:: Arrays whose length is computed at run time.
 * Variadic Macros:: Macros with a variable number of arguments.
 * Escaped Newlines::Slightly looser rules for escaped newlines.
@@ -1873,6 +1875,38 @@ The structure has size zero.  In C++, empty structures 
are part
 of the language.  G++ treats empty structures as if they had a single
 member of type @code{char}.
 
+@node Flexible Array Members in Unions
+@section Unions with Flexible Array Members
+@cindex unions with flexible array members
+@cindex unions with FAMs
+
+GCC permits a C99 flexible array member (FAM) to be in a union:
+
+@smallexample
+union with_fam @{
+  int a;
+  int b[];
+@};
+@end smallexample
+
+If every member of a union is a flexible array member, the size of
+such a union is zero.
+
+@node Flexible Array Members alone in Structures
+@section Structures with only Flexible Array Members
+@cindex structures with only flexible array members
+@cindex structures with only FAMs
+
+GCC permits a C99 flexible array member (FAM) to be alone in a structure:
+
+@smallexample
+struct only_fam @{
+  int b[];
+@};
+@end smallexample
+
+The size of such a structure is zero.
+
 @node Variable Length
 @section Arrays of Variable Length
 @cindex variable-length arrays
-- 
2.31.1



[PATCH v5 0/4]Allow flexible array members in unions and alone in structures [PR53548]

2024-05-01 Thread Qing Zhao
Hi,

This is the 5th version for 
Allow flexible array members in unions and alone in structures [PR53548]

(for your reference, the 1st version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649737.html
The 2nd version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/650019.html
The 3rd version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/650255.html
The 4th version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-May/650341.html)

compared to the 4th version, the only change is (in patch 4):

Add one blank line between the comment and the definition of
 the function "add_flexible_array_elts_to_size".

Per Jason's comment.

The patch series is approved with this change.  

I will commit this patch series to GCC15 when it's open.

thanks.

Qing


[committed] libstdc++: Guard uses of is_pointer_interconvertible_v [PR114891]

2024-05-01 Thread Jonathan Wakely
Tested x86_64-linux. Pushed to trunk.

I'll backport this to gcc-14 as well, but it can wait until after the
14.1 release.

-- >8 --

This type trait isn't supported by Clang 18. It's only used in static
assertions, so they can just be omitted if the trait isn't available.

libstdc++-v3/ChangeLog:

PR libstdc++/114891
* include/std/generator: Check feature test macro before using
is_pointer_interconvertible_v.
---
 libstdc++-v3/include/std/generator | 8 
 1 file changed, 8 insertions(+)

diff --git a/libstdc++-v3/include/std/generator 
b/libstdc++-v3/include/std/generator
index 789016b5a88..1d5acc91420 100644
--- a/libstdc++-v3/include/std/generator
+++ b/libstdc++-v3/include/std/generator
@@ -322,8 +322,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template
auto await_suspend(std::coroutine_handle<_Promise> __c) noexcept
{
+#ifdef __glibcxx_is_pointer_interconvertible
  static_assert(is_pointer_interconvertible_base_of_v<
_Promise_erased, _Promise>);
+#endif
 
  auto& __n = __c.promise()._M_nest;
  return __n._M_pop();
@@ -344,8 +346,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template
void await_suspend(std::coroutine_handle<_Promise>) noexcept
{
+#ifdef __glibcxx_is_pointer_interconvertible
  static_assert(is_pointer_interconvertible_base_of_v<
_Promise_erased, _Promise>);
+#endif
  _M_bottom_value = ::std::addressof(_M_value);
}
 
@@ -375,8 +379,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::coroutine_handle<>
await_suspend(std::coroutine_handle<_Promise> __p) noexcept
{
+#ifdef __glibcxx_is_pointer_interconvertible
  static_assert(is_pointer_interconvertible_base_of_v<
_Promise_erased, _Promise>);
+#endif
 
  auto __c = _Coro_handle::from_address(__p.address());
  auto __t = _Coro_handle::from_address(this->_M_gen._M_coro.address());
@@ -685,8 +691,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return { coroutine_handle::from_promise(*this) }; }
   };
 
+#ifdef __glibcxx_is_pointer_interconvertible
   static_assert(is_pointer_interconvertible_base_of_v<_Erased_promise,
promise_type>);
+#endif
 
   generator(const generator&) = delete;
 
-- 
2.44.0



Re: [PATCH 4/4] lra: Apply DF_LIVE_SUBREG data

2024-05-01 Thread Vladimir Makarov


On 2/3/24 05:50, Lehua Ding wrote:

This patch apply the DF_LIVE_SUBREG to LRA pass. More changes were made
to the LRA than the IRA since the LRA will modify the DF data directly.
The main big changes are centered on the lra-lives.cc file.

gcc/ChangeLog:

* lra-coalesce.cc (update_live_info): Extend to DF_LIVE_SUBREG.
(lra_coalesce): Ditto.
* lra-constraints.cc (update_ebb_live_info): Ditto.
(get_live_on_other_edges): Ditto.
(inherit_in_ebb): Ditto.
(lra_inheritance): Ditto.
(fix_bb_live_info): Ditto.
(remove_inheritance_pseudos): Ditto.
* lra-int.h (GCC_LRA_INT_H): include subreg-live-range.h
(struct lra_insn_reg): Add op filed to record the corresponding rtx.
* lra-lives.cc (class bb_data_pseudos): Extend the bb_data_pseudos to
include new partial_def/use and range_def/use fileds for DF_LIVE_SUBREG
problem.

Typo "fileds".

(need_track_subreg_p): checking is the regno need to be tracked.
(make_hard_regno_live): switch to live_subreg filed.

The same typo.

(make_hard_regno_dead): Ditto.
(mark_regno_live): Support record subreg liveness.
(mark_regno_dead): Ditto.
(live_trans_fun): Adjust transfer function to support subreg liveness.
(live_con_fun_0): Adjust Confluence function to support subreg liveness.
(live_con_fun_n): Ditto.
(initiate_live_solver): Ditto.
(finish_live_solver): Ditto.
(process_bb_lives): Ditto.
(lra_create_live_ranges_1): Dump subreg liveness.
* lra-remat.cc (dump_candidates_and_remat_bb_data): Switch to
DF_LIVE_SUBREG df data.
(calculate_livein_cands): Ditto.
(do_remat): Ditto.
* lra-spills.cc (spill_pseudos): Ditto.
* lra.cc (new_insn_reg): New argument op.
(add_regs_to_insn_regno_info): Add new argument op.


The patch is ok for me with some minor requests:

You missed log entry for collect_non_operand_hard_regs.  Log entry for 
lra_create_live_ranges_1 is not full (at least, it should be "Ditto. ...").


Also you changed signature for functions update_live_info, 
fix_bb_live_info, mark_regno_live, mark_regno_dead, new_insn_reg but did 
not updated the function comments.  Outdated comments are even worse 
than the comment absence.  Please fix them.


Also some variable naming could be improved but it is up to you.

So now you need just an approval for the rest patches to commit your 
work but they are not my area responsibility.


It is difficult predict for patches of this size how they will work for 
other targets.  I tested you patches on aarch64 and ppc64le. They seems 
working right but please be prepare to switch them off (it is easy) if 
the patches create some issues for other targets, of course until fixing 
the issues.


And thank you for your contribution.  Improving GCC performance these 
days is a challenging task as so many people are working on GCC but you 
found such opportunity and most importantly implement it.




Re: [PATCH 3/4] ira: Apply DF_LIVE_SUBREG data

2024-05-01 Thread Vladimir Makarov



On 2/3/24 05:50, Lehua Ding wrote:

This patch simple replace df_get_live_in to df_get_subreg_live_in
and replace df_get_live_out to df_get_subreg_live_out.

gcc/ChangeLog:

* ira-build.cc (create_bb_allocnos): Switch to DF_LIVE_SUBREG df data.
(create_loop_allocnos): Ditto.
* ira-color.cc (ira_loop_edge_freq): Ditto.
* ira-emit.cc (generate_edge_moves): Ditto.
(add_ranges_and_copies): Ditto.
* ira-lives.cc (process_out_of_region_eh_regs): Ditto.
(add_conflict_from_region_landing_pads): Ditto.
(process_bb_node_lives): Ditto.
* ira.cc (find_moveable_pseudos): Ditto.
(interesting_dest_for_shprep_1): Ditto.
(allocate_initial_values): Ditto.
(ira): Ditto.


This patch is ok for me.

  gcc/ira-build.cc |  7 ---
  gcc/ira-color.cc |  8 
  gcc/ira-emit.cc  | 12 ++--
  gcc/ira-lives.cc |  7 ---
  gcc/ira.cc   | 19 ---
  5 files changed, 30 insertions(+), 23 deletions(-)




Re: [PATCH v4 4/4] Update the C/C++ FE routines

2024-05-01 Thread Qing Zhao


On May 1, 2024, at 09:35, Jason Merrill  wrote:

On 5/1/24 08:19, Qing Zhao wrote:
 "add_flexible_array_elts_to_size" and "layout_var_decl"  to handle
 the cases when the DECL is union.
Add testing cases to test the _bos for flexible array members in unions
or alone in structures.
gcc/c/ChangeLog:
* c-decl.cc (add_flexible_array_elts_to_size): Handle the cases
when the DECL is union.
gcc/cp/ChangeLog:
* decl.cc (layout_var_decl): Handle the cases when the DECL is
union with a flexible array member initializer.
gcc/testsuite/ChangeLog:
* c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test.
* c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.
---
 gcc/c/c-decl.cc   | 30 +++--
 gcc/cp/decl.cc| 32 +++--
 .../fam-in-union-alone-in-struct-bos-1.c  | 66 +++
 .../fam-in-union-alone-in-struct-bos.c| 45 +
 4 files changed, 159 insertions(+), 14 deletions(-)
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 947f3cd589eb..9ba92690daf5 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5337,9 +5337,9 @@ zero_length_array_type_p (const_tree type)
 }
   /* INIT is a constructor that forms DECL's initializer.  If the final
-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
-

Please keep the blank line between the comment and the function.

Okay, will change that.

 Please post the adjusted patch, but no need to wait for approval again, the 
patch series is OK.

Thanks. Will post the adjusted patch.

Qing

+   element initializes a flexible array field, adjust the size of the
+   DECL with the initializer based on whether the DECL is a union or
+   a structure.  */
 static void
 add_flexible_array_elts_to_size (tree decl, tree init)
 {
@@ -5353,10 +5353,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
   if (flexible_array_member_type_p (type))
 {
   complete_array_type (, elt, false);
-  DECL_SIZE (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-  DECL_SIZE_UNIT (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+  /* For a structure, add the size of the initializer to the DECL's
+  size.  */
+  if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ {
+   DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+   DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+   TYPE_SIZE_UNIT (type));
+ }
+  /* For a union, the DECL's size is the maximum of the current size
+  and the size of the initializer.  */
+  else
+ {
+   DECL_SIZE (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+   DECL_SIZE_UNIT (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+   TYPE_SIZE_UNIT (type));
+ }
 }
 }

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9a91c6f80da1..78e21b05296c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6555,8 +6555,9 @@ layout_var_decl (tree decl)
  }
 }
 -  /* If the final element initializes a flexible array field, add the size of
- that initializer to DECL's size.  */
+  /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure.  */
   if (type != error_mark_node
   && DECL_INITIAL (decl)
   && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6577,11 +6578,28 @@ layout_var_decl (tree decl)
&& TREE_CODE (vtype) == ARRAY_TYPE
&& COMPLETE_TYPE_P (vtype))
  {
-   DECL_SIZE (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
-   DECL_SIZE_UNIT (decl)
- = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
-   TYPE_SIZE_UNIT (vtype));
+   /* For a structure, add the size of the initializer to the DECL's
+  size.  */
+   if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+ {
+   DECL_SIZE (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+   TYPE_SIZE (vtype));
+   DECL_SIZE_UNIT (decl)
+ = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+   TYPE_SIZE_UNIT (vtype));
+ }
+   /* For a union, the DECL's size is the maximum of the current size
+  and the size of the initializer.  */
+   else
+ {
+   DECL_SIZE (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE (decl),
+   TYPE_SIZE (vtype));
+   DECL_SIZE_UNIT (decl)
+ = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+   TYPE_SIZE_UNIT (vtype));
+ }
  }
  }
 }
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
new file mode 100644
index ..aae9cf39c8c7
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c

Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Patrick Palka
On Thu, 2 May 2024, Nathaniel Shead wrote:

> On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:
> > On Wed, 1 May 2024, Nathaniel Shead wrote:
> > 
> > > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > > 
> > > -- >8 --
> > > 
> > > When calling instantiate_pending_templates at end of parsing, any new
> > > functions that are instantiated from this point have their module
> > > purview set based on the current value of module_kind.
> > > 
> > > This is unideal, however, as the modules code will then treat these
> > > instantiations as reachable and cause large swathes of the GMF to be
> > > emitted into the module CMI, despite no code in the actual module
> > > purview referencing it.
> > > 
> > > This patch fixes this by also remembering the value of module_kind when
> > > the instantiation was deferred, and restoring it when doing this
> > > deferred instantiation.  That way newly instantiated declarations
> > > appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
> > > instantiation was required, meaning that GMF entities won't be counted
> > > as reachable unless referenced by an actually reachable entity.
> > > 
> > > Note that purviewness and attachment etc. is generally only determined
> > > by the base template: this is purely for determining whether a
> > > specialisation was declared in the module purview and hence whether it
> > > should be streamed out.  See the comment on 'set_instantiating_module'.
> > > 
> > >   PR c++/114630
> > >   PR c++/114795
> > > 
> > > gcc/cp/ChangeLog:
> > > 
> > >   * cp-tree.h (struct tinst_level): Add field for tracking
> > >   module_kind.
> > >   * pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
> > >   (reopen_tinst_level): Restore module_kind from level.
> > >   (instantiate_pending_templates): Save and restore module_kind so
> > >   it isn't affected by reopen_tinst_level.
> > 
> > LGTM.  Another approach is to instantiate all so-far deferred
> > instantiations and vtables once we reach the start of the module
> > purview, but your approach is much cleaner.
> > 
> > Note that deferred instantiation can induce more deferred instantiation,
> > but your approach will do the right thing here (module_kind will be
> > inherited from the point of instantiation).
> > 
> > What if an instantiation is needed from both the GMF and the module
> > purview?  Then IIUC it'll be instantiated as if from the GMF, which
> > seems right to me.
> > 
> 
> Hm..., so I believe it'll be marked according to whichever instantiates
> it "first", so if e.g. deferred from GMF and then instantiated
> non-deferred from purview it'll be marked purview (and the deferred
> instantiation will be skipped as it's already instantiated).  This could
> mean it gets unnecessarily emitted if it only got instantiated because
> it got used in e.g. a non-inline function body, I suppose; but that's
> true in general actually, at the moment.

FWIW I think the most relevant situation where we need to instantiate
immediately and can't defer until EOF is during constexpr evaluation of
a variable initializer.  (We also immediately instantiate variable
template specializations, and function template specializations with
deduced return type, but in these cases we'd always instantiate from the
first use, i.e. from the GMF in this scenario.)

So I guess a testcase for this situation could be something like:

module;
template constexpr int f(T t) { return t; }
template int f(int);

export module foo;
constexpr int w = f(0);
// f ideally shouldn't be emitted in the CMI?

> 
> Maybe then a better approach would be to instead always use the
> DECL_MODULE_PURVIEW_P of the instantiating template instead of the
> global 'module_purview_p' function in 'set_instantiating_module'?
> I think that should still make sure that instantiations are emitted
> when they need to be (because they'll be reachable from a declaration
> in the purview): I might try to experiment with something like this.

The approach of instantiating all so-far deferred instantiations/vtables
at the start of the module purview should handle this properly too.

> 
> > > 
> > > gcc/testsuite/ChangeLog:
> > > 
> > >   * g++.dg/modules/gmf-3.C: New test.
> > > 
> > > Signed-off-by: Nathaniel Shead 
> > > ---
> > >  gcc/cp/cp-tree.h |  3 +++
> > >  gcc/cp/pt.cc |  4 
> > >  gcc/testsuite/g++.dg/modules/gmf-3.C | 13 +
> > >  3 files changed, 20 insertions(+)
> > >  create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C
> > > 
> > > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > > index 1938ada0268..0e619120ccc 100644
> > > --- a/gcc/cp/cp-tree.h
> > > +++ b/gcc/cp/cp-tree.h
> > > @@ -6626,6 +6626,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
> > >/* The location where the template is instantiated.  */
> > >location_t locus;
> > >  
> > > +  /* The module kind where the template is 

[pushed] c++: const void* memchr [PR113706]

2024-05-01 Thread Jason Merrill
Tested x86_64-pc-linux-gnu, applying to trunk.

-- 8< --

The C++ standard specifies that the  functions have const and
non-const overloads, unlike C's single function with const argument and
non-const return.  Many systems don't actually implement this, but only add
an overload with non-const argument, so both end up having non-const return.
Solaris  does what the standard says, but we were penalizing it by
not recognizing the const overload as the built-in memchr.

PR c++/113706

gcc/cp/ChangeLog:

* decl.cc (decls_match): Handle memchr return type being
const-qualified.

gcc/testsuite/ChangeLog:

* g++.dg/opt/const-builtin1.C: New test.
* c-c++-common/pr103798-2.c: Remove xfail.
---
 gcc/cp/decl.cc| 10 +++
 gcc/testsuite/c-c++-common/pr103798-2.c   |  3 +--
 gcc/testsuite/g++.dg/opt/const-builtin1.C | 33 +++
 3 files changed, 44 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/opt/const-builtin1.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d88e0698652..df855334133 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1156,6 +1156,16 @@ decls_match (tree newdecl, tree olddecl, bool 
record_versions /* = true */)
   tree r2 = fndecl_declared_return_type (olddecl);
   tree r1 = fndecl_declared_return_type (newdecl);
 
+  /* For memchr et al, allow const void* return type (as specified by C++)
+when we expect void* (as in C).  */
+  if (DECL_IS_UNDECLARED_BUILTIN (olddecl)
+ && DECL_EXTERN_C_P (olddecl)
+ && !same_type_p (r1, r2)
+ && TREE_CODE (r1) == POINTER_TYPE
+ && TREE_CODE (r2) == POINTER_TYPE
+ && comp_ptr_ttypes (TREE_TYPE (r1), TREE_TYPE (r2)))
+   r2 = r1;
+
   tree p1 = TYPE_ARG_TYPES (f1);
   tree p2 = TYPE_ARG_TYPES (f2);
 
diff --git a/gcc/testsuite/c-c++-common/pr103798-2.c 
b/gcc/testsuite/c-c++-common/pr103798-2.c
index 83cdfaa1660..e7e99c3679e 100644
--- a/gcc/testsuite/c-c++-common/pr103798-2.c
+++ b/gcc/testsuite/c-c++-common/pr103798-2.c
@@ -27,5 +27,4 @@ main ()
  return 0;
 }
 
-/* See PR c++/113706 for the xfail.  */
-/* { dg-final { scan-assembler-not "memchr" { xfail { c++ && { *-*-solaris2* 
*-*-vxworks* } } } } } */
+/* { dg-final { scan-assembler-not "memchr" } } */
diff --git a/gcc/testsuite/g++.dg/opt/const-builtin1.C 
b/gcc/testsuite/g++.dg/opt/const-builtin1.C
new file mode 100644
index 000..8b9987271c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/const-builtin1.C
@@ -0,0 +1,33 @@
+// PR c++/113706
+/* A variant of the pr103798-2.c test with const void * memchr return type, as
+   specified by the C++ standard.  */
+/* { dg-do run } */
+/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */
+
+extern "C" const void *memchr (const void *, int, __SIZE_TYPE__); // { 
dg-bogus "built-in" }
+
+__attribute__ ((weak))
+int
+f (int a)
+{
+   return memchr ("aE", a, 2) != 0;
+}
+
+__attribute__ ((weak))
+int
+g (char a)
+{
+  return a == 'a' || a == 'E';
+}
+
+int
+main ()
+{
+ for (int i = 0; i < 255; i++)
+   if (f (i + 256) != g (i + 256))
+ __builtin_abort ();
+
+ return 0;
+}
+
+/* { dg-final { scan-assembler-not "memchr" } } */

base-commit: c60b3e211c555706cdc2dc8bfcdd540152cff350
-- 
2.44.0



Re: [PATCH v4 4/4] Update the C/C++ FE routines

2024-05-01 Thread Jason Merrill

On 5/1/24 08:19, Qing Zhao wrote:

  "add_flexible_array_elts_to_size" and "layout_var_decl"  to handle
  the cases when the DECL is union.

Add testing cases to test the _bos for flexible array members in unions
or alone in structures.

gcc/c/ChangeLog:

* c-decl.cc (add_flexible_array_elts_to_size): Handle the cases
when the DECL is union.

gcc/cp/ChangeLog:

* decl.cc (layout_var_decl): Handle the cases when the DECL is
union with a flexible array member initializer.

gcc/testsuite/ChangeLog:

* c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test.
* c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.
---
  gcc/c/c-decl.cc   | 30 +++--
  gcc/cp/decl.cc| 32 +++--
  .../fam-in-union-alone-in-struct-bos-1.c  | 66 +++
  .../fam-in-union-alone-in-struct-bos.c| 45 +
  4 files changed, 159 insertions(+), 14 deletions(-)
  create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
  create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 947f3cd589eb..9ba92690daf5 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5337,9 +5337,9 @@ zero_length_array_type_p (const_tree type)
  }
  
  /* INIT is a constructor that forms DECL's initializer.  If the final

-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
-


Please keep the blank line between the comment and the function.  Please 
post the adjusted patch, but no need to wait for approval again, the 
patch series is OK.



+   element initializes a flexible array field, adjust the size of the
+   DECL with the initializer based on whether the DECL is a union or
+   a structure.  */
  static void
  add_flexible_array_elts_to_size (tree decl, tree init)
  {
@@ -5353,10 +5353,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
if (flexible_array_member_type_p (type))
  {
complete_array_type (, elt, false);
-  DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-  DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+  /* For a structure, add the size of the initializer to the DECL's
+size.  */
+  if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
+  /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+  else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
  }
  }
  
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9a91c6f80da1..78e21b05296c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6555,8 +6555,9 @@ layout_var_decl (tree decl)
}
  }
  
-  /* If the final element initializes a flexible array field, add the size of

- that initializer to DECL's size.  */
+  /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure.  */
if (type != error_mark_node
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6577,11 +6578,28 @@ layout_var_decl (tree decl)
  && TREE_CODE (vtype) == ARRAY_TYPE
  && COMPLETE_TYPE_P (vtype))
{
- DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
- DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
- TYPE_SIZE_UNIT (vtype));
+ /* For a structure, add the size of the initializer to the DECL's
+size.  */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+   }
+ /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+ else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl),
+ 

Re: [PATCH 4/4] c++: Add new xtreme-header testcase for GMF discarding

2024-05-01 Thread Jason Merrill

On 5/1/24 03:01, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?


OK.


Another thought would be to replace xtreme-header.h with  so
that we don't need to keep it up-to-date in the future.  But this patch just
does the obviously correct thing.

-- >8 --

This new testcase helps verify that the issues discovered in PR114630
with GMF entries being inappropriately emitted into the module CMI don't
regress, at least for the kinds of code used in the standard library
headers.

This also updates the base xtreme-header.h file to include new header
files that are now available.

gcc/testsuite/ChangeLog:

* g++.dg/modules/xtreme-header.h: Update.
* g++.dg/modules/xtreme-header-8.C: New test.

Signed-off-by: Nathaniel Shead 
---
  .../g++.dg/modules/xtreme-header-8.C  |  9 +++
  gcc/testsuite/g++.dg/modules/xtreme-header.h  | 24 ---
  2 files changed, 25 insertions(+), 8 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/xtreme-header-8.C

diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-8.C 
b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C
new file mode 100644
index 000..b0d0ae87534
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// { dg-module-cmi empty }
+
+module;
+#include "xtreme-header.h"
+export module empty;
+
+// The whole GMF should be discarded here
+// { dg-final { scan-lang-dump "Wrote 0 clusters" module } }
diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header.h 
b/gcc/testsuite/g++.dg/modules/xtreme-header.h
index 3147aaf00f4..8d95218755a 100644
--- a/gcc/testsuite/g++.dg/modules/xtreme-header.h
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header.h
@@ -89,7 +89,6 @@
  
  // C++20

  #if __cplusplus > 201703
-#if 1
  #include 
  #include 
  #include 
@@ -98,6 +97,7 @@
  #if __cpp_coroutines
  #include 
  #endif
+#include 
  #include 
  #include 
  #include 
@@ -106,24 +106,32 @@
  #include 
  #include 
  #include 
-#if 0
-// Unimplemented
-#include 
-#endif
-#endif
  #endif
  
  // C++23

  #if __cplusplus > 202002L
  #include 
+#include 
+#include 
  #include 
  #include 
+#include 
  #if 0
  // Unimplemented
  #include 
  #include 
-#include 
  #include 
-#include 
+#endif
+#endif
+
+// C++26
+#if __cplusplus > 202302L
+#if 0
+// Unimplemented
+#include 
+#include 
+#include 
+#include 
+#include 
  #endif
  #endif




Re: [PATCH 1/4] c++/modules: Don't emit unused GMF partial specializations [PR114630]

2024-05-01 Thread Jason Merrill

On 5/1/24 02:59, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?


OK.


-- >8 --

The change in r14-8408 to also emit partial specializations in the
global module fragment caused the regression in the linked PR; this
patch fixes this by restricting emitted GM partial specializations to
those that are actually used.

PR c++/114630

gcc/cp/ChangeLog:

* module.cc (depset::hash::add_partial_entities): Mark GM
specializations as unreached.
(depset::hash::find_dependencies): Also reach entities in the
DECL_TEMPLATE_SPECIALIZATIONS list.

gcc/testsuite/ChangeLog:

* g++.dg/modules/partial-3.C: New test.

Signed-off-by: Nathaniel Shead 
---
  gcc/cp/module.cc | 75 +++-
  gcc/testsuite/g++.dg/modules/partial-3.C | 20 +++
  2 files changed, 66 insertions(+), 29 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/modules/partial-3.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index fac0301d80e..02b0ab3d687 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13304,14 +13304,22 @@ depset::hash::add_partial_entities (vec 
*partial_classes)
depset *dep = make_dependency (inner, depset::EK_DECL);
  
if (dep->get_entity_kind () == depset::EK_REDIRECT)

-   /* We should have recorded the template as a partial
-  specialization.  */
-   gcc_checking_assert (dep->deps[0]->get_entity_kind ()
-== depset::EK_PARTIAL);
+   {
+ dep = dep->deps[0];
+ /* We should have recorded the template as a partial
+specialization.  */
+ gcc_checking_assert (dep->get_entity_kind ()
+  == depset::EK_PARTIAL);
+   }
else
/* It was an explicit specialization, not a partial one.  */
gcc_checking_assert (dep->get_entity_kind ()
 == depset::EK_SPECIALIZATION);
+
+  /* Only emit GM entities if reached.  */
+  if (!DECL_LANG_SPECIFIC (inner)
+ || !DECL_MODULE_PURVIEW_P (inner))
+   dep->set_flag_bit ();
  }
  }
  
@@ -13632,31 +13640,40 @@ depset::hash::find_dependencies (module_state *module)

  if (!walker.is_key_order ()
  && TREE_CODE (decl) == TEMPLATE_DECL
  && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
-   /* Mark all the explicit & partial specializations as
-  reachable.  */
-   for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl);
-cons; cons = TREE_CHAIN (cons))
- {
-   tree spec = TREE_VALUE (cons);
-   if (TYPE_P (spec))
- spec = TYPE_NAME (spec);
-   int use_tpl;
-   node_template_info (spec, use_tpl);
-   if (use_tpl & 2)
- {
-   depset *spec_dep = find_dependency (spec);
-   if (spec_dep->get_entity_kind () == EK_REDIRECT)
- spec_dep = spec_dep->deps[0];
-   if (spec_dep->is_unreached ())
- {
-   reached_unreached = true;
-   spec_dep->clear_flag_bit ();
-   dump (dumper::DEPEND)
- && dump ("Reaching unreached specialization"
-  " %C:%N", TREE_CODE (spec), spec);
- }
- }
- }
+   {
+ /* Mark all the explicit & partial specializations as
+reachable.  We search both specialization lists as some
+constrained partial specializations for class types are
+only found in DECL_TEMPLATE_SPECIALIZATIONS.  */
+ auto mark_reached = [this](tree spec)
+   {
+ if (TYPE_P (spec))
+   spec = TYPE_NAME (spec);
+ int use_tpl;
+ node_template_info (spec, use_tpl);
+ if (use_tpl & 2)
+   {
+ depset *spec_dep = find_dependency (spec);
+ if (spec_dep->get_entity_kind () == EK_REDIRECT)
+   spec_dep = spec_dep->deps[0];
+ if (spec_dep->is_unreached ())
+   {
+ reached_unreached = true;
+ spec_dep->clear_flag_bit ();
+ dump (dumper::DEPEND)
+   && dump ("Reaching unreached specialization"
+" %C:%N", TREE_CODE (spec), spec);
+   }
+   }
+   };
+
+ for (tree cons = DECL_TEMPLATE_INSTANTIATIONS 

Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Jason Merrill

On 5/1/24 07:11, Patrick Palka wrote:

On Wed, 1 May 2024, Nathaniel Shead wrote:


Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When calling instantiate_pending_templates at end of parsing, any new
functions that are instantiated from this point have their module
purview set based on the current value of module_kind.

This is unideal, however, as the modules code will then treat these
instantiations as reachable and cause large swathes of the GMF to be
emitted into the module CMI, despite no code in the actual module
purview referencing it.

This patch fixes this by also remembering the value of module_kind when
the instantiation was deferred, and restoring it when doing this
deferred instantiation.  That way newly instantiated declarations
appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
instantiation was required, meaning that GMF entities won't be counted
as reachable unless referenced by an actually reachable entity.

Note that purviewness and attachment etc. is generally only determined
by the base template: this is purely for determining whether a
specialisation was declared in the module purview and hence whether it
should be streamed out.  See the comment on 'set_instantiating_module'.

PR c++/114630
PR c++/114795

gcc/cp/ChangeLog:

* cp-tree.h (struct tinst_level): Add field for tracking
module_kind.
* pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
(reopen_tinst_level): Restore module_kind from level.
(instantiate_pending_templates): Save and restore module_kind so
it isn't affected by reopen_tinst_level.


LGTM.  Another approach is to instantiate all so-far deferred
instantiations and vtables once we reach the start of the module
purview, but your approach is much cleaner.


Hmm, I actually think I like the approach of instantiating at that point 
better, so that instantiations in the GMF can't depend on things in 
module purview.


And probably do the same again when switching to the private module 
fragment, when that's implemented.


Jason



[PATCH v4 2/4] C and C++ FE changes

2024-05-01 Thread Qing Zhao
 to support flexible array members
 in unions and alone in structures. Adjust testcases for flexible array member
 in union and alone in structure extension.

gcc/c/ChangeLog:

* c-decl.cc (finish_struct): Change errors to pedwarns for the cases
flexible array members in union or alone in structures.

gcc/cp/ChangeLog:

* class.cc (diagnose_flexarrays): Change error to pdewarn for the case
flexible array members alone in structures.
* decl.cc (grokdeclarator): Change error to pdewarn for the case
flexible array members in unions.

gcc/ChangeLog:

* stor-layout.cc (place_union_field): Use zero sizes for flexible array
member fields.

gcc/testsuite/ChangeLog:

* c-c++-common/builtin-clear-padding-3.c: Adjust testcase.
* g++.dg/ext/flexary12.C: Likewise.
* g++.dg/ext/flexary19.C: Likewise.
* g++.dg/ext/flexary2.C: Likewise.
* g++.dg/ext/flexary3.C: Likewise.
* g++.dg/ext/flexary36.C: Likewise.
* g++.dg/ext/flexary4.C: Likewise.
* g++.dg/ext/flexary5.C: Likewise.
* g++.dg/ext/flexary8.C: Likewise.
* g++.dg/torture/pr64280.C: Likewise.
* gcc.dg/20050620-1.c: Likewise.
* gcc.dg/940510-1.c: Likewise.
---
 gcc/c/c-decl.cc   | 16 ++
 gcc/cp/class.cc   | 11 ++--
 gcc/cp/decl.cc|  7 ++-
 gcc/stor-layout.cc|  9 +++-
 .../c-c++-common/builtin-clear-padding-3.c| 10 ++--
 gcc/testsuite/g++.dg/ext/flexary12.C  |  6 +--
 gcc/testsuite/g++.dg/ext/flexary19.C  | 42 +++
 gcc/testsuite/g++.dg/ext/flexary2.C   |  2 +-
 gcc/testsuite/g++.dg/ext/flexary3.C   |  2 +-
 gcc/testsuite/g++.dg/ext/flexary36.C  |  2 +-
 gcc/testsuite/g++.dg/ext/flexary4.C   | 54 +--
 gcc/testsuite/g++.dg/ext/flexary5.C   |  4 +-
 gcc/testsuite/g++.dg/ext/flexary8.C   |  8 +--
 gcc/testsuite/g++.dg/torture/pr64280.C|  2 +-
 gcc/testsuite/gcc.dg/20050620-1.c |  2 +-
 gcc/testsuite/gcc.dg/940510-1.c   |  4 +-
 16 files changed, 91 insertions(+), 90 deletions(-)

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 345090dae38b..947f3cd589eb 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -9471,11 +9471,8 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
   if (flexible_array_member_type_p (TREE_TYPE (x)))
{
  if (TREE_CODE (t) == UNION_TYPE)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in union");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in union is a GCC extension");
  else if (!is_last_field)
{
  error_at (DECL_SOURCE_LOCATION (x),
@@ -9483,12 +9480,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, 
tree attributes,
  TREE_TYPE (x) = error_mark_node;
}
  else if (!saw_named_field)
-   {
- error_at (DECL_SOURCE_LOCATION (x),
-   "flexible array member in a struct with no named "
-   "members");
- TREE_TYPE (x) = error_mark_node;
-   }
+   pedwarn (DECL_SOURCE_LOCATION (x), OPT_Wpedantic,
+"flexible array member in a struct with no named "
+"members is a GCC extension");
}
 
   if (pedantic && TREE_CODE (t) == RECORD_TYPE
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 5f258729940b..0c8afb72550f 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -7624,6 +7624,7 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   bool diagd = false;
 
   const char *msg = 0;
+  const char *msg_fam = 0;
 
   if (TYPE_DOMAIN (TREE_TYPE (fmem->array)))
 {
@@ -7649,15 +7650,19 @@ diagnose_flexarrays (tree t, const flexmems_t *fmem)
   if (fmem->after[0])
msg = G_("flexible array member %qD not at end of %q#T");
   else if (!fmem->first)
-   msg = G_("flexible array member %qD in an otherwise empty %q#T");
+   msg_fam = G_("flexible array member %qD in an otherwise"
+" empty %q#T is a GCC extension");
 
-  if (msg)
+  if (msg || msg_fam)
{
  location_t loc = DECL_SOURCE_LOCATION (fmem->array);
  diagd = true;
 
  auto_diagnostic_group d;
- error_at (loc, msg, fmem->array, t);
+ if (msg)
+   error_at (loc, msg, fmem->array, t);
+ else
+   pedwarn (loc, OPT_Wpedantic, msg_fam, fmem->array, t);
 
  /* In the unlikely event that the member following the flexible
 array member is declared in a different class, or the member
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 

[PATCH v4 4/4] Update the C/C++ FE routines

2024-05-01 Thread Qing Zhao
 "add_flexible_array_elts_to_size" and "layout_var_decl"  to handle
 the cases when the DECL is union.

Add testing cases to test the _bos for flexible array members in unions
or alone in structures.

gcc/c/ChangeLog:

* c-decl.cc (add_flexible_array_elts_to_size): Handle the cases
when the DECL is union.

gcc/cp/ChangeLog:

* decl.cc (layout_var_decl): Handle the cases when the DECL is
union with a flexible array member initializer.

gcc/testsuite/ChangeLog:

* c-c++-common/fam-in-union-alone-in-struct-bos-1.c: New test.
* c-c++-common/fam-in-union-alone-in-struct-bos.c: New test.
---
 gcc/c/c-decl.cc   | 30 +++--
 gcc/cp/decl.cc| 32 +++--
 .../fam-in-union-alone-in-struct-bos-1.c  | 66 +++
 .../fam-in-union-alone-in-struct-bos.c| 45 +
 4 files changed, 159 insertions(+), 14 deletions(-)
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos-1.c
 create mode 100644 
gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-bos.c

diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index 947f3cd589eb..9ba92690daf5 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5337,9 +5337,9 @@ zero_length_array_type_p (const_tree type)
 }
 
 /* INIT is a constructor that forms DECL's initializer.  If the final
-   element initializes a flexible array field, add the size of that
-   initializer to DECL's size.  */
-
+   element initializes a flexible array field, adjust the size of the
+   DECL with the initializer based on whether the DECL is a union or
+   a structure.  */
 static void
 add_flexible_array_elts_to_size (tree decl, tree init)
 {
@@ -5353,10 +5353,26 @@ add_flexible_array_elts_to_size (tree decl, tree init)
   if (flexible_array_member_type_p (type))
 {
   complete_array_type (, elt, false);
-  DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
-  DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl), TYPE_SIZE_UNIT (type));
+  /* For a structure, add the size of the initializer to the DECL's
+size.  */
+  if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
+  /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+  else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl), TYPE_SIZE (type));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (type));
+   }
 }
 }
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9a91c6f80da1..78e21b05296c 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -6555,8 +6555,9 @@ layout_var_decl (tree decl)
}
 }
 
-  /* If the final element initializes a flexible array field, add the size of
- that initializer to DECL's size.  */
+  /* If the final element initializes a flexible array field, adjust
+ the size of the DECL with the initializer based on whether the
+ DECL is a union or a structure.  */
   if (type != error_mark_node
   && DECL_INITIAL (decl)
   && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR
@@ -6577,11 +6578,28 @@ layout_var_decl (tree decl)
  && TREE_CODE (vtype) == ARRAY_TYPE
  && COMPLETE_TYPE_P (vtype))
{
- DECL_SIZE (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE (decl), TYPE_SIZE (vtype));
- DECL_SIZE_UNIT (decl)
-   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
- TYPE_SIZE_UNIT (vtype));
+ /* For a structure, add the size of the initializer to the DECL's
+size.  */
+ if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
+   {
+ DECL_SIZE (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (PLUS_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+   }
+ /* For a union, the DECL's size is the maximum of the current size
+and the size of the initializer.  */
+ else
+   {
+ DECL_SIZE (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE (decl),
+ TYPE_SIZE (vtype));
+ DECL_SIZE_UNIT (decl)
+   = size_binop (MAX_EXPR, DECL_SIZE_UNIT (decl),
+ TYPE_SIZE_UNIT (vtype));
+  

[PATCH v4 3/4] Add testing cases for flexible array members in unions and alone in structures.

2024-05-01 Thread Qing Zhao
gcc/testsuite/ChangeLog:

* c-c++-common/fam-in-union-alone-in-struct-1.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-2.c: New testcase.
* c-c++-common/fam-in-union-alone-in-struct-3.c: New testcase.
---
 .../fam-in-union-alone-in-struct-1.c  | 52 +++
 .../fam-in-union-alone-in-struct-2.c  | 51 ++
 .../fam-in-union-alone-in-struct-3.c  | 36 +
 3 files changed, 139 insertions(+)
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
 create mode 100644 gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c

diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
new file mode 100644
index ..7d4721aa95ac
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-1.c
@@ -0,0 +1,52 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do run} */
+/* { dg-options "-Wpedantic" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-1 } */
+  int b[];  /* { dg-warning "flexible array member in union is a GCC 
extension" } */
+};
+
+struct only_fam {
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[];
+  /* { dg-warning "in a struct with no named members" "" { target c } .-1 } */
+  /* { dg-warning "in an otherwise empty" "" { target c++ } .-2 } */
+  /* { dg-warning "forbids flexible array member" "" { target c++ } .-3 } */
+};
+
+int main ()
+{
+  if (sizeof (union with_fam_1) != sizeof (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_2) != __alignof__ (int))
+__builtin_abort ();
+  if (sizeof (union with_fam_3) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam) != 0)
+__builtin_abort ();
+  if (sizeof (struct only_fam_2) != sizeof (int))
+__builtin_abort ();
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
new file mode 100644
index ..3743f9e7dac5
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-2.c
@@ -0,0 +1,51 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures: initialization  */
+/* { dg-do run} */
+/* { dg-options "-O2" } */
+
+union with_fam_1 {
+  int a;
+  int b[]; 
+} with_fam_1_v = {.b = {1, 2, 3, 4}};
+
+union with_fam_2 {
+  int a;
+  char b[];  
+} with_fam_2_v = {.a = 0x1f2f3f4f};
+
+union with_fam_3 {
+  char a[];  
+  int b[];  
+} with_fam_3_v = {.b = {0x1f2f3f4f, 0x5f6f7f7f}};
+
+struct only_fam {
+  int b[]; 
+} only_fam_v = {{7, 11}};
+
+struct only_fam_2 {
+  unsigned int : 2;
+  unsigned int : 3;
+  int b[]; 
+} only_fam_2_v = {{7, 11}};
+
+int main ()
+{
+  if (with_fam_1_v.b[3] != 4
+  || with_fam_1_v.b[0] != 1)
+__builtin_abort ();
+  if (with_fam_2_v.b[3] != 0x1f
+  || with_fam_2_v.b[0] != 0x4f)
+__builtin_abort ();
+  if (with_fam_3_v.a[0] != 0x4f
+  || with_fam_3_v.a[7] != 0x5f)
+__builtin_abort ();
+  if (only_fam_v.b[0] != 7
+  || only_fam_v.b[1] != 11)
+__builtin_abort ();
+  if (only_fam_2_v.b[0] != 7
+  || only_fam_2_v.b[1] != 11)
+__builtin_abort ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c 
b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
new file mode 100644
index ..dd36fa01306d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/fam-in-union-alone-in-struct-3.c
@@ -0,0 +1,36 @@
+/* testing the correct usage of flexible array members in unions 
+   and alone in structures.  */
+/* { dg-do compile } */
+/* { dg-options "-pedantic-errors" } */
+
+union with_fam_1 {
+  int a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_2 {
+  char a;
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};
+
+union with_fam_3 {
+  char a[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+  /* { dg-error "in an otherwise empty" "" { target c++ } .-1 } */
+  int b[];  /* { dg-error "flexible array member in union is a GCC extension" 
} */
+};

[PATCH v4 1/4] Allow flexible array members in unions and alone in structures [PR53548]

2024-05-01 Thread Qing Zhao
The request for GCC to accept that the C99 flexible array member can be
in a union or alone in a structure has been made a long time ago around 2012
for supporting several practical cases including glibc.

A GCC PR has been opened for such request at that time:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53548

However, this PR was closed as WONTFIX around 2015 due to the following reason:

"there is an existing extension that makes the requested functionality possible"
i.e GCC fully supported that the zero-length array can be in a union or alone
in a structure for a long time. (though I didn't see any official documentation
on such extension)

It's reasonable to close PR53548 at that time since zero-length array extension
can be used for such purpose.

However, since GCC13, in order to improve the C/C++ security, we introduced
-fstrict-flex-arrays=n to gradually eliminate the "fake flexible array"
usages from C/C++ source code. As a result, zero-length arrays eventually
will be replaced by C99 flexiable array member completely.

Therefore, GCC needs to explicitly allow such extensions directly for C99
flexible arrays, since flexable array member in unions or alone in structs
are common code patterns in active use by the Linux kernel (and other projects).

For example, these do not error by default with GCC:

union one {
  int a;
  int b[0];
};

union two {
  int a;
  struct {
struct { } __empty;
int b[];
  };
};

But these do:

union three {
  int a;
  int b[];
};

struct four {
  int b[];
}

Clang has supported such extensions since March, 2024
https://github.com/llvm/llvm-project/pull/84428

GCC should also support such extensions. This will allow for
a seamless transition for code bases away from zero-length arrays without
losing existing code patterns.

gcc/ChangeLog:

* doc/extend.texi: Add documentation for Flexible Array Members in
Unions and Flexible Array Members alone in Structures.
---
 gcc/doc/extend.texi | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7b54a241a7bf..94a77d7ef39c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -42,6 +42,8 @@ extensions, accepted by GCC in C90 mode and in C++.
 * Named Address Spaces::Named address spaces.
 * Zero Length:: Zero-length arrays.
 * Empty Structures::Structures with no members.
+* Flexible Array Members in Unions::  Unions with Flexible Array Members.
+* Flexible Array Members alone in Structures::  Structures with only Flexible 
Array Members.
 * Variable Length:: Arrays whose length is computed at run time.
 * Variadic Macros:: Macros with a variable number of arguments.
 * Escaped Newlines::Slightly looser rules for escaped newlines.
@@ -1873,6 +1875,38 @@ The structure has size zero.  In C++, empty structures 
are part
 of the language.  G++ treats empty structures as if they had a single
 member of type @code{char}.
 
+@node Flexible Array Members in Unions
+@section Unions with Flexible Array Members
+@cindex unions with flexible array members
+@cindex unions with FAMs
+
+GCC permits a C99 flexible array member (FAM) to be in a union:
+
+@smallexample
+union with_fam @{
+  int a;
+  int b[];
+@};
+@end smallexample
+
+If every member of a union is a flexible array member, the size of
+such a union is zero.
+
+@node Flexible Array Members alone in Structures
+@section Structures with only Flexible Array Members
+@cindex structures with only flexible array members
+@cindex structures with only FAMs
+
+GCC permits a C99 flexible array member (FAM) to be alone in a structure:
+
+@smallexample
+struct only_fam @{
+  int b[];
+@};
+@end smallexample
+
+The size of such a structure is zero.
+
 @node Variable Length
 @section Arrays of Variable Length
 @cindex variable-length arrays
-- 
2.31.1



[PATCH v4 0/4] Allow flexible array members in unions and alone in structures [PR53548]

2024-05-01 Thread Qing Zhao
Hi,

This is the 4th version for 
Allow flexible array members in unions and alone in structures [PR53548]

(for your reference, the 1st version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/649737.html
The 2nd version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/650019.html
The 3rd version is at:
https://gcc.gnu.org/pipermail/gcc-patches/2024-April/650255.html)

compared to the 3rd version, the major difference are:

A. Two minor wording changes in doc/extend.texi per Jason's comments.
B. In the 4th patch, for both C and C++ FE, delete the new variable
   "is_decl_type_union". 

Review needed:

   C++ FE changes (in Patch 2 and Patch 4);
   Middle-end changes (in Patch 2);
   New C FE change (in Patch 4);
   New testing cases for _bos (in Patch 4);

Approval status:

   All other changes (C FE and documentation and related testing cases)
   have been approved with minor updates.

The patch set includes:
 1. Documentation change.
Allow flexible array members in unions and alone in structures
[PR53548]
 2. C and C++ FE changes to support flexible array members in unions and
   alone in structures.
Adjust testcases for flexible array member in union and alone in
   structure extension.
 3. Add testing cases for flexible array members in unions and alone in
   structures.
 4. Update the C FE routine "add_flexible_array_elts_to_size" C++ FE
   routine "layout_var_decl"  to handle the cases when the DECL is
   union.
Add testing cvases to test the _bos for FAM in union and alone in
   structures.

bootstrapped and regression tested on both x86 and aarch64, no issue.

Okay for GCC15?

thanks.

Qing


Re: [PATCH] c++: Implement modules ABI for vtable emissions

2024-05-01 Thread Jason Merrill

On 5/1/24 04:37, Nathaniel Shead wrote:

Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

This patch implements the changes described in
https://github.com/itanium-cxx-abi/cxx-abi/pull/171.

One restriction that is lifted in the ABI that hasn't been updated here
is that the ABI no longer requires unique vtables to be emitted with
vague linkage.  I haven't changed this behaviour for this patch, but in
the future we should probably look into changing the relevant target
hook ('class_data_always_comdat') to default to 'false'.


I suppose we could, but it seems unnecessary.  We've previously decided 
to use COMDAT even when we know that a vague linkage entity is only 
emitted in one TU.  For instance, sticking with COMDAT is more forgiving 
to changes in key function identification.


The patch is OK.

Jason



[pushed] doc: FreeBSD no longer has a GNU toolchain in base

2024-05-01 Thread Gerald Pfeifer
The recent thread on building on FreeBSD made me release there's quite 
some cruft to remove (and a note to add) regarding that.

Pushed (and more to come).

Gerald


gcc:
PR target/69374
PR target/112959
* doc/install.texi (Specific) <*-*-freebsd*>: No longer refer
to GCC or binutils in base. Recommend bootstrap using binutils.
---
 gcc/doc/install.texi | 15 +--
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index 4119304f66a..b1d28dcb03b 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -4092,16 +4092,11 @@ This configuration is intended for embedded systems.
 We support FreeBSD using the ELF file format with DWARF 2 debugging
 for all CPU architectures.  There are
 no known issues with mixing object files and libraries with different
-debugging formats.  Otherwise, this release of GCC should now match
-more of the configuration used in the stock FreeBSD configuration of
-GCC@.  In particular, @option{--enable-threads} is now configured by
-default.  However, as a general user, do not attempt to replace the
-system compiler with this release.
-
-The version of binutils installed in @file{/usr/bin} probably works
-with this release of GCC@.  Bootstrapping against the latest GNU
-binutils and/or the version found in @file{/usr/ports/devel/binutils} has
-been known to enable additional features and improve overall testsuite
+debugging formats.
+
+We recommend bootstrapping against the latest GNU binutils or the
+version found in the @file{devel/binutils} port. This also has been
+known to enable additional features and improve overall testsuite
 results.
 
 @html
-- 
2.44.0


Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Nathaniel Shead
On Wed, May 01, 2024 at 10:11:20AM -0400, Patrick Palka wrote:
> On Wed, 1 May 2024, Nathaniel Shead wrote:
> 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> > 
> > -- >8 --
> > 
> > When calling instantiate_pending_templates at end of parsing, any new
> > functions that are instantiated from this point have their module
> > purview set based on the current value of module_kind.
> > 
> > This is unideal, however, as the modules code will then treat these
> > instantiations as reachable and cause large swathes of the GMF to be
> > emitted into the module CMI, despite no code in the actual module
> > purview referencing it.
> > 
> > This patch fixes this by also remembering the value of module_kind when
> > the instantiation was deferred, and restoring it when doing this
> > deferred instantiation.  That way newly instantiated declarations
> > appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
> > instantiation was required, meaning that GMF entities won't be counted
> > as reachable unless referenced by an actually reachable entity.
> > 
> > Note that purviewness and attachment etc. is generally only determined
> > by the base template: this is purely for determining whether a
> > specialisation was declared in the module purview and hence whether it
> > should be streamed out.  See the comment on 'set_instantiating_module'.
> > 
> > PR c++/114630
> > PR c++/114795
> > 
> > gcc/cp/ChangeLog:
> > 
> > * cp-tree.h (struct tinst_level): Add field for tracking
> > module_kind.
> > * pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
> > (reopen_tinst_level): Restore module_kind from level.
> > (instantiate_pending_templates): Save and restore module_kind so
> > it isn't affected by reopen_tinst_level.
> 
> LGTM.  Another approach is to instantiate all so-far deferred
> instantiations and vtables once we reach the start of the module
> purview, but your approach is much cleaner.
> 
> Note that deferred instantiation can induce more deferred instantiation,
> but your approach will do the right thing here (module_kind will be
> inherited from the point of instantiation).
> 
> What if an instantiation is needed from both the GMF and the module
> purview?  Then IIUC it'll be instantiated as if from the GMF, which
> seems right to me.
> 

Hm..., so I believe it'll be marked according to whichever instantiates
it "first", so if e.g. deferred from GMF and then instantiated
non-deferred from purview it'll be marked purview (and the deferred
instantiation will be skipped as it's already instantiated).  This could
mean it gets unnecessarily emitted if it only got instantiated because
it got used in e.g. a non-inline function body, I suppose; but that's
true in general actually, at the moment.

Maybe then a better approach would be to instead always use the
DECL_MODULE_PURVIEW_P of the instantiating template instead of the
global 'module_purview_p' function in 'set_instantiating_module'?
I think that should still make sure that instantiations are emitted
when they need to be (because they'll be reachable from a declaration
in the purview): I might try to experiment with something like this.

> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/modules/gmf-3.C: New test.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/cp-tree.h |  3 +++
> >  gcc/cp/pt.cc |  4 
> >  gcc/testsuite/g++.dg/modules/gmf-3.C | 13 +
> >  3 files changed, 20 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C
> > 
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 1938ada0268..0e619120ccc 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -6626,6 +6626,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
> >/* The location where the template is instantiated.  */
> >location_t locus;
> >  
> > +  /* The module kind where the template is instantiated. */
> > +  unsigned module_kind;
> > +
> >/* errorcount + sorrycount when we pushed this level.  */
> >unsigned short errors;
> >  
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index 1c3eef60c06..401aa92bc3e 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -11277,6 +11277,7 @@ push_tinst_level_loc (tree tldcl, tree targs, 
> > location_t loc)
> >new_level->tldcl = tldcl;
> >new_level->targs = targs;
> >new_level->locus = loc;
> > +  new_level->module_kind = module_kind;
> >new_level->errors = errorcount + sorrycount;
> >new_level->next = NULL;
> >new_level->refcount = 0;
> > @@ -11345,6 +11346,7 @@ reopen_tinst_level (struct tinst_level *level)
> >for (t = level; t; t = t->next)
> >  ++tinst_depth;
> >  
> > +  module_kind = level->module_kind;
> >set_refcount_ptr (current_tinst_level, level);
> >pop_tinst_level ();
> >if (current_tinst_level)
> > @@ -27442,6 +27444,7 @@ instantiate_pending_templates (int retries)
> >  

Re: [PATCH] c++/modules: Fix dangling pointer with imported_temploid_friends

2024-05-01 Thread Nathaniel Shead
On Wed, May 01, 2024 at 09:57:38AM -0400, Patrick Palka wrote:
> 
> On Wed, 1 May 2024, Nathaniel Shead wrote:
> 
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
> > later 14.2)?  I don't think making it a GTY root is necessary but I felt
> > perhaps better to be safe than sorry.
> > 
> > Potentially another approach would be to use DECL_UID instead like how
> > entity_map does; would that be preferable?
> > 
> > -- >8 --
> > 
> > I got notified by Linaro CI and by checking testresults that there seems
> > to be some occasional failures in tpl-friend-4_b.C on some architectures
> > and standards modes since r15-59-gb5f6a56940e708.  I haven't been able
> > to reproduce but looking at the backtrace I suspect the issue is that
> > we're adding to the 'imported_temploid_friend' map a decl that is
> > ultimately discarded, which then has its address reused by a later decl
> > causing a failure in the assert in 'set_originating_module'.
> > 
> > This patch attempts to fix the issue in two ways: by ensuring that we
> > only store the decl if we know it's a new decl (and hence won't be
> > discarded), and by making the imported_temploid_friends map a GTY root
> > so that even if the decl does get discarded later the address isn't
> > reused.
> > 
> > gcc/cp/ChangeLog:
> > 
> > * module.cc (imported_temploid_friends): Mark GTY, and...
> > (init_modules): ...allocate from GGC.
> > (trees_in::decl_value): Only write to imported_temploid_friends
> > for new decls.
> > 
> > Signed-off-by: Nathaniel Shead 
> > ---
> >  gcc/cp/module.cc | 7 ---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> > index 5b8ff5bc483..37d38bb9654 100644
> > --- a/gcc/cp/module.cc
> > +++ b/gcc/cp/module.cc
> > @@ -2731,7 +2731,7 @@ static keyed_map_t *keyed_table;
> > need to be attached to the same module as the temploid.  This maps
> > these decls to the temploid they are instantiated them, as there is
> > no other easy way to get this information.  */
> > -static hash_map *imported_temploid_friends;
> > +static GTY(()) hash_map *imported_temploid_friends;
> >  
> >  //
> >  /* Tree streaming.   The tree streaming is very specific to the tree
> > @@ -8327,7 +8327,8 @@ trees_in::decl_value ()
> >if (TREE_CODE (inner) == FUNCTION_DECL
> >|| TREE_CODE (inner) == TYPE_DECL)
> >  if (tree owner = tree_node ())
> > -  imported_temploid_friends->put (decl, owner);
> > +  if (is_new)
> > +   imported_temploid_friends->put (decl, owner);
> 
> Hmm, I'm not seeing this code path getting reached for tpl-friend-4_b.C.
> It seems we're instead adding to imported_temploid_friends from
> propagate_defining_module, during tsubst_friend_function.
> 
> What seems to be happening is that we we first tsubst_friend_function
> 'foo' from TPL, and then we tsubst_friend_function 'foo' from DEF,
> which ends up calling duplicate_decls, which ggc_frees this 'foo'
> redeclaration that is still present in the imported_temploid_friends map.
> 
> So I don't think marking imported_temploid_friends as a GC root would
> help with this situation.  If we want to keep imported_temploid_friends
> as a tree -> tree map, I think we just need to ensure that a decl
> is removed from the map upon getting ggc_free'd from e.g.  duplicate_decls.
> 
> But it seems simpler to use DECL_UID as the key instead, since those
> never get reused even after the decl gets ggc_free'd IIUC.
> 

Ah right, thanks for digging into that further.  Yup OK, I think
probably the DECL_UID route feels safer to me then in case there are
other places where a decl might be explicitly freed.

Looking at tree.cc it looks like the relevant function is
'allocate_decl_uid' which shouldn't reuse UIDs until 2^32 decls have
been created, so we should be safe on the reuse front.

I'll draft and test a patch for that tomorrow morning.

> >  
> >/* Regular typedefs will have a NULL TREE_TYPE at this point.  */
> >unsigned tdef_flags = 0;
> > @@ -20523,7 +20524,7 @@ init_modules (cpp_reader *reader)
> >entity_map = new entity_map_t (EXPERIMENT (1, 400));
> >vec_safe_reserve (entity_ary, EXPERIMENT (1, 400));
> >imported_temploid_friends
> > -   = new hash_map (EXPERIMENT (1, 400));
> > +   = hash_map::create_ggc (EXPERIMENT (1, 400));
> >  }
> >  
> >  #if CHECKING_P
> > -- 
> > 2.43.2
> > 
> > 
> 


Re: [PATCH 3/4] c++/modules: Also track module purview from deferred vtable instantiation [PR114630]

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Nathaniel Shead wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

LGTM

> 
> -- >8 --
> 
> Similarly to in the previous commit, templated virtual functions are
> sometimes not instantiated until after parsing has completed.  This
> means that any new declarations they instantiate are incorrectly marked
> as being in the module purview, causing them to not be discarded from
> the GMF.
> 
>   PR c++/114630
>   PR c++/114795
> 
> gcc/cp/ChangeLog:
> 
>   * decl2.cc (mark_vtable_entries): Set module purview of deferred
>   instantiations from the function decl.
>   (c_parse_final_cleanups): Save and restore module_kind.
> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/modules/gmf-4.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/decl2.cc  | 11 +--
>  gcc/testsuite/g++.dg/modules/gmf-4.C | 27 +++
>  2 files changed, 36 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/modules/gmf-4.C
> 
> diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
> index 806a2a4bc69..0115a6b1cc9 100644
> --- a/gcc/cp/decl2.cc
> +++ b/gcc/cp/decl2.cc
> @@ -2210,6 +2210,11 @@ mark_vtable_entries (tree decl, vec 
> _vtables)
>   location, as we're called from c_parse_final_cleanups, which
>   takes care of that.  */
>input_location = DECL_SOURCE_LOCATION (fn);
> +  /* Similarly, any deferred instantiations should have the same
> +  module purview as this function.  */
> +  module_kind &= ~MK_PURVIEW;
> +  if (DECL_LANG_SPECIFIC (fn) && DECL_MODULE_PURVIEW_P (fn))
> + module_kind |= MK_PURVIEW;
>mark_used (fn);
>  }
>  }
> @@ -5085,6 +5090,7 @@ c_parse_final_cleanups (void)
>tree decl;
>  
>locus_at_end_of_parsing = input_location;
> +  unsigned module_kind_at_end_of_parsing = module_kind;
>/* We're done parsing.  */
>at_eof = 1;
>  
> @@ -5177,9 +5183,10 @@ c_parse_final_cleanups (void)
>   reconsider = true;
>   keyed_classes->unordered_remove (i);
> }
> -  /* The input_location may have been changed during marking of
> -  vtable entries.  */
> +  /* The input_location and module_kind may have been changed
> +  during marking of vtable entries.  */
>input_location = locus_at_end_of_parsing;
> +  module_kind = module_kind_at_end_of_parsing;
>  
>/* Write out needed type info variables.  We have to be careful
>looping through unemitted decls, because emit_tinfo_decl may
> diff --git a/gcc/testsuite/g++.dg/modules/gmf-4.C 
> b/gcc/testsuite/g++.dg/modules/gmf-4.C
> new file mode 100644
> index 000..c95bc782cea
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/gmf-4.C
> @@ -0,0 +1,27 @@
> +// PR c++/114630
> +// { dg-additional-options "-fmodules-ts -Wno-global-module 
> -fdump-lang-module" }
> +// { dg-module-cmi M }
> +
> +// Deferred instantiation of GM virtual functions should not place
> +// newly discovered declarations in the module purview
> +
> +module;
> +
> +template 
> +void go() {
> +  extern T fn_decl();
> +}
> +
> +template 
> +struct S {
> +  virtual void f() {
> +go();
> +  }
> +};
> +
> +S s;
> +
> +export module M;
> +
> +// The whole GMF should be discarded here
> +// { dg-final { scan-lang-dump "Wrote 0 clusters" module } }
> -- 
> 2.43.2
> 
> 



Re: [PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Patrick Palka
On Wed, 1 May 2024, Nathaniel Shead wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?
> 
> -- >8 --
> 
> When calling instantiate_pending_templates at end of parsing, any new
> functions that are instantiated from this point have their module
> purview set based on the current value of module_kind.
> 
> This is unideal, however, as the modules code will then treat these
> instantiations as reachable and cause large swathes of the GMF to be
> emitted into the module CMI, despite no code in the actual module
> purview referencing it.
> 
> This patch fixes this by also remembering the value of module_kind when
> the instantiation was deferred, and restoring it when doing this
> deferred instantiation.  That way newly instantiated declarations
> appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
> instantiation was required, meaning that GMF entities won't be counted
> as reachable unless referenced by an actually reachable entity.
> 
> Note that purviewness and attachment etc. is generally only determined
> by the base template: this is purely for determining whether a
> specialisation was declared in the module purview and hence whether it
> should be streamed out.  See the comment on 'set_instantiating_module'.
> 
>   PR c++/114630
>   PR c++/114795
> 
> gcc/cp/ChangeLog:
> 
>   * cp-tree.h (struct tinst_level): Add field for tracking
>   module_kind.
>   * pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
>   (reopen_tinst_level): Restore module_kind from level.
>   (instantiate_pending_templates): Save and restore module_kind so
>   it isn't affected by reopen_tinst_level.

LGTM.  Another approach is to instantiate all so-far deferred
instantiations and vtables once we reach the start of the module
purview, but your approach is much cleaner.

Note that deferred instantiation can induce more deferred instantiation,
but your approach will do the right thing here (module_kind will be
inherited from the point of instantiation).

What if an instantiation is needed from both the GMF and the module
purview?  Then IIUC it'll be instantiated as if from the GMF, which
seems right to me.

> 
> gcc/testsuite/ChangeLog:
> 
>   * g++.dg/modules/gmf-3.C: New test.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/cp-tree.h |  3 +++
>  gcc/cp/pt.cc |  4 
>  gcc/testsuite/g++.dg/modules/gmf-3.C | 13 +
>  3 files changed, 20 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C
> 
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 1938ada0268..0e619120ccc 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -6626,6 +6626,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
>/* The location where the template is instantiated.  */
>location_t locus;
>  
> +  /* The module kind where the template is instantiated. */
> +  unsigned module_kind;
> +
>/* errorcount + sorrycount when we pushed this level.  */
>unsigned short errors;
>  
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 1c3eef60c06..401aa92bc3e 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -11277,6 +11277,7 @@ push_tinst_level_loc (tree tldcl, tree targs, 
> location_t loc)
>new_level->tldcl = tldcl;
>new_level->targs = targs;
>new_level->locus = loc;
> +  new_level->module_kind = module_kind;
>new_level->errors = errorcount + sorrycount;
>new_level->next = NULL;
>new_level->refcount = 0;
> @@ -11345,6 +11346,7 @@ reopen_tinst_level (struct tinst_level *level)
>for (t = level; t; t = t->next)
>  ++tinst_depth;
>  
> +  module_kind = level->module_kind;
>set_refcount_ptr (current_tinst_level, level);
>pop_tinst_level ();
>if (current_tinst_level)
> @@ -27442,6 +27444,7 @@ instantiate_pending_templates (int retries)
>  {
>int reconsider;
>location_t saved_loc = input_location;
> +  unsigned saved_module_kind = module_kind;
>  
>/* Instantiating templates may trigger vtable generation.  This in turn
>   may require further template instantiations.  We place a limit here
> @@ -27532,6 +27535,7 @@ instantiate_pending_templates (int retries)
>while (reconsider);
>  
>input_location = saved_loc;
> +  module_kind = saved_module_kind;
>  }
>  
>  /* Substitute ARGVEC into T, which is a list of initializers for
> diff --git a/gcc/testsuite/g++.dg/modules/gmf-3.C 
> b/gcc/testsuite/g++.dg/modules/gmf-3.C
> new file mode 100644
> index 000..e52ae904ea9
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/modules/gmf-3.C
> @@ -0,0 +1,13 @@
> +// PR c++/114630
> +// { dg-additional-options "-fmodules-ts -Wno-global-module 
> -fdump-lang-module" }
> +// { dg-module-cmi M }
> +
> +module;
> +template  struct allocator {
> +  allocator() {}
> +};
> +template class allocator;
> +export module M;
> +
> +// The whole GMF should be discarded here
> +// { dg-final { scan-lang-dump "Wrote 0 clusters" module 

Re: [wwwdocs] Porting-to-14: Mention new pragma GCC Target behavior

2024-05-01 Thread Gerald Pfeifer
On Tue, 30 Apr 2024, Martin Jambor wrote:
> +Pragma GCC Target now affects preprocessor 
> symbols

Note the id: should be "gcc-target-pragma", though I even suggest to 
simplify and say "target-pragma".

> +The behavior of pragma GCC Target and specifically how it affects ISA

Seconding Jakub's
 
  "And here as well, perhaps even #pragma GCC target."

> +macros has changed in GCC 14.  In GCC 13 and older, the GCC
> +target pragma defined and undefined corresponding ISA macros in
> +C when using integrated preprocessor during compilation but not when

"...the integrated preprocessor..."

> +preprocessor was invoked as a separate step or when using -save-temps.

"...the preprocessor..."

and -save-temps, or better "the -save-temps 
option".

> +This can lead to different behavior, especially in C++.  For example,
> +functions the C++ snippet below will be (silently) compiled for an
> +incorrect instruction set by GCC 14.

"functions" above looks like it's extraneous and should be skipped?

> +  /* With GCC 14, __AVX2__ here will always be defined and pop_options
> +  never called. */
> +  #if ! __AVX2__
> +  #pragma GCC pop_options
> +  #endif

Maybe a bit subtle, I would not say a #pragma is called; how about invoked 
or activated?

> +
> +The fix in this case would be to remember
> +whether pop_options needs to be performed in a new
> +user-defined macro.

"The fix in this case is to remember" (or "...remembering...")

Gerald


Re: [PATCH v3 1/4] Allow flexible array members in unions and alone in structures [PR53548]

2024-05-01 Thread Qing Zhao


On Apr 30, 2024, at 17:55, Kees Cook  wrote:

On Tue, Apr 30, 2024 at 05:51:20PM -0400, Jason Merrill wrote:
On 4/30/24 14:45, Qing Zhao wrote:


On Apr 30, 2024, at 15:27, Jason Merrill  wrote:

On 4/30/24 07:58, Qing Zhao wrote:
The request for GCC to accept that the C99 flexible array member can be
in a union or alone in a structure has been made a long time ago
around 2012
for supporting several practical cases including glibc.
A GCC PR has been opened for such request at that time:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53548
However, this PR was closed as WONTFIX around 2015 due to the
following reason:
"there is an existing extension that makes the requested
functionality possible"
i.e GCC fully supported that the zero-length array can be in a
union or alone
in a structure for a long time. (though I didn't see any
official documentation
on such extension)
It's reasonable to close PR53548 at that time since zero-length
array extension
can be used for such purpose.
However, since GCC13, in order to improve the C/C++ security, we
introduced
-fstrict-flex-arrays=n to gradually eliminate the "fake flexible array"
usages from C/C++ source code. As a result, zero-length arrays eventually
will be replaced by C99 flexiable array member completely.
Therefore, GCC needs to explicitly allow such extensions directly for C99
flexible arrays, since flexable array member in unions or alone
in structs
are common code patterns in active use by the Linux kernel (and
other projects).
For example, these do not error by default with GCC:
union one {
  int a;
  int b[0];
};
union two {
  int a;
  struct {
struct { } __empty;
int b[];
  };
};
But these do:
union three {
  int a;
  int b[];
};
struct four {
  int b[];
}
Clang has supported such extensions since March, 2024
https://github.com/llvm/llvm-project/pull/84428
GCC should also support such extensions. This will allow for
a seamless transition for code bases away from zero-length arrays without
losing existing code patterns.
gcc/ChangeLog:
* doc/extend.texi: Add documentation for Flexible Array Members in
Unions and Flexible Array Members alone in Structures.
---
 gcc/doc/extend.texi | 34 ++
 1 file changed, 34 insertions(+)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 7b54a241a7bf..cba98c8aadd7 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -42,6 +42,8 @@ extensions, accepted by GCC in C90 mode and in C++.
 * Named Address Spaces::Named address spaces.
 * Zero Length:: Zero-length arrays.
 * Empty Structures::Structures with no members.
+* Flexible Array Members in Unions::  Unions with Flexible
Array Members.
+* Flexible Array Members alone in Structures::  Structures with
only Flexible Array Members.
 * Variable Length:: Arrays whose length is computed at run time.
 * Variadic Macros:: Macros with a variable number of arguments.
 * Escaped Newlines::Slightly looser rules for escaped newlines.
@@ -1873,6 +1875,38 @@ The structure has size zero.  In C++,
empty structures are part
 of the language.  G++ treats empty structures as if they had a single
 member of type @code{char}.
 +@node Flexible Array Members in Unions
+@section Unions with Flexible Array Members
+@cindex unions with flexible array members
+@cindex unions with FAMs
+
+GCC permits a C99 flexible array member (FAM) to be in a union:
+
+@smallexample
+union with_fam @{
+  int a;
+  int b[];
+@};
+@end smallexample
+
+If all the members of a union are flexible array member, the size of

It’s for the following case:

union with_fam_3 {
  char a[];
  int b[];
}

And also include:  (the only member of a union is a flexible array
member as you mentioned below)

union with_fam_1 {
  char a[];
}

So, I think the original sentence:

“If all the members of a union are flexible array member, the size of”

Should be better than the below:

"If the only member of a union is a flexible array member”

Makes sense, but then it should be "members" both times rather than
"members" and then "member".

"If every member of a union is a flexible array, the size ..." ?

Yes, I have updated the doc as this. -:).

Qing

--
Kees Cook



Re: [PATCH] c++/modules: Fix dangling pointer with imported_temploid_friends

2024-05-01 Thread Patrick Palka


On Wed, 1 May 2024, Nathaniel Shead wrote:

> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk (and
> later 14.2)?  I don't think making it a GTY root is necessary but I felt
> perhaps better to be safe than sorry.
> 
> Potentially another approach would be to use DECL_UID instead like how
> entity_map does; would that be preferable?
> 
> -- >8 --
> 
> I got notified by Linaro CI and by checking testresults that there seems
> to be some occasional failures in tpl-friend-4_b.C on some architectures
> and standards modes since r15-59-gb5f6a56940e708.  I haven't been able
> to reproduce but looking at the backtrace I suspect the issue is that
> we're adding to the 'imported_temploid_friend' map a decl that is
> ultimately discarded, which then has its address reused by a later decl
> causing a failure in the assert in 'set_originating_module'.
> 
> This patch attempts to fix the issue in two ways: by ensuring that we
> only store the decl if we know it's a new decl (and hence won't be
> discarded), and by making the imported_temploid_friends map a GTY root
> so that even if the decl does get discarded later the address isn't
> reused.
> 
> gcc/cp/ChangeLog:
> 
>   * module.cc (imported_temploid_friends): Mark GTY, and...
>   (init_modules): ...allocate from GGC.
>   (trees_in::decl_value): Only write to imported_temploid_friends
>   for new decls.
> 
> Signed-off-by: Nathaniel Shead 
> ---
>  gcc/cp/module.cc | 7 ---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
> index 5b8ff5bc483..37d38bb9654 100644
> --- a/gcc/cp/module.cc
> +++ b/gcc/cp/module.cc
> @@ -2731,7 +2731,7 @@ static keyed_map_t *keyed_table;
> need to be attached to the same module as the temploid.  This maps
> these decls to the temploid they are instantiated them, as there is
> no other easy way to get this information.  */
> -static hash_map *imported_temploid_friends;
> +static GTY(()) hash_map *imported_temploid_friends;
>  
>  //
>  /* Tree streaming.   The tree streaming is very specific to the tree
> @@ -8327,7 +8327,8 @@ trees_in::decl_value ()
>if (TREE_CODE (inner) == FUNCTION_DECL
>|| TREE_CODE (inner) == TYPE_DECL)
>  if (tree owner = tree_node ())
> -  imported_temploid_friends->put (decl, owner);
> +  if (is_new)
> + imported_temploid_friends->put (decl, owner);

Hmm, I'm not seeing this code path getting reached for tpl-friend-4_b.C.
It seems we're instead adding to imported_temploid_friends from
propagate_defining_module, during tsubst_friend_function.

What seems to be happening is that we we first tsubst_friend_function
'foo' from TPL, and then we tsubst_friend_function 'foo' from DEF,
which ends up calling duplicate_decls, which ggc_frees this 'foo'
redeclaration that is still present in the imported_temploid_friends map.

So I don't think marking imported_temploid_friends as a GC root would
help with this situation.  If we want to keep imported_temploid_friends
as a tree -> tree map, I think we just need to ensure that a decl
is removed from the map upon getting ggc_free'd from e.g.  duplicate_decls.

But it seems simpler to use DECL_UID as the key instead, since those
never get reused even after the decl gets ggc_free'd IIUC.

>  
>/* Regular typedefs will have a NULL TREE_TYPE at this point.  */
>unsigned tdef_flags = 0;
> @@ -20523,7 +20524,7 @@ init_modules (cpp_reader *reader)
>entity_map = new entity_map_t (EXPERIMENT (1, 400));
>vec_safe_reserve (entity_ary, EXPERIMENT (1, 400));
>imported_temploid_friends
> - = new hash_map (EXPERIMENT (1, 400));
> + = hash_map::create_ggc (EXPERIMENT (1, 400));
>  }
>  
>  #if CHECKING_P
> -- 
> 2.43.2
> 
> 



Re: [PATCH][wwwdocs] Improve grammar for AVR changes in GCC 14

2024-05-01 Thread Jonathan Wakely
On Mon, 22 Apr 2024 at 12:35, Georg-Johann Lay  wrote:
>
> Am 22.04.24 um 12:04 schrieb Jonathan Wakely:
> > OK for wwwdocs?
>
> For me it's ok (I am not a native speaker though,
> which is the reason the typos are there to begin with).

I've pushed this now.


>
> Johann
>
> >   htdocs/gcc-14/changes.html | 16 
> >   1 file changed, 8 insertions(+), 8 deletions(-)
> >
> > diff --git a/htdocs/gcc-14/changes.html b/htdocs/gcc-14/changes.html
> > index 9509487c..21d33db8 100644
> > --- a/htdocs/gcc-14/changes.html
> > +++ b/htdocs/gcc-14/changes.html
> > @@ -696,13 +696,13 @@ a work-in-progress.
> >   AVR
> >   
> > On AVR64* and AVR128* devices, read-only data is now located in 
> > program
> > -memory per default and no more in RAM.
> > +memory per default and no longer in RAM.
> >   
> > Only a 32KiB block of program memory can be used to store
> >   and access .rodata in that way. Which block is used can be selected
> > - by defining symbol __flmap.
> > + by defining the symbol __flmap.
> >   As an alternative, the byte address of the block can be specified
> > - by symbol __RODATA_FLASH_START__ which takes
> > + by the symbol __RODATA_FLASH_START__ which takes
> >   precedence over __flmap.
> >   For example, linking with
> >   -Wl,--defsym,__RODATA_FLASH_START__=32k
> > @@ -715,9 +715,9 @@ a work-in-progress.
> >   href="https://github.com/avrdudes/avr-libc/issues/931;>#931
> >   can be used. The latter initializes NVMCTRL_CTRLB.FLMAP
> >   in the startup code and according to the value
> > - of__flmap resp.
> > + of__flmap or
> >   __RODATA_FLASH_START__.
> > -  When AVR-LibC with#931 is used, then defining symbol
> > +  When AVR-LibC with#931 is used, then defining the symbol
> >   __flmap_lock to a non-zero value will set bit
> >   NVMCTRL_CTRLB.FLMAPLOCK. This will protect
> >   NVMCTRL_CTRLB.FLMAP from any further changes 
> > @@ -726,7 +726,7 @@ a work-in-progress.
> >   can be used:
> >   __asm (".global __flmap_lock"  "\n\t"
> >  "__flmap_lock = 1");
> > -  When you do not want the code from#931, then define global
> > +  When you do not want the code from#931, then define a 
> > global
> >   symbol __do_flmap_init and the linker will not pull in
> >   that code from libmcu.a any more.
> > In order to return to the old placement of read-only data in 
> > RAM,
> > @@ -736,7 +736,7 @@ __asm (".global __flmap_lock"  "\n\t"
> > functionality.
> > 
> > Read-only data is located in output section 
> > .rodata,
> > - wheras it is part of .text when located in RAM.
> > + whereas it is part of .text when located in RAM.
> > The feature is only available when the compiler is configured
> >   with a version of Binutils that implements
> >   https://sourceware.org/PR31124;>PR31124, which is the
> > @@ -784,7 +784,7 @@ __asm (".global __flmap_lock"  "\n\t"
> > 
> >   On the Reduced Tiny devices,
> >   the meaning of register constraint"w" has been 
> > changed.
> > -It containts now the registers R24R31 like it is the case for 
> > all
> > +It now constrains the registers R24R31 as is the case for all
> >   the other devices.
> > 
> >   
>



Fwd: [PATCH V2 0/4] Add DF_LIVE_SUBREG data and apply to IRA and LRA

2024-05-01 Thread Vladimir Makarov


I am resending this message as the previous one had one wrong response 
email address "gcc-pat...@gcc.gnu.org"


 Forwarded Message 
Subject: 	Re: [PATCH V2 0/4] Add DF_LIVE_SUBREG data and apply to IRA 
and LRA

Date:   Wed, 1 May 2024 08:35:27 -0400
From:   Vladimir Makarov 
To: 	Lehua Ding , gcc-pat...@gcc.gnu.org, 
richard.sandif...@arm.com

CC: juzhe.zh...@rivai.ai, shuo.c...@rivai.ai, jin@rivai.ai




On 4/24/24 06:01, Lehua Ding wrote:

Hi Vladimir and Richard,

These patches are used to add a new data flow DF_LIVE_SUBREG,
which will track subreg liveness and then apply it to IRA and LRA
passes (enabled via -O3 or -ftrack-subreg-liveness). These patches
are for GCC 15. And these codes are pushed to the devel/subreg-coalesce
branch. In addition, my colleague Shuo Chen will also be involved in some
of the remain work, thank you for your support.

Thank you for creation of the branch.  It helped me a lot.

These patches are separated from the subreg-coalesce patches submitted
a few months ago. I refactored the code according to comments. The next
patches will support subreg coalesce base on they. Here are some data
abot build time of SPEC INT 2017 (x86-64 target):

Thank you for refactoring patches.

baseline baseline(+track-subreg-liveness)
specint2017 build time : 1892s 1883s

Interesting and surprisingly unexpected improvement.

Regarding build times, I've run it a few times, but they all seem to take
much less time. Since the difference is small, it's possible that it's 
just

a change in environment. But it's theoretically possible, since supporting
subreg-liveness could have reduced the number of living regs.

For memory usage, I trided PR 69609 by valgrind, peak memory size grow 
from

2003910656 to 2003947520, very small increase.


I'll soon finish code review of IRA and LRA changes and send it today or 
tomorrow.


But In brief I have no objections to the patches, just some minor 
requests to improve them.


Re: [PATCH] wwwdocs: contribute.html: Update consensus on patch content.

2024-05-01 Thread Carlos O'Donell
On 4/25/24 14:32, Richard Biener wrote:
> 
> 
>> Am 25.04.2024 um 17:44 schrieb Carlos O'Donell :
>>
>> Discussion is here:
>> https://inbox.sourceware.org/gcc/CAPS5khZeWkAD=v8ka9g5eecdnk3bdhfnzjumpvc+hedmkvj...@mail.gmail.com/
>>
>> Rough consensus from Jakub Jelinek, Richard Biener and others is
>> that maintainers are for the change.
> 
> Ok

Pushed.

Thanks for helping me move this forward.

I look forward to pre-commit CI across all the projects.

Helping Linaro make forward progress here is my primary goal.

-- 
Cheers,
Carlos.



[PATCH] c++: Implement modules ABI for vtable emissions

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

This patch implements the changes described in
https://github.com/itanium-cxx-abi/cxx-abi/pull/171.

One restriction that is lifted in the ABI that hasn't been updated here
is that the ABI no longer requires unique vtables to be emitted with
vague linkage.  I haven't changed this behaviour for this patch, but in
the future we should probably look into changing the relevant target
hook ('class_data_always_comdat') to default to 'false'.

Since the ABI for vtables attached to named modules no longer depends on
key methods, this also resolves the issue described in PR c++/105224.

PR c++/105224

gcc/cp/ChangeLog:

* class.cc (finish_struct_1): Also push classes attached to a
module into the 'keyed_classes' list.
* decl.cc (record_key_method_defined): Don't push classes
attached to a named module into the 'keyed_classes' list.
* module.cc (trees_in::read_class_def): Likewise.
* decl2.cc (import_export_class): Uniquely emit vtables for
non-template classes attached to a named module.
(vtables_uniquely_emitted): New function.
(import_export_decl): Update comments. Update with knowledge
about new kinds of uniquely emitted vtables.

gcc/testsuite/ChangeLog:

* g++.dg/modules/virt-2_a.C: Update linkage requirements.
* g++.dg/modules/virt-2_b.C: Likewise.
* g++.dg/modules/virt-2_c.C: Likewise.
* g++.dg/modules/virt-4_a.C: New test.
* g++.dg/modules/virt-4_b.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/class.cc |   7 +-
 gcc/cp/decl.cc  |   8 +-
 gcc/cp/decl2.cc | 102 
 gcc/cp/module.cc|  12 ++-
 gcc/testsuite/g++.dg/modules/virt-2_a.C |   3 -
 gcc/testsuite/g++.dg/modules/virt-2_b.C |   9 ++-
 gcc/testsuite/g++.dg/modules/virt-2_c.C |  10 +--
 gcc/testsuite/g++.dg/modules/virt-4_a.C |  31 +++
 gcc/testsuite/g++.dg/modules/virt-4_b.C |  23 ++
 9 files changed, 151 insertions(+), 54 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/virt-4_a.C
 create mode 100644 gcc/testsuite/g++.dg/modules/virt-4_b.C

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 5f258729940..5ef7c71af61 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -7820,8 +7820,11 @@ finish_struct_1 (tree t)
   /* If a polymorphic class has no key method, we may emit the vtable
 in every translation unit where the class definition appears.  If
 we're devirtualizing, we can look into the vtable even if we
-aren't emitting it.  */
-  if (!CLASSTYPE_KEY_METHOD (t))
+aren't emitting it.
+
+Additionally, if the class is attached to a named module, make sure
+to always emit the vtable in this TU.  */
+  if (!CLASSTYPE_KEY_METHOD (t) || module_attach_p ())
vec_safe_push (keyed_classes, t);
 }
 
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d88e0698652..573cfc7ece5 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -18471,7 +18471,13 @@ record_key_method_defined (tree fndecl)
 {
   tree fnclass = DECL_CONTEXT (fndecl);
   if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
-   vec_safe_push (keyed_classes, fnclass);
+   {
+ tree classdecl = TYPE_NAME (fnclass);
+ /* Classes attached to a named module are already handled.  */
+ if (!DECL_LANG_SPECIFIC (classdecl)
+ || !DECL_MODULE_ATTACH_P (classdecl))
+   vec_safe_push (keyed_classes, fnclass);
+   }
 }
 }
 
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 806a2a4bc69..a883131d175 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2426,17 +2426,26 @@ import_export_class (tree ctype)
   import_export = -1;
   else if (TYPE_POLYMORPHIC_P (ctype))
 {
-  /* The ABI specifies that the virtual table and associated
-information are emitted with the key method, if any.  */
-  tree method = CLASSTYPE_KEY_METHOD (ctype);
-  /* If weak symbol support is not available, then we must be
-careful not to emit the vtable when the key function is
-inline.  An inline function can be defined in multiple
-translation units.  If we were to emit the vtable in each
-translation unit containing a definition, we would get
-multiple definition errors at link-time.  */
-  if (method && (flag_weak || ! DECL_DECLARED_INLINE_P (method)))
-   import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
+  tree cdecl = TYPE_NAME (ctype);
+  if (DECL_LANG_SPECIFIC (cdecl) && DECL_MODULE_ATTACH_P (cdecl))
+   /* For class types attached to a named module, the ABI specifies
+  that the tables are uniquely emitted in the object for the
+  module unit in which it is defined.  */
+   import_export = (DECL_MODULE_IMPORT_P (cdecl) ? -1 : 1);
+ 

Re: [PATCH] wwwdocs: Add note to changes.html for __has_{feature,extension}

2024-05-01 Thread Gerald Pfeifer
On Fri, 26 Apr 2024, Marek Polacek wrote:
> Thanks, I think you can go ahead with this.

Agreed, thanks.

Alex, if you agree, how about simplifying

  +This is primarily intended to aid the portability of code written
  +against Clang.

to

  +This is aids the portability of code written against Clang.

or similar? (Feel free to simply push such a change.)

Gerald


[PATCH 4/4] c++: Add new xtreme-header testcase for GMF discarding

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

Another thought would be to replace xtreme-header.h with  so
that we don't need to keep it up-to-date in the future.  But this patch just
does the obviously correct thing.

-- >8 --

This new testcase helps verify that the issues discovered in PR114630
with GMF entries being inappropriately emitted into the module CMI don't
regress, at least for the kinds of code used in the standard library
headers.

This also updates the base xtreme-header.h file to include new header
files that are now available.

gcc/testsuite/ChangeLog:

* g++.dg/modules/xtreme-header.h: Update.
* g++.dg/modules/xtreme-header-8.C: New test.

Signed-off-by: Nathaniel Shead 
---
 .../g++.dg/modules/xtreme-header-8.C  |  9 +++
 gcc/testsuite/g++.dg/modules/xtreme-header.h  | 24 ---
 2 files changed, 25 insertions(+), 8 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/xtreme-header-8.C

diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header-8.C 
b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C
new file mode 100644
index 000..b0d0ae87534
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header-8.C
@@ -0,0 +1,9 @@
+// { dg-additional-options "-fmodules-ts -fdump-lang-module" }
+// { dg-module-cmi empty }
+
+module;
+#include "xtreme-header.h"
+export module empty;
+
+// The whole GMF should be discarded here
+// { dg-final { scan-lang-dump "Wrote 0 clusters" module } }
diff --git a/gcc/testsuite/g++.dg/modules/xtreme-header.h 
b/gcc/testsuite/g++.dg/modules/xtreme-header.h
index 3147aaf00f4..8d95218755a 100644
--- a/gcc/testsuite/g++.dg/modules/xtreme-header.h
+++ b/gcc/testsuite/g++.dg/modules/xtreme-header.h
@@ -89,7 +89,6 @@
 
 // C++20
 #if __cplusplus > 201703
-#if 1
 #include 
 #include 
 #include 
@@ -98,6 +97,7 @@
 #if __cpp_coroutines
 #include 
 #endif
+#include 
 #include 
 #include 
 #include 
@@ -106,24 +106,32 @@
 #include 
 #include 
 #include 
-#if 0
-// Unimplemented
-#include 
-#endif
-#endif
 #endif
 
 // C++23
 #if __cplusplus > 202002L
 #include 
+#include 
+#include 
 #include 
 #include 
+#include 
 #if 0
 // Unimplemented
 #include 
 #include 
-#include 
 #include 
-#include 
+#endif
+#endif
+
+// C++26
+#if __cplusplus > 202302L
+#if 0
+// Unimplemented
+#include 
+#include 
+#include 
+#include 
+#include 
 #endif
 #endif
-- 
2.43.2



[PATCH 3/4] c++/modules: Also track module purview from deferred vtable instantiation [PR114630]

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

Similarly to in the previous commit, templated virtual functions are
sometimes not instantiated until after parsing has completed.  This
means that any new declarations they instantiate are incorrectly marked
as being in the module purview, causing them to not be discarded from
the GMF.

PR c++/114630
PR c++/114795

gcc/cp/ChangeLog:

* decl2.cc (mark_vtable_entries): Set module purview of deferred
instantiations from the function decl.
(c_parse_final_cleanups): Save and restore module_kind.

gcc/testsuite/ChangeLog:

* g++.dg/modules/gmf-4.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/decl2.cc  | 11 +--
 gcc/testsuite/g++.dg/modules/gmf-4.C | 27 +++
 2 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-4.C

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 806a2a4bc69..0115a6b1cc9 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2210,6 +2210,11 @@ mark_vtable_entries (tree decl, vec 
_vtables)
  location, as we're called from c_parse_final_cleanups, which
  takes care of that.  */
   input_location = DECL_SOURCE_LOCATION (fn);
+  /* Similarly, any deferred instantiations should have the same
+module purview as this function.  */
+  module_kind &= ~MK_PURVIEW;
+  if (DECL_LANG_SPECIFIC (fn) && DECL_MODULE_PURVIEW_P (fn))
+   module_kind |= MK_PURVIEW;
   mark_used (fn);
 }
 }
@@ -5085,6 +5090,7 @@ c_parse_final_cleanups (void)
   tree decl;
 
   locus_at_end_of_parsing = input_location;
+  unsigned module_kind_at_end_of_parsing = module_kind;
   /* We're done parsing.  */
   at_eof = 1;
 
@@ -5177,9 +5183,10 @@ c_parse_final_cleanups (void)
reconsider = true;
keyed_classes->unordered_remove (i);
  }
-  /* The input_location may have been changed during marking of
-vtable entries.  */
+  /* The input_location and module_kind may have been changed
+during marking of vtable entries.  */
   input_location = locus_at_end_of_parsing;
+  module_kind = module_kind_at_end_of_parsing;
 
   /* Write out needed type info variables.  We have to be careful
 looping through unemitted decls, because emit_tinfo_decl may
diff --git a/gcc/testsuite/g++.dg/modules/gmf-4.C 
b/gcc/testsuite/g++.dg/modules/gmf-4.C
new file mode 100644
index 000..c95bc782cea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-4.C
@@ -0,0 +1,27 @@
+// PR c++/114630
+// { dg-additional-options "-fmodules-ts -Wno-global-module 
-fdump-lang-module" }
+// { dg-module-cmi M }
+
+// Deferred instantiation of GM virtual functions should not place
+// newly discovered declarations in the module purview
+
+module;
+
+template 
+void go() {
+  extern T fn_decl();
+}
+
+template 
+struct S {
+  virtual void f() {
+go();
+  }
+};
+
+S s;
+
+export module M;
+
+// The whole GMF should be discarded here
+// { dg-final { scan-lang-dump "Wrote 0 clusters" module } }
-- 
2.43.2



[PATCH 2/4] c++/modules: Track module purview for deferred instantiations [PR114630]

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

When calling instantiate_pending_templates at end of parsing, any new
functions that are instantiated from this point have their module
purview set based on the current value of module_kind.

This is unideal, however, as the modules code will then treat these
instantiations as reachable and cause large swathes of the GMF to be
emitted into the module CMI, despite no code in the actual module
purview referencing it.

This patch fixes this by also remembering the value of module_kind when
the instantiation was deferred, and restoring it when doing this
deferred instantiation.  That way newly instantiated declarations
appropriately get a DECL_MODULE_PURVIEW_P appropriate for where the
instantiation was required, meaning that GMF entities won't be counted
as reachable unless referenced by an actually reachable entity.

Note that purviewness and attachment etc. is generally only determined
by the base template: this is purely for determining whether a
specialisation was declared in the module purview and hence whether it
should be streamed out.  See the comment on 'set_instantiating_module'.

PR c++/114630
PR c++/114795

gcc/cp/ChangeLog:

* cp-tree.h (struct tinst_level): Add field for tracking
module_kind.
* pt.cc (push_tinst_level_loc): Cache module_kind in new_level.
(reopen_tinst_level): Restore module_kind from level.
(instantiate_pending_templates): Save and restore module_kind so
it isn't affected by reopen_tinst_level.

gcc/testsuite/ChangeLog:

* g++.dg/modules/gmf-3.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/cp-tree.h |  3 +++
 gcc/cp/pt.cc |  4 
 gcc/testsuite/g++.dg/modules/gmf-3.C | 13 +
 3 files changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 1938ada0268..0e619120ccc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6626,6 +6626,9 @@ struct GTY((chain_next ("%h.next"))) tinst_level {
   /* The location where the template is instantiated.  */
   location_t locus;
 
+  /* The module kind where the template is instantiated. */
+  unsigned module_kind;
+
   /* errorcount + sorrycount when we pushed this level.  */
   unsigned short errors;
 
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 1c3eef60c06..401aa92bc3e 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -11277,6 +11277,7 @@ push_tinst_level_loc (tree tldcl, tree targs, 
location_t loc)
   new_level->tldcl = tldcl;
   new_level->targs = targs;
   new_level->locus = loc;
+  new_level->module_kind = module_kind;
   new_level->errors = errorcount + sorrycount;
   new_level->next = NULL;
   new_level->refcount = 0;
@@ -11345,6 +11346,7 @@ reopen_tinst_level (struct tinst_level *level)
   for (t = level; t; t = t->next)
 ++tinst_depth;
 
+  module_kind = level->module_kind;
   set_refcount_ptr (current_tinst_level, level);
   pop_tinst_level ();
   if (current_tinst_level)
@@ -27442,6 +27444,7 @@ instantiate_pending_templates (int retries)
 {
   int reconsider;
   location_t saved_loc = input_location;
+  unsigned saved_module_kind = module_kind;
 
   /* Instantiating templates may trigger vtable generation.  This in turn
  may require further template instantiations.  We place a limit here
@@ -27532,6 +27535,7 @@ instantiate_pending_templates (int retries)
   while (reconsider);
 
   input_location = saved_loc;
+  module_kind = saved_module_kind;
 }
 
 /* Substitute ARGVEC into T, which is a list of initializers for
diff --git a/gcc/testsuite/g++.dg/modules/gmf-3.C 
b/gcc/testsuite/g++.dg/modules/gmf-3.C
new file mode 100644
index 000..e52ae904ea9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/gmf-3.C
@@ -0,0 +1,13 @@
+// PR c++/114630
+// { dg-additional-options "-fmodules-ts -Wno-global-module 
-fdump-lang-module" }
+// { dg-module-cmi M }
+
+module;
+template  struct allocator {
+  allocator() {}
+};
+template class allocator;
+export module M;
+
+// The whole GMF should be discarded here
+// { dg-final { scan-lang-dump "Wrote 0 clusters" module } }
-- 
2.43.2



[PATCH 1/4] c++/modules: Don't emit unused GMF partial specializations [PR114630]

2024-05-01 Thread Nathaniel Shead
Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk?

-- >8 --

The change in r14-8408 to also emit partial specializations in the
global module fragment caused the regression in the linked PR; this
patch fixes this by restricting emitted GM partial specializations to
those that are actually used.

PR c++/114630

gcc/cp/ChangeLog:

* module.cc (depset::hash::add_partial_entities): Mark GM
specializations as unreached.
(depset::hash::find_dependencies): Also reach entities in the
DECL_TEMPLATE_SPECIALIZATIONS list.

gcc/testsuite/ChangeLog:

* g++.dg/modules/partial-3.C: New test.

Signed-off-by: Nathaniel Shead 
---
 gcc/cp/module.cc | 75 +++-
 gcc/testsuite/g++.dg/modules/partial-3.C | 20 +++
 2 files changed, 66 insertions(+), 29 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/partial-3.C

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index fac0301d80e..02b0ab3d687 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13304,14 +13304,22 @@ depset::hash::add_partial_entities (vec 
*partial_classes)
   depset *dep = make_dependency (inner, depset::EK_DECL);
 
   if (dep->get_entity_kind () == depset::EK_REDIRECT)
-   /* We should have recorded the template as a partial
-  specialization.  */
-   gcc_checking_assert (dep->deps[0]->get_entity_kind ()
-== depset::EK_PARTIAL);
+   {
+ dep = dep->deps[0];
+ /* We should have recorded the template as a partial
+specialization.  */
+ gcc_checking_assert (dep->get_entity_kind ()
+  == depset::EK_PARTIAL);
+   }
   else
/* It was an explicit specialization, not a partial one.  */
gcc_checking_assert (dep->get_entity_kind ()
 == depset::EK_SPECIALIZATION);
+
+  /* Only emit GM entities if reached.  */
+  if (!DECL_LANG_SPECIFIC (inner)
+ || !DECL_MODULE_PURVIEW_P (inner))
+   dep->set_flag_bit ();
 }
 }
 
@@ -13632,31 +13640,40 @@ depset::hash::find_dependencies (module_state *module)
  if (!walker.is_key_order ()
  && TREE_CODE (decl) == TEMPLATE_DECL
  && !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
-   /* Mark all the explicit & partial specializations as
-  reachable.  */
-   for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl);
-cons; cons = TREE_CHAIN (cons))
- {
-   tree spec = TREE_VALUE (cons);
-   if (TYPE_P (spec))
- spec = TYPE_NAME (spec);
-   int use_tpl;
-   node_template_info (spec, use_tpl);
-   if (use_tpl & 2)
- {
-   depset *spec_dep = find_dependency (spec);
-   if (spec_dep->get_entity_kind () == EK_REDIRECT)
- spec_dep = spec_dep->deps[0];
-   if (spec_dep->is_unreached ())
- {
-   reached_unreached = true;
-   spec_dep->clear_flag_bit ();
-   dump (dumper::DEPEND)
- && dump ("Reaching unreached specialization"
-  " %C:%N", TREE_CODE (spec), spec);
- }
- }
- }
+   {
+ /* Mark all the explicit & partial specializations as
+reachable.  We search both specialization lists as some
+constrained partial specializations for class types are
+only found in DECL_TEMPLATE_SPECIALIZATIONS.  */
+ auto mark_reached = [this](tree spec)
+   {
+ if (TYPE_P (spec))
+   spec = TYPE_NAME (spec);
+ int use_tpl;
+ node_template_info (spec, use_tpl);
+ if (use_tpl & 2)
+   {
+ depset *spec_dep = find_dependency (spec);
+ if (spec_dep->get_entity_kind () == EK_REDIRECT)
+   spec_dep = spec_dep->deps[0];
+ if (spec_dep->is_unreached ())
+   {
+ reached_unreached = true;
+ spec_dep->clear_flag_bit ();
+ dump (dumper::DEPEND)
+   && dump ("Reaching unreached specialization"
+" %C:%N", TREE_CODE (spec), spec);
+   }
+   }
+   };
+
+ for (tree cons = DECL_TEMPLATE_INSTANTIATIONS (decl);
+  cons; cons = TREE_CHAIN (cons))

[PATCH 0/4] c++/modules: Fix missed GMF discarding

2024-05-01 Thread Nathaniel Shead
This patch series fixes a number of issues with declarations in the GMF not
correctly getting discarded, and ending up in the module CMI.  The most
noticeable outcome of this is users running very quickly into issues with
including a header after those names have already been provided by an 'import';
this should go away once we implement deduplication of textual redefinitions,
but it's still worth discarding as it otherwise inflates the size of the CMI
with unused declarations.

Nathaniel Shead (4):
  c++: Don't emit unused GMF partial specializations [PR114630]
  c++: Track module purview for deferred instantiations [PR114630]
  c++: Also track module purview from deferred vtable instantiation
[PR114630]
  c++: Add new xtreme-header testcase for GMF discarding

 gcc/cp/cp-tree.h  |  3 +
 gcc/cp/decl2.cc   | 11 ++-
 gcc/cp/module.cc  | 75 ---
 gcc/cp/pt.cc  |  4 +
 gcc/testsuite/g++.dg/modules/gmf-3.C  | 13 
 gcc/testsuite/g++.dg/modules/gmf-4.C  | 27 +++
 gcc/testsuite/g++.dg/modules/partial-3.C  | 20 +
 .../g++.dg/modules/xtreme-header-8.C  |  9 +++
 gcc/testsuite/g++.dg/modules/xtreme-header.h  | 24 --
 9 files changed, 147 insertions(+), 39 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-3.C
 create mode 100644 gcc/testsuite/g++.dg/modules/gmf-4.C
 create mode 100644 gcc/testsuite/g++.dg/modules/partial-3.C
 create mode 100644 gcc/testsuite/g++.dg/modules/xtreme-header-8.C

-- 
2.43.2



[pushed] doc: Remove old details on libunwind for ia64-*-hpux*

2024-05-01 Thread Gerald Pfeifer
Pushed.

Gerald


gcc:
PR target/69374
* doc/install.texi (Specific) : Remove details
on libunwind for GCC 3.4 and earlier.
---
 gcc/doc/install.texi | 6 --
 1 file changed, 6 deletions(-)

diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index b13c62ed2b7..4119304f66a 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -4316,12 +4316,6 @@ Building GCC on this target requires the GNU Assembler.  
The bundled HP
 assembler will not work.  To prevent GCC from using the wrong assembler,
 the option @option{--with-gnu-as} may be necessary.
 
-The GCC libunwind library has not been ported to HPUX@.  This means that for
-GCC versions 3.2.3 and earlier, @option{--enable-libunwind-exceptions}
-is required to build GCC@.  For GCC 3.3 and later, this is the default.
-For gcc 3.4.3 and later, @option{--enable-libunwind-exceptions} is
-removed and the system libunwind library will always be used.
-
 @html
 
 
-- 
2.44.0


[COMMITTED] Reduce startup costs for Value_Range.

2024-05-01 Thread Aldy Hernandez
Value_Range is our polymorphic temporary that can hold any range.  It
is used for type agnostic code where it isn't known ahead of time,
what the type of the range will be (irange, france, etc).  Currently,
there is a temporary of each type in the object, which means we need
to construct each range for every temporary.  This isn't scaling
well now that prange is about to add yet another range type.

This patch removes each range, opting to use in-place new for a byte
buffer sufficiently large to hold ranges of any type.  It reduces the
memory footprint by 14% for every Value_Range temporary (from 792 to
680 bytes), and we are guaranteed it will never again grow as we add
more range types (strings, complex numbers, etc).

Surprisingly, it improves VRP performance by 6.61% and overall
compilation by 0.44%, which is a lot more than we bargained for
when we started working on prange performance.

There is a slight change in semantics for Value_Range.  The default
constructor does not initialize the object at all.  It must be
manually initialized with either Value_Range::set_type(), or by
assigning a range to it.  This means that IPA's m_known_value_ranges
must be initialized at allocation, instead of depending on the empty
constructor to initialize it to VR_UNDEFINED for unsupported_range.

I have taken the time to properly document both the class, and each
method.  If anything isn't clear, please let me know so I can adjust it
accordingly.

gcc/ChangeLog:

* ipa-fnsummary.cc (evaluate_properties_for_edge): Initialize 
Value_Range's.
* value-range.h (class Value_Range): Add a buffer and remove
m_irange and m_frange.
(Value_Range::Value_Range): Call init.
(Value_Range::set_type): Same.
(Value_Range::init): Use in place new to initialize buffer.
(Value_Range::operator=): Tidy.
---
 gcc/ipa-fnsummary.cc |   8 ++-
 gcc/value-range.h| 127 ---
 2 files changed, 76 insertions(+), 59 deletions(-)

diff --git a/gcc/ipa-fnsummary.cc b/gcc/ipa-fnsummary.cc
index dff40cd8aa5..668a01ef175 100644
--- a/gcc/ipa-fnsummary.cc
+++ b/gcc/ipa-fnsummary.cc
@@ -681,8 +681,12 @@ evaluate_properties_for_edge (struct cgraph_edge *e, bool 
inline_p,
if (!vr.undefined_p () && !vr.varying_p ())
  {
if (!avals->m_known_value_ranges.length ())
- avals->m_known_value_ranges.safe_grow_cleared (count,
-true);
+ {
+   avals->m_known_value_ranges.safe_grow_cleared 
(count,
+  
true);
+   for (int i = 0; i < count; ++i)
+ avals->m_known_value_ranges[i].set_type 
(void_type_node);
+ }
avals->m_known_value_ranges[i] = vr;
  }
  }
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 471f362f388..f1c638f8cd0 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -684,6 +684,16 @@ typedef int_range<2> value_range;
 // This is an "infinite" precision range object for use in temporary
 // calculations for any of the handled types.  The object can be
 // transparently used as a vrange.
+//
+// Using any of the various constructors initializes the object
+// appropriately, but the default constructor is uninitialized and
+// must be initialized either with set_type() or by assigning into it.
+//
+// Assigning between incompatible types is allowed.  For example if a
+// temporary holds an irange, you can assign an frange into it, and
+// all the right things will happen.  However, before passing this
+// object to a function accepting a vrange, the correct type must be
+// set.  If it isn't, you can do so with set_type().
 
 class Value_Range
 {
@@ -693,6 +703,7 @@ public:
   Value_Range (tree type);
   Value_Range (tree, tree, value_range_kind kind = VR_RANGE);
   Value_Range (const Value_Range &);
+  ~Value_Range ();
   void set_type (tree type);
   vrange& operator= (const vrange &);
   Value_Range& operator= (const Value_Range &);
@@ -726,16 +737,29 @@ public:
   void accept (const vrange_visitor ) const { m_vrange->accept (v); }
 private:
   void init (tree type);
-  unsupported_range m_unsupported;
+  void init (const vrange &);
+
   vrange *m_vrange;
-  int_range_max m_irange;
-  frange m_frange;
+  // The buffer must be at least the size of the largest range.
+  static_assert (sizeof (int_range_max) > sizeof (frange));
+  char m_buffer[sizeof (int_range_max)];
 };
 
+// The default constructor is uninitialized and must be initialized
+// with either set_type() or with an assignment into it.
+
 inline
 Value_Range::Value_Range ()
 {
-  m_vrange = _unsupported;
+  m_vrange = NULL;
+}
+
+// Copy constructor.
+
+inline

[COMMITTED] Cleanups to unsupported_range.

2024-05-01 Thread Aldy Hernandez
Here are some cleanups to unsupported_range so the assignment operator
takes an unsupported_range and behaves like the other ranges.  This
makes subsequent cleanups easier.

gcc/ChangeLog:

* value-range.cc (unsupported_range::union_): Cast vrange to
unsupported_range.
(unsupported_range::intersect): Same.
(unsupported_range::operator=): Make argument an unsupported_range.
* value-range.h: New constructor.
---
 gcc/value-range.cc | 10 +++---
 gcc/value-range.h  |  7 ++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/gcc/value-range.cc b/gcc/value-range.cc
index ca6d521c625..7250115261f 100644
--- a/gcc/value-range.cc
+++ b/gcc/value-range.cc
@@ -147,8 +147,10 @@ unsupported_range::set_varying (tree)
 }
 
 bool
-unsupported_range::union_ (const vrange )
+unsupported_range::union_ (const vrange )
 {
+  const unsupported_range  = as_a  (v);
+
   if (r.undefined_p () || varying_p ())
 return false;
   if (undefined_p () || r.varying_p ())
@@ -161,8 +163,10 @@ unsupported_range::union_ (const vrange )
 }
 
 bool
-unsupported_range::intersect (const vrange )
+unsupported_range::intersect (const vrange )
 {
+  const unsupported_range  = as_a  (v);
+
   if (undefined_p () || r.varying_p ())
 return false;
   if (r.undefined_p ())
@@ -216,7 +220,7 @@ unsupported_range::fits_p (const vrange &) const
 }
 
 unsupported_range &
-unsupported_range::operator= (const vrange )
+unsupported_range::operator= (const unsupported_range )
 {
   if (r.undefined_p ())
 set_undefined ();
diff --git a/gcc/value-range.h b/gcc/value-range.h
index 11c73faca1b..471f362f388 100644
--- a/gcc/value-range.h
+++ b/gcc/value-range.h
@@ -389,6 +389,11 @@ public:
   {
 set_undefined ();
   }
+  unsupported_range (const unsupported_range )
+: vrange (VR_UNKNOWN)
+  {
+unsupported_range::operator= (src);
+  }
   void set (tree min, tree, value_range_kind = VR_RANGE) final override;
   tree type () const final override;
   bool supports_type_p (const_tree) const final override;
@@ -405,7 +410,7 @@ public:
   void set_zero (tree type) final override;
   void set_nonnegative (tree type) final override;
   bool fits_p (const vrange &) const final override;
-  unsupported_range& operator= (const vrange );
+  unsupported_range& operator= (const unsupported_range );
   tree lbound () const final override;
   tree ubound () const final override;
 };
-- 
2.44.0



[PATCH] c++: Implement C++26 P2573R2 - = delete("should have a reason"); [PR114458]

2024-05-01 Thread Jakub Jelinek
Hi!

The following patch implements the C++26 P2573R2
= delete("should have a reason"); paper.
I've tried to avoid increasing compile time memory for it when it isn't
used (e.g. by adding a new lang_decl tree member), so the reason is
represented as STRING_CST in DECL_INITIAL (which normally is for
DECL_DELETED_FN error_mark_node) and to differentiate this delete("reason")
initializer from some bogus attempt to initialize a function with "reason"
using the RID_DELETE identifier as TREE_TYPE of the STRING_CST, as nothing
needs to care about the type of the reason.  If preferred it could
be say TREE_LIST with the reason STRING_CST and RID_DELETE identifier or
something similar instead, but that would need more compile time memory when
it is used.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2024-05-01  Jakub Jelinek  

PR c++/114458
gcc/c-family/
* c-cppbuiltin.cc (c_cpp_builtins): Predefine
__cpp_deleted_function=202403L for C++26.
gcc/cp/ChangeLog
* parser.cc (cp_parser_pure_specifier): Implement C++26 P2573R2
- = delete("should have a reason");.  Parse deleted-function-body.
* decl.cc (duplicate_decls): Copy DECL_INITIAL from DECL_DELETED_FN
olddecl to newdecl if it is a STRING_CST.
(cp_finish_decl): Handle deleted init with a reason.
* decl2.cc: Include "escaped_string.h".
(grokfield): Handle deleted init with a reason.
(mark_used): Emit DECL_DELETED_FN reason in the message if any.
gcc/testsuite/
* g++.dg/cpp26/feat-cxx26.C (__cpp_deleted_function): Add test.
* g++.dg/cpp26/delete-reason1.C: New test.
* g++.dg/cpp26/delete-reason2.C: New test.
* g++.dg/parse/error65.C (f1): Adjust expected diagnostics.

--- gcc/c-family/c-cppbuiltin.cc.jj 2024-04-30 08:57:07.359039013 +0200
+++ gcc/c-family/c-cppbuiltin.cc2024-04-30 19:16:45.069542205 +0200
@@ -1092,6 +1092,7 @@ c_cpp_builtins (cpp_reader *pfile)
  cpp_define (pfile, "__cpp_static_assert=202306L");
  cpp_define (pfile, "__cpp_placeholder_variables=202306L");
  cpp_define (pfile, "__cpp_structured_bindings=202403L");
+ cpp_define (pfile, "__cpp_deleted_function=202403L");
}
   if (flag_concepts)
 {
--- gcc/cp/parser.cc.jj 2024-04-30 08:57:07.349039147 +0200
+++ gcc/cp/parser.cc2024-04-30 16:47:01.427952875 +0200
@@ -28573,6 +28573,27 @@ cp_parser_pure_specifier (cp_parser* par
   || token->keyword == RID_DELETE)
 {
   maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+   {
+ if (cxx_dialect >= cxx11 && cxx_dialect < cxx26)
+   pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+OPT_Wc__26_extensions,
+"% reason only available with "
+"%<-std=c++2c%> or %<-std=gnu++2c%>");
+
+ /* Consume the `('.  */
+ matching_parens parens;
+ parens.consume_open (parser);
+ tree reason = cp_parser_unevaluated_string_literal (parser);
+ /* Consume the `)'.  */
+ parens.require_close (parser);
+ if (TREE_CODE (reason) == STRING_CST)
+   {
+ TREE_TYPE (reason) = token->u.value;
+ return reason;
+   }
+   }
+
   return token->u.value;
 }
 
--- gcc/cp/decl.cc.jj   2024-04-30 08:55:26.172389593 +0200
+++ gcc/cp/decl.cc  2024-04-30 19:01:32.316543498 +0200
@@ -2410,6 +2410,10 @@ duplicate_decls (tree newdecl, tree oldd
"previous declaration of %qD", olddecl);
}
  DECL_DELETED_FN (newdecl) |= DECL_DELETED_FN (olddecl);
+ if (DECL_DELETED_FN (olddecl)
+ && DECL_INITIAL (olddecl)
+ && TREE_CODE (DECL_INITIAL (olddecl)) == STRING_CST)
+   DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
}
 }
 
@@ -8587,17 +8591,20 @@ cp_finish_decl (tree decl, tree init, bo
   if (init && TREE_CODE (decl) == FUNCTION_DECL)
 {
   tree clone;
-  if (init == ridpointers[(int)RID_DELETE])
+  if (init == ridpointers[(int)RID_DELETE]
+ || (TREE_CODE (init) == STRING_CST
+ && TREE_TYPE (init) == ridpointers[(int)RID_DELETE]))
{
  /* FIXME check this is 1st decl.  */
  DECL_DELETED_FN (decl) = 1;
  DECL_DECLARED_INLINE_P (decl) = 1;
- DECL_INITIAL (decl) = error_mark_node;
+ DECL_INITIAL (decl)
+   = TREE_CODE (init) == STRING_CST ? init : error_mark_node;
  FOR_EACH_CLONE (clone, decl)
{
  DECL_DELETED_FN (clone) = 1;
  DECL_DECLARED_INLINE_P (clone) = 1;
- DECL_INITIAL (clone) = error_mark_node;
+ DECL_INITIAL (clone) = DECL_INITIAL (decl);
}
  init = NULL_TREE;
}
--- gcc/cp/decl2.cc.jj  2024-04-25 20:33:30.770858926 +0200
+++ gcc/cp/decl2.cc