[PATCH] except: Fix __builtin_eh_return_data_regno (-42) expansion [PR101195]

2024-01-30 Thread Jakub Jelinek
Hi!

The expansion of this builtin emits an error if the argument is not
INTEGER_CST, otherwise uses tree_to_uhwi on the argument (which is declared
int) and then uses EH_RETURN_DATA_REGNO macro which on most targets returns
INVALID_REGNUM for all values but some small number (2 or 4); if it returns
INVALID_REGNUM, we silently expand to -1.

Now, I think the error for non-INTEGER_CST makes sense to catch when people
unintentionally don't call it with a constant (but, users shouldn't really
use this builtin anyway, it is for the unwinder only).  Initially I thought
about emitting an error for the negative values as well on which
tree_to_uhwi otherwise ICEs, but given that the function will silently
expand to -1 for INT_MAX - 1 or INT_MAX - 3 other values, I think treating
the negatives the same silently is fine too.

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

2024-01-30  Jakub Jelinek  

PR middle-end/101195
* except.cc (expand_builtin_eh_return_data_regno): If which doesn't
fit into unsigned HOST_WIDE_INT, return constm1_rtx.

* gcc.dg/pr101195.c: New test.

--- gcc/except.cc.jj2024-01-03 11:51:37.552647625 +0100
+++ gcc/except.cc   2024-01-29 09:46:09.385299324 +0100
@@ -2167,6 +2167,9 @@ expand_builtin_eh_return_data_regno (tre
   return constm1_rtx;
 }
 
+  if (!tree_fits_uhwi_p (which))
+return constm1_rtx;
+
   iwhich = tree_to_uhwi (which);
   iwhich = EH_RETURN_DATA_REGNO (iwhich);
   if (iwhich == INVALID_REGNUM)
--- gcc/testsuite/gcc.dg/pr101195.c.jj  2024-01-29 09:48:15.969510457 +0100
+++ gcc/testsuite/gcc.dg/pr101195.c 2024-01-29 09:48:08.626614220 +0100
@@ -0,0 +1,8 @@
+/* PR middle-end/101195 */
+/* { dg-do compile } */
+
+int
+foo (void)
+{
+  return __builtin_eh_return_data_regno (-42);
+}

Jakub



[PATCH] tree-ssa-strlen: Fix up handle_store [PR113603]

2024-01-30 Thread Jakub Jelinek
Hi!

Since r10-2101-gb631bdb3c16e85f35d3 handle_store uses
count_nonzero_bytes{,_addr} which (more recently limited to statements
with the same vuse) can walk earlier statements feeding the rhs
of the store and call get_stridx on it.
Unlike most of the other functions where get_stridx is called first on
rhs and only later on lhs, handle_store calls get_stridx on the lhs before
the count_nonzero_bytes* call and does some si->nonzero_bytes comparison
on it.
Now, strinfo structures are refcounted and it is important not to screw
it up.
What happens on the following testcase is that we call get_strinfo on the
destination idx's base (g), which returns a strinfo at that moment
with refcount of 2, one copy referenced in bb 2 final strinfos, one in bb 3
(the vector of strinfos was unshared from the dominator there because some
other strinfo was added) and finally we process a store in bb 6.
Now, count_nonzero_bytes is called and that sees &g[1] in a PHI and
calls get_stridx on it, which in turn calls get_stridx_plus_constant
because &g + 1 address doesn't have stridx yet.  This creates a new
strinfo for it:
  si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
basesi->full_string_p);
  set_strinfo (idx, si);
and the latter call, because it is the first one in bb 6 that needs it,
unshares the stridx_to_strinfo vector (so refcount of the g strinfo becomes
3).
Now, get_stridx_plus_constant needs to chain the new strinfo of &g[1] in
between the related strinfos, so after the g record.  Because the strinfo
is now shared between the current bb and 2 other bbs, it needs to
unshare_strinfo it (creating a new strinfo which can be modified as a copy
of the old one, decrementing refcount of the old shared one and setting
refcount of the new one to 1):
  if (strinfo *nextsi = get_strinfo (chainsi->next))
{
  nextsi = unshare_strinfo (nextsi);
  si->next = nextsi->idx;
  nextsi->prev = idx;
}
  chainsi = unshare_strinfo (chainsi);
  if (chainsi->first == 0)
chainsi->first = chainsi->idx;
  chainsi->next = idx;
Now, the bug is that the caller of this a couple of frames above,
handle_store, holds on a pointer to this g strinfo (but doesn't know
about the unsharing, so the pointer is to the old strinfo with refcount
of 2), and later needs to update it, so it
  si = unshare_strinfo (si);
and modifies some fields in it.
This creates a new strinfo (with refcount of 1 which is stored into
the vector of the current bb) based on the old strinfo for g and
decrements refcount of the old one to 1.  So, now we are in inconsistent
state, because the old strinfo for g is referenced in bb 2 and bb 3
vectors, but has just refcount of 1, and then have one strinfo (the one
created by unshare_strinfo (chainsi) in get_stridx_plus_constant) which
has refcount of 1 but isn't referenced from anywhere anymore.
Later on when we free one of the bb 2 or bb 3 vectors (forgot which)
that decrements refcount from 1 to 0 and poisons the strinfo/returns it to
the pool, but then maybe_invalidate when looking at the other bb's pointer
to it ICEs.

The following patch fixes it by calling get_strinfo again, it is guaranteed
to return non-NULL, but could be an unshared copy instead of the originally
fetched shared one.

I believe we only need to do this refetching for the case where get_strinfo
is called on the lhs before get_stridx is called on other operands, because
we should be always modifying (apart from the chaining changes) the strinfo
for the destination of the statements, not other strinfos just consumed in
there.

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

2024-01-30  Jakub Jelinek  

PR tree-optimization/113603
* tree-ssa-strlen.cc (strlen_pass::handle_store): After
count_nonzero_bytes call refetch si using get_strinfo in case it
has been unshared in the meantime.

* gcc.c-torture/compile/pr113603.c: New test.

--- gcc/tree-ssa-strlen.cc.jj   2024-01-29 10:20:25.0 +0100
+++ gcc/tree-ssa-strlen.cc  2024-01-29 15:50:17.056461933 +0100
@@ -5044,6 +5044,9 @@ strlen_pass::handle_store (bool *zero_wr
 
   if (si != NULL)
 {
+  /* The count_nonzero_bytes call above might have unshared si.
+Fetch it again from the vector.  */
+  si = get_strinfo (idx);
   /* The corresponding element is set to 1 if the first and last
 element, respectively, of the sequence of characters being
 written over the string described by SI ends before
--- gcc/testsuite/gcc.c-torture/compile/pr113603.c.jj   2024-01-29 
16:09:54.335227319 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr113603.c  2024-01-29 
16:09:36.010481829 +0100
@@ -0,0 +1,40 @@
+/* PR tree-optimization/113603 */
+
+int a, e;
+signed char b;
+int *c;
+signed char *d;
+short f;
+signed char g[3];
+
+int *
+foo (void)
+{
+  for (int i = 0; i < 3; i++)
+g[i] = 2;
+  int j[100][100] = { {}, {4} };
+  signed char *k = &g[1

[PATCH v2] RISC-V: Bugfix for vls mode aggregated in GPR calling convention

2024-01-30 Thread pan2 . li
From: Pan Li 

According to the issue as below.

https://hub.fgit.cf/riscv-non-isa/riscv-elf-psabi-doc/pull/416

When the mode size of vls integer mode is less than 2 * XLEN, we will
take the gpr for both the args and the return values. Instead of the
reference. For example the below code:

typedef short v8hi __attribute__ ((vector_size (16)));

v8hi __attribute__((noinline))
add (v8hi a, v8hi b)
{
  v8hi r = a + b;
  return r;
}

Before this patch:
add:
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v1,0(a1) <== arg by reference
  vle16.v  v2,0(a2) <== arg by reference
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(a0) <== return by reference
  ret

After this patch:
add:
  addi sp,sp,-32
  sd   a0,0(sp)  <== arg by register a0 - a3
  sd   a1,8(sp)
  sd   a2,16(sp)
  sd   a3,24(sp)
  addi a5,sp,16
  vsetivli zero,8,e16,m1,ta,ma
  vle16.v  v2,0(sp)
  vle16.v  v1,0(a5)
  vadd.vv  v1,v1,v2
  vse16.v  v1,0(sp)
  ld   a0,0(sp)  <== return by a0 - a1.
  ld   a1,8(sp)
  addi sp,sp,32
  jr   ra

For vls floating point, we take the same rules as integer and passed by
the gpr or reference.  However, we can simplify the above code by vmv,
and avoid the read/write values to the stack.  We will prepare another
patch for it as it isn't the scope of bugfix.

The riscv regression passed for this patch.

gcc/ChangeLog:

* config/riscv/riscv.cc (riscv_v_vls_mode_aggregate_gpr_count): New 
function to
calculate the gpr count required by vls mode.
(riscv_v_vls_to_gpr_mode): New function convert vls mode to gpr mode.
(riscv_pass_vls_aggregate_in_gpr): New function to return the rtx of gpr
for vls mode.
(riscv_get_arg_info): Add vls mode handling.
(riscv_pass_by_reference): Return false if arg info has no zero gpr 
count.

gcc/testsuite/ChangeLog:

* gcc.target/riscv/rvv/autovec/vls/def.h: Add new helper macro.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-6.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-7.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-8.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-9.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-1.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-2.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-3.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-4.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-5.c: New test.
* gcc.target/riscv/rvv/autovec/vls/calling-convention-run-6.c: New test.

Signed-off-by: Pan Li 
---
 gcc/config/riscv/riscv.cc |  75 +
 .../rvv/autovec/vls/calling-convention-1.c| 154 ++
 .../rvv/autovec/vls/calling-convention-10.c   |  51 ++
 .../rvv/autovec/vls/calling-convention-2.c| 142 
 .../rvv/autovec/vls/calling-convention-3.c| 130 +++
 .../rvv/autovec/vls/calling-convention-4.c| 118 ++
 .../rvv/autovec/vls/calling-convention-5.c| 141 
 .../rvv/autovec/vls/calling-convention-6.c| 129 +++
 .../rvv/autovec/vls/calling-convention-7.c| 118 ++
 .../rvv/autovec/vls/calling-convention-8.c|  43 +
 .../rvv/autovec/vls/calling-convention-9.c|  51 ++
 .../autovec/vls/calling-convention-run-1.c|  55 +++
 .../autovec/vls/calling-convention-run-2.c|  55 +++
 .../autovec/vls/calling-convention-run-3.c|  55 +++
 .../autovec/vls/calling-convention-run-4.c|  55 +++
 .../autovec/vls/calling-convention-run-5.c|  55 +++
 .../autovec/vls/calling-convention-run-6.c|  55 +++
 .../gcc.target/riscv/rvv/autovec/vls/def.h|  74 +
 18 files changed, 1556 insertions(+)
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-1.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-10.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-2.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-3.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-4.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autovec/vls/calling-convention-5.c
 create mode 100644 
gcc/testsuite/gcc.target/riscv/rvv/autove

[committed] testsuite: Fix up pr113622-{2,3}.c for i686-linux [PR113622]

2024-01-30 Thread Jakub Jelinek
On Mon, Jan 29, 2024 at 01:05:51PM +0100, Richard Biener wrote:
>   * gcc.target/i386/pr113622-2.c: New testcase.
>   * gcc.target/i386/pr113622-3.c: Likewise.

The 2 new tests FAIL for me on i686-linux:
.../gcc/testsuite/gcc.target/i386/pr113622-2.c:5:14: error: data type of 'a' 
isn't suitable for a register
.../gcc/testsuite/gcc.target/i386/pr113622-2.c:5:29: error: data type of 'b' 
isn't suitable for a register
.../gcc/testsuite/gcc.target/i386/pr113622-2.c:5:44: error: data type of 'c' 
isn't suitable for a register
The problem is that the tests use vectors of double, something added
only in SSE2, while the testcases ask for just -msse which only provides
vectors of floats.

So, either it should be using floats instead of doubles, or we need
to add -msse2 to dg-options.

I've done the latter.

Tested on x86_64-linux with
RUNTESTFLAGS='--target_board=unix\{-m32/-march=i686,-m64\} i386.exp=pr113622*.c'
and committed to trunk as obvious.

2024-01-30  Jakub Jelinek  

PR middle-end/113622
* gcc.target/i386/pr113622-2.c: Use -msse2 instead of -msse in
dg-options.
* gcc.target/i386/pr113622-3.c: Likewise.

--- gcc/testsuite/gcc.target/i386/pr113622-2.c.jj   2024-01-29 
23:54:36.330418899 +0100
+++ gcc/testsuite/gcc.target/i386/pr113622-2.c  2024-01-30 08:54:27.227934561 
+0100
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-msse -w" } */
+/* { dg-options "-msse2 -w" } */
 
 typedef double __attribute__ ((vector_size (16))) vec;
 register vec a asm("xmm5"), b asm("xmm6"), c asm("xmm7");
--- gcc/testsuite/gcc.target/i386/pr113622-3.c.jj   2024-01-29 
23:54:36.330418899 +0100
+++ gcc/testsuite/gcc.target/i386/pr113622-3.c  2024-01-30 08:54:32.867854967 
+0100
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-msse" } */
+/* { dg-options "-msse2" } */
 
 typedef double __attribute__ ((vector_size (16))) vec;
 


Jakub



RE: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention

2024-01-30 Thread Li, Pan2
Thanks Kito for comments, rebase the upstream and always goes to GPR in V2.

https://gcc.gnu.org/pipermail/gcc-patches/2024-January/644291.html

Pan

-Original Message-
From: Kito Cheng  
Sent: Monday, January 29, 2024 9:23 PM
To: Li, Pan2 
Cc: gcc-patches@gcc.gnu.org; juzhe.zh...@rivai.ai; Wang, Yanzhang 

Subject: Re: [PATCH v1] RISC-V: Bugfix for vls integer mode calling convention

> @@ -4868,6 +4968,63 @@ riscv_pass_fpr_pair (machine_mode mode, unsigned 
> regno1,
>GEN_INT (offset2;
>  }
>
> +static rtx
> +riscv_pass_vls_aggregate_in_gpr_or_fpr (struct riscv_arg_info *info,
> +   machine_mode mode, unsigned gpr_base,
> +   unsigned fpr_base)

Tried a few more clang and GCC code gen and I found VLS vector is
always passed in
GPR, and never passed in FPR, so I think I should update psABI rather than fix
that on GCC side.

> @@ -4997,9 +5170,7 @@ riscv_get_arg_info (struct riscv_arg_info *info, const 
> CUMULATIVE_ARGS *cum,
>info->gpr_offset = cum->num_gprs;
>info->fpr_offset = cum->num_fprs;
>
> -  /* When disable vector_abi or scalable vector argument is anonymous, this
> - argument is passed by reference.  */
> -  if (riscv_v_ext_mode_p (mode) && (!riscv_vector_abi || !named))
> +  if (riscv_mode_pass_by_reference_p (mode, named))

Keep as it is fine since riscv_vector_abi is gone.

>  return NULL_RTX;
>
>if (named)


Re: [PATCH] except: Fix __builtin_eh_return_data_regno (-42) expansion [PR101195]

2024-01-30 Thread Richard Biener
On Tue, 30 Jan 2024, Jakub Jelinek wrote:

> Hi!
> 
> The expansion of this builtin emits an error if the argument is not
> INTEGER_CST, otherwise uses tree_to_uhwi on the argument (which is declared
> int) and then uses EH_RETURN_DATA_REGNO macro which on most targets returns
> INVALID_REGNUM for all values but some small number (2 or 4); if it returns
> INVALID_REGNUM, we silently expand to -1.
> 
> Now, I think the error for non-INTEGER_CST makes sense to catch when people
> unintentionally don't call it with a constant (but, users shouldn't really
> use this builtin anyway, it is for the unwinder only).  Initially I thought
> about emitting an error for the negative values as well on which
> tree_to_uhwi otherwise ICEs, but given that the function will silently
> expand to -1 for INT_MAX - 1 or INT_MAX - 3 other values, I think treating
> the negatives the same silently is fine too.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK

> 2024-01-30  Jakub Jelinek  
> 
>   PR middle-end/101195
>   * except.cc (expand_builtin_eh_return_data_regno): If which doesn't
>   fit into unsigned HOST_WIDE_INT, return constm1_rtx.
> 
>   * gcc.dg/pr101195.c: New test.
> 
> --- gcc/except.cc.jj  2024-01-03 11:51:37.552647625 +0100
> +++ gcc/except.cc 2024-01-29 09:46:09.385299324 +0100
> @@ -2167,6 +2167,9 @@ expand_builtin_eh_return_data_regno (tre
>return constm1_rtx;
>  }
>  
> +  if (!tree_fits_uhwi_p (which))
> +return constm1_rtx;
> +
>iwhich = tree_to_uhwi (which);
>iwhich = EH_RETURN_DATA_REGNO (iwhich);
>if (iwhich == INVALID_REGNUM)
> --- gcc/testsuite/gcc.dg/pr101195.c.jj2024-01-29 09:48:15.969510457 
> +0100
> +++ gcc/testsuite/gcc.dg/pr101195.c   2024-01-29 09:48:08.626614220 +0100
> @@ -0,0 +1,8 @@
> +/* PR middle-end/101195 */
> +/* { dg-do compile } */
> +
> +int
> +foo (void)
> +{
> +  return __builtin_eh_return_data_regno (-42);
> +}
> 
>   Jakub
> 
> 

-- 
Richard Biener 
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)


Re: [PATCH] tree-ssa-strlen: Fix up handle_store [PR113603]

2024-01-30 Thread Richard Biener
On Tue, 30 Jan 2024, Jakub Jelinek wrote:

> Hi!
> 
> Since r10-2101-gb631bdb3c16e85f35d3 handle_store uses
> count_nonzero_bytes{,_addr} which (more recently limited to statements
> with the same vuse) can walk earlier statements feeding the rhs
> of the store and call get_stridx on it.
> Unlike most of the other functions where get_stridx is called first on
> rhs and only later on lhs, handle_store calls get_stridx on the lhs before
> the count_nonzero_bytes* call and does some si->nonzero_bytes comparison
> on it.
> Now, strinfo structures are refcounted and it is important not to screw
> it up.
> What happens on the following testcase is that we call get_strinfo on the
> destination idx's base (g), which returns a strinfo at that moment
> with refcount of 2, one copy referenced in bb 2 final strinfos, one in bb 3
> (the vector of strinfos was unshared from the dominator there because some
> other strinfo was added) and finally we process a store in bb 6.
> Now, count_nonzero_bytes is called and that sees &g[1] in a PHI and
> calls get_stridx on it, which in turn calls get_stridx_plus_constant
> because &g + 1 address doesn't have stridx yet.  This creates a new
> strinfo for it:
>   si = new_strinfo (ptr, idx, build_int_cst (size_type_node, nonzero_chars),
> basesi->full_string_p);
>   set_strinfo (idx, si);
> and the latter call, because it is the first one in bb 6 that needs it,
> unshares the stridx_to_strinfo vector (so refcount of the g strinfo becomes
> 3).
> Now, get_stridx_plus_constant needs to chain the new strinfo of &g[1] in
> between the related strinfos, so after the g record.  Because the strinfo
> is now shared between the current bb and 2 other bbs, it needs to
> unshare_strinfo it (creating a new strinfo which can be modified as a copy
> of the old one, decrementing refcount of the old shared one and setting
> refcount of the new one to 1):
>   if (strinfo *nextsi = get_strinfo (chainsi->next))
> {
>   nextsi = unshare_strinfo (nextsi);
>   si->next = nextsi->idx;
>   nextsi->prev = idx;
> }
>   chainsi = unshare_strinfo (chainsi);
>   if (chainsi->first == 0)
> chainsi->first = chainsi->idx;
>   chainsi->next = idx;
> Now, the bug is that the caller of this a couple of frames above,
> handle_store, holds on a pointer to this g strinfo (but doesn't know
> about the unsharing, so the pointer is to the old strinfo with refcount
> of 2), and later needs to update it, so it
>   si = unshare_strinfo (si);
> and modifies some fields in it.
> This creates a new strinfo (with refcount of 1 which is stored into
> the vector of the current bb) based on the old strinfo for g and
> decrements refcount of the old one to 1.  So, now we are in inconsistent
> state, because the old strinfo for g is referenced in bb 2 and bb 3
> vectors, but has just refcount of 1, and then have one strinfo (the one
> created by unshare_strinfo (chainsi) in get_stridx_plus_constant) which
> has refcount of 1 but isn't referenced from anywhere anymore.
> Later on when we free one of the bb 2 or bb 3 vectors (forgot which)
> that decrements refcount from 1 to 0 and poisons the strinfo/returns it to
> the pool, but then maybe_invalidate when looking at the other bb's pointer
> to it ICEs.
> 
> The following patch fixes it by calling get_strinfo again, it is guaranteed
> to return non-NULL, but could be an unshared copy instead of the originally
> fetched shared one.
> 
> I believe we only need to do this refetching for the case where get_strinfo
> is called on the lhs before get_stridx is called on other operands, because
> we should be always modifying (apart from the chaining changes) the strinfo
> for the destination of the statements, not other strinfos just consumed in
> there.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK

> 2024-01-30  Jakub Jelinek  
> 
>   PR tree-optimization/113603
>   * tree-ssa-strlen.cc (strlen_pass::handle_store): After
>   count_nonzero_bytes call refetch si using get_strinfo in case it
>   has been unshared in the meantime.
> 
>   * gcc.c-torture/compile/pr113603.c: New test.
> 
> --- gcc/tree-ssa-strlen.cc.jj 2024-01-29 10:20:25.0 +0100
> +++ gcc/tree-ssa-strlen.cc2024-01-29 15:50:17.056461933 +0100
> @@ -5044,6 +5044,9 @@ strlen_pass::handle_store (bool *zero_wr
>  
>if (si != NULL)
>  {
> +  /* The count_nonzero_bytes call above might have unshared si.
> +  Fetch it again from the vector.  */
> +  si = get_strinfo (idx);
>/* The corresponding element is set to 1 if the first and last
>element, respectively, of the sequence of characters being
>written over the string described by SI ends before
> --- gcc/testsuite/gcc.c-torture/compile/pr113603.c.jj 2024-01-29 
> 16:09:54.335227319 +0100
> +++ gcc/testsuite/gcc.c-torture/compile/pr113603.c2024-01-29 
> 16:09:36.010481829 +0100
> @@ -0,0 +1,40 @@
> +/* PR tree-optimization/1

[PATCH] riscv: Move UNSPEC_XTHEAD* from unspecv to unspec

2024-01-30 Thread Christoph Müllner
The UNSPEC_XTHEAD* macros ended up in the unspecv enum,
which broke gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c.
The INSNs expect these unspecs to be not volatile.
Further, there is not reason to have them defined volatile.
So let's simply move the macros into the unspec enum.

With this patch we have again 0 fails in riscv.exp.

gcc/ChangeLog:

* config/riscv/riscv.md: Move UNSPEC_XTHEADFMV* to unspec enum.

Signed-off-by: Christoph Müllner 
---
 gcc/config/riscv/riscv.md | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index edcaec4a786..b320ad0210e 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -89,6 +89,10 @@ (define_c_enum "unspec" [
 
   ;; Workaround for HFmode without hardware extension
   UNSPEC_FMV_SFP16_X
+
+  ;; XTheadFmv moves
+  UNSPEC_XTHEADFMV
+  UNSPEC_XTHEADFMV_HW
 ])
 
 (define_c_enum "unspecv" [
@@ -127,10 +131,6 @@ (define_c_enum "unspecv" [
   ;; Zihintpause unspec
   UNSPECV_PAUSE
 
-  ;; XTheadFmv unspec
-  UNSPEC_XTHEADFMV
-  UNSPEC_XTHEADFMV_HW
-
   ;; XTheadInt unspec
   UNSPECV_XTHEADINT_PUSH
   UNSPECV_XTHEADINT_POP
-- 
2.43.0



[pushed] aarch64: Handle debug references to removed registers [PR113636]

2024-01-30 Thread Richard Sandiford
In this PR, we entered early-ra with quite a bit of dead code.
The code was duly removed (to avoid wasting registers), but there
was a dangling reference in debug instructions, which caused an
ICE later.

Fixed by resetting a debug instruction if it references a register
that is no longer needed by non-debug instructions.

Tested on aarch64-linux-gnu & pushed.

Richard


gcc/
PR target/113636
* config/aarch64/aarch64-early-ra.cc (early_ra::replace_regs): Take
the containing insn as an extra parameter.  Reset debug instructions
if they reference a register that is no longer used by real insns.
(early_ra::apply_allocation): Update calls accordingly.

gcc/testsuite/
PR target/113636
* go.dg/pr113636.go: New test.
---
 gcc/config/aarch64/aarch64-early-ra.cc | 19 
 gcc/testsuite/go.dg/pr113636.go| 40 ++
 2 files changed, 54 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/go.dg/pr113636.go

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc 
b/gcc/config/aarch64/aarch64-early-ra.cc
index 033eac7aaf1..028296639b8 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -478,7 +478,7 @@ private:
   void broaden_colors ();
   void finalize_allocation ();
 
-  bool replace_regs (df_ref);
+  bool replace_regs (rtx_insn *, df_ref);
   int try_enforce_constraints (rtx_insn *, vec> &);
   void enforce_constraints (rtx_insn *);
   bool maybe_convert_to_strided_access (rtx_insn *);
@@ -2981,8 +2981,9 @@ early_ra::finalize_allocation ()
 }
 
 // Replace any allocno references in REFS with the allocated register.
+// INSN is the instruction that contains REFS.
 bool
-early_ra::replace_regs (df_ref refs)
+early_ra::replace_regs (rtx_insn *insn, df_ref refs)
 {
   bool changed = false;
   for (df_ref ref = refs; ref; ref = DF_REF_NEXT_LOC (ref))
@@ -2992,6 +2993,14 @@ early_ra::replace_regs (df_ref refs)
continue;
 
   auto new_regno = range.allocno (0)->hard_regno;
+  if (new_regno == FIRST_PSEUDO_REGISTER)
+   {
+ // Reset a debug instruction if, after DCE, the only remaining
+ // references to a register are in such instructions.
+ gcc_assert (DEBUG_INSN_P (insn));
+ INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+ return true;
+   }
   *DF_REF_LOC (ref) = gen_rtx_REG (GET_MODE (DF_REF_REG (ref)), new_regno);
   changed = true;
 }
@@ -3224,8 +3233,8 @@ early_ra::apply_allocation ()
  continue;
 
bool changed = maybe_convert_to_strided_access (insn);
-   changed |= replace_regs (DF_INSN_DEFS (insn));
-   changed |= replace_regs (DF_INSN_USES (insn));
+   changed |= replace_regs (insn, DF_INSN_DEFS (insn));
+   changed |= replace_regs (insn, DF_INSN_USES (insn));
if (changed && NONDEBUG_INSN_P (insn))
  {
if (GET_CODE (PATTERN (insn)) != USE
@@ -3245,7 +3254,7 @@ early_ra::apply_allocation ()
  else
ptr = &XEXP (*ptr, 1);
  }
-   changed |= replace_regs (DF_INSN_EQ_USES (insn));
+   changed |= replace_regs (insn, DF_INSN_EQ_USES (insn));
if (changed)
  df_insn_rescan (insn);
   }
diff --git a/gcc/testsuite/go.dg/pr113636.go b/gcc/testsuite/go.dg/pr113636.go
new file mode 100644
index 000..3f43b696765
--- /dev/null
+++ b/gcc/testsuite/go.dg/pr113636.go
@@ -0,0 +1,40 @@
+// { dg-do compile }
+// { dg-options "-O3 -g" }
+// { dg-additional-options "-mtune=thunderxt88" { target aarch64*-*-* } }
+
+package main
+
+import "math"
+
+func sinhcosh(x float64) (sh, ch float64) {
+   if math.Abs(x) <= 0.5 {
+   return math.Sinh(x), math.Cosh(x)
+   }
+   e := math.Exp(x)
+   ei := 0.5 / e
+   e *= 0.5
+   return e - ei, e + ei
+}
+
+func Cos(x complex128) complex128 {
+   switch re, im := real(x), imag(x); {
+   case im == 0 && (math.IsInf(re, 0) || math.IsNaN(re)):
+   return complex(math.NaN(), -im*math.Copysign(0, re))
+   case math.IsInf(im, 0):
+   switch {
+   // case re == 0:
+   //  return complex(math.Inf(1), -re*math.Copysign(0, im))
+   case math.IsInf(re, 0) || math.IsNaN(re):
+   return complex(math.Inf(1), math.NaN())
+   }
+   // case re == 0 && math.IsNaN(im):
+   //  return complex(math.NaN(), 0)
+   }
+   s, c := math.Sincos(real(x))
+   sh, ch := sinhcosh(imag(x))
+   return complex(c*ch, -s*sh)
+}
+
+func main() {
+   Cos(complex(2.5, 3.5))
+}
-- 
2.25.1



[pushed] aarch64: Avoid allocating FPRs to address registers [PR113623]

2024-01-30 Thread Richard Sandiford
For something like:

void
foo (void)
{
  int *ptr;
  asm volatile ("%0" : "=w" (ptr));
  asm volatile ("%0" :: "m" (*ptr));
}

early-ra would allocate ptr to an FPR for the first asm, thus
leaving an FPR address in the second asm.  The address was then
reloaded by LRA to make it valid.

But early-ra shouldn't be allocating at all in that kind of
situation.  Doing so caused the ICE in the PR (with LDP fusion).

Fixed by making sure that we record address references as
GPR references.

Tested on aarch64-linux-gnu & pushed.

Richard


gcc/
PR target/113623
* config/aarch64/aarch64-early-ra.cc (early_ra::preprocess_insns):
Mark all registers that occur in addresses as needing a GPR.

gcc/testsuite/
PR target/113623
* gcc.c-torture/compile/pr113623.c: New test.
---
 gcc/config/aarch64/aarch64-early-ra.cc|   9 ++
 .../gcc.c-torture/compile/pr113623.c  | 137 ++
 2 files changed, 146 insertions(+)
 create mode 100644 gcc/testsuite/gcc.c-torture/compile/pr113623.c

diff --git a/gcc/config/aarch64/aarch64-early-ra.cc 
b/gcc/config/aarch64/aarch64-early-ra.cc
index 028296639b8..1a03d86e94b 100644
--- a/gcc/config/aarch64/aarch64-early-ra.cc
+++ b/gcc/config/aarch64/aarch64-early-ra.cc
@@ -1173,6 +1173,15 @@ early_ra::preprocess_insns ()
   if (!NONDEBUG_INSN_P (insn))
continue;
 
+  // Mark all registers that occur in addresses as needing a GPR.
+  vec_rtx_properties properties;
+  properties.add_insn (insn, true);
+  for (rtx_obj_reference ref : properties.refs ())
+   if (ref.is_reg ()
+   && ref.in_address ()
+   && !HARD_REGISTER_NUM_P (ref.regno))
+ m_pseudo_regs[ref.regno].flags |= ALLOWS_NONFPR | NEEDS_NONFPR;
+
   if (GET_CODE (PATTERN (insn)) == USE
  || GET_CODE (PATTERN (insn)) == CLOBBER)
continue;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr113623.c 
b/gcc/testsuite/gcc.c-torture/compile/pr113623.c
new file mode 100644
index 000..ed33890054e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr113623.c
@@ -0,0 +1,137 @@
+typedef struct A A;
+typedef struct B B;
+struct A { char *a; long b; };
+enum { C, D };
+typedef struct { A *c; A *d; } E;
+typedef enum { F } G;
+typedef enum { H } I;
+struct B { A *e, *f, *g, *h; char i; } j;
+int k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z, aa, ab, ac, ad, ae, af;
+int ag, ah, ai, aj, ak, al, am, an, ao, ap;
+E aq;
+G ar;
+I as;
+char at;
+
+static int
+foo (char *c, long d)
+{
+  switch (d) {
+  case 7:
+switch (c[6])
+case 'd':
+  if (ao)
+  case 'h':
+if (an)
+case 'r':
+  if (am)
+  case 's':
+if (al)
+  if (ak)
+return C;
+/* FALLTHRU */
+  case 8:
+switch (c[7])
+case 'e':
+  if (aj)
+  case 'h':
+if (ai)
+case 'n':
+  if (ah)
+  case 'y':
+if (ag)
+case 9:
+  switch (c[8])
+  case 'l':
+  case 0:
+switch (c[9])
+case 'e':
+  if (af)
+if (ae)
+case 'n':
+  if (ad)
+  case 't':
+if (ac)
+case 'y':
+  if (ab)
+  case 1:
+switch (c[0])
+case 'r':
+case 2:
+  switch (c[1])
+  case 'e':
+  case 3:
+switch (c[2])
+case 'd':
+  if (aa)
+  case 'e':
+if (z)
+case 'h':
+  if (y)
+  case 'l':
+if (x)
+case 'n':
+  if (w)
+  case 's':
+if (v)
+case 4:
+  switch (c[3])
+  case 'h':
+if (u)
+case 't':
+  if (t)
+  case 5:
+switch (c[4])
+case 'e':
+  if (s)
+  case 'g':
+if (r)
+  

Re: [PATCH V2] rs6000: New pass for replacement of adjacent loads fusion (lxv).

2024-01-30 Thread Michael Meissner
On Sun, Jan 21, 2024 at 07:57:54PM +0530, Ajit Agarwal wrote:
> 
> Hello All:
> 
> New pass to replace adjacent memory addresses lxv with lxvp.
> Added common infrastructure for load store fusion for
> different targets.
> 
> Common routines are refactored in fusion-common.h.
> 
> AARCH64 load/store fusion pass is not changed with the 
> common infrastructure.
> 
> For AARCH64 architectures just include "fusion-common.h"
> and target dependent code can be added to that.
> 
> 
> Alex/Richard:
> 
> If you would like me to add for AARCH64 I can do that for AARCH64.
> 
> If you would like to do that is fine with me.
> 
> Bootstrapped and regtested with powerpc64-linux-gnu.
> 
> Improvement in performance is seen with Spec 2017 spec FP benchmarks.

This patch is a lot better than the previous patch in that it generates fewer
extra instructions, and just replaces some of the load vector instructions with
load vector pair.

In compiling Spec 2017 with it, I see the following results:

Benchmarks that generate lxvp instead of lxv:

500.perlbench_r replace 10 LXVs with  5 LXVPs
502.gcc_r   replace  2 LXVs with  1 LXVPs
510.parest_rreplace 28 LXVs with 14 LXVPs
511.povray_rreplace  4 LXVs with  2 LXVPs
521.wrf_r   replace 12 LXVs with  6 LXVPs
527.cam4_r  replace 12 LXVs with  6 LXVPs
557.xz_rreplace 10 LXVs with  5 LXVPs

A few of the benchmarks generated a different number of NOPs, based on how
prefixed addresses were generated.  I tend to feel this is minor compared to
the others.

 507.cactuBSSN_r 17 fewer alignment NOPs
 520.omnetpp_r  231 more  alignment NOPs
 523.xalancbmk_r246 fewer alignment NOPs
 531.deepsjeng_r  2 more  alignment NOPs
 541.leela_r 28 more  alignment NOPs
 549.fotonik3d_r 27 more  alignment NOPs
 554.roms_r   8 more  alignment NOPs

However there were three benchmarks where the code regressed.  In particular,
it looks like there are more load and store vectors to the stack, so it
indicates more spilling is going on.

525.x264_r  16 more  stack spills, but  84 LXVPs
526.blender_r4 more  stack spills, but 149 LXVPs

One benchmark actually generated fewer stack spills as well as generating
LXVPs.

538.imagick_r   11 fewer stack spills, and  26 LXVPs

Note, these are changes to the static instructions generated.  It does not
evaluate whether the changes help/hurt performance.

-- 
Michael Meissner, IBM
PO Box 98, Ayer, Massachusetts, USA, 01432
email: meiss...@linux.ibm.com


Re: [PATCH] riscv: Move UNSPEC_XTHEAD* from unspecv to unspec

2024-01-30 Thread Kito Cheng
Yeah, that should be put in unspec rather than unspecv, LGTM :)

On Tue, Jan 30, 2024 at 5:29 PM Christoph Müllner
 wrote:
>
> The UNSPEC_XTHEAD* macros ended up in the unspecv enum,
> which broke gcc/testsuite/gcc.target/riscv/xtheadfmv-fmv.c.
> The INSNs expect these unspecs to be not volatile.
> Further, there is not reason to have them defined volatile.
> So let's simply move the macros into the unspec enum.
>
> With this patch we have again 0 fails in riscv.exp.
>
> gcc/ChangeLog:
>
> * config/riscv/riscv.md: Move UNSPEC_XTHEADFMV* to unspec enum.
>
> Signed-off-by: Christoph Müllner 
> ---
>  gcc/config/riscv/riscv.md | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
> index edcaec4a786..b320ad0210e 100644
> --- a/gcc/config/riscv/riscv.md
> +++ b/gcc/config/riscv/riscv.md
> @@ -89,6 +89,10 @@ (define_c_enum "unspec" [
>
>;; Workaround for HFmode without hardware extension
>UNSPEC_FMV_SFP16_X
> +
> +  ;; XTheadFmv moves
> +  UNSPEC_XTHEADFMV
> +  UNSPEC_XTHEADFMV_HW
>  ])
>
>  (define_c_enum "unspecv" [
> @@ -127,10 +131,6 @@ (define_c_enum "unspecv" [
>;; Zihintpause unspec
>UNSPECV_PAUSE
>
> -  ;; XTheadFmv unspec
> -  UNSPEC_XTHEADFMV
> -  UNSPEC_XTHEADFMV_HW
> -
>;; XTheadInt unspec
>UNSPECV_XTHEADINT_PUSH
>UNSPECV_XTHEADINT_POP
> --
> 2.43.0
>


Re: [PATCH]middle-end: check memory accesses in the destination block [PR113588].

2024-01-30 Thread Richard Biener
On Mon, 29 Jan 2024, Tamar Christina wrote:

> Hi All,
> 
> When analyzing loads for early break it was always the intention that 
> for the exit where things get moved to we only check the loads that can 
> be reached from the condition.

Looking at the code I'm a bit confused that we always move to
single_pred (loop->latch) - IIRC that was different at some point?

Shouldn't we move stores after the last early exit condition instead?

In particular for the peeled case single_pred (loop->latch) is the
block with the actual early exit condition?  So for that case we'd
need to move to the latch itself instead?  For non-peeled we move
to the block with the IV condition which looks OK.

> However the main loop checks all loads and we skip the destination BB.  
> As such we never actually check the loads reachable from the COND in the 
> last BB unless this BB was also the exit chosen by the vectorizer.
> 
> This leads us to incorrectly vectorize the loop in the PR and in doing so 
> access
> out of bounds.
> 
> Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> 
> Ok for master?

The patch ends up with a worklist and another confusing comment

+  /* For the destination BB we need to only analyze loads reachable from 
the early
+ break statement itself.  */

But I think it's a downstream issue from the issue above.  That said,
even for the non-peeled case we need to check ref_within_array_bound,
no?

So what about re-doing that initial loop like the following instead
(and also fix dest_bb, but I'd like clarification here).  Basically
walk all blocks, do the ref_within_array_bound first and only
after we've seen 'dest_bb' do the checks required for moving
stores for all upstream BBs.

And dest_bb should be

  /* Move side-effects to the in-loop destination of the last early
 exit.  */
  if (LOOP_VINFO_EARLY_BREAKS_VECT_PEELED (loop_vinfo))
dest_bb = loop->latch;
  else
dest_bb = single_pred (loop->latch);


diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
index f592aeb8028..d6c8910dd6c 100644
--- a/gcc/tree-vect-data-refs.cc
+++ b/gcc/tree-vect-data-refs.cc
@@ -668,7 +668,6 @@ vect_analyze_early_break_dependences (loop_vec_info 
loop_vinfo)
   auto_vec bases;
   basic_block dest_bb = NULL;
 
-  hash_set  visited;
   class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   class loop *loop_nest = loop_outer (loop);
 
@@ -681,15 +680,11 @@ vect_analyze_early_break_dependences (loop_vec_info 
loop_vinfo)
  side-effects to is always the latch connected exit.  When we support
  general control flow we can do better but for now this is fine.  */
   dest_bb = single_pred (loop->latch);
-  basic_block bb = dest_bb;
+  basic_block bb = loop->latch;
+  bool check_deps = false;
 
   do
 {
-  /* If the destination block is also the header then we have nothing to 
do.  */
-  if (!single_pred_p (bb))
-   continue;
-
-  bb = single_pred (bb);
   gimple_stmt_iterator gsi = gsi_last_bb (bb);
 
   /* Now analyze all the remaining statements and try to determine which
@@ -707,6 +702,25 @@ vect_analyze_early_break_dependences (loop_vec_info 
loop_vinfo)
  if (!dr_ref)
continue;
 
+ /* Check if vector accesses to the object will be within bounds.
+must be a constant or assume loop will be versioned or niters
+bounded by VF so accesses are within range.  */
+ if (!ref_within_array_bound (stmt, DR_REF (dr_ref)))
+   {
+ if (dump_enabled_p ())
+   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+"early breaks not supported: vectorization "
+"would %s beyond size of obj.",
+DR_IS_READ (dr_ref) ? "read" : "write");
+ return opt_result::failure_at (stmt,
+"can't safely apply code motion to "
+"dependencies of %G to vectorize "
+"the early exit.\n", stmt);
+   }
+
+ if (!check_deps)
+   continue;
+
  /* We currently only support statically allocated objects due to
 not having first-faulting loads support or peeling for
 alignment support.  Compute the size of the referenced object
@@ -739,22 +753,6 @@ vect_analyze_early_break_dependences (loop_vec_info 
loop_vinfo)
 "the early exit.\n", stmt);
}
 
- /* Check if vector accesses to the object will be within bounds.
-must be a constant or assume loop will be versioned or niters
-bounded by VF so accesses are within range.  */
- if (!ref_within_array_bound (stmt, DR_REF (dr_ref)))
-   {
- if (dump_enabled_p ())
-   dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
-"early breaks not supported: vectorizatio

Re: [tree-ssa PATCH] PR target/113560: Enhance is_widening_mult_rhs_p.

2024-01-30 Thread Richard Biener
On Tue, Jan 30, 2024 at 8:33 AM Roger Sayle  wrote:
>
>
> This patch resolves PR113560, a code quality regression from GCC12
> affecting x86_64, by enhancing the middle-end's tree-ssa-math-opts.cc
> to recognize more instances of widening multiplications.
>
> The widening multiplication perception code identifies cases like:
>
> _1 = (unsigned __int128) x;
> __res = _1 * 100;
>
> but in the reported test case, the original input looks like:
>
> _1 = (unsigned long long) x;
> _2 = (unsigned __int128) _1;
> __res = _2 * 100;
>
> which gets optimized by constant folding during tree-ssa to:
>
> _2 = x & 18446744073709551615;  // x & 0x
> __res = _2 * 100;
>
> where the BIT_AND_EXPR hides (has consumed) the extension operation.
> This reveals the more general deficiency (missed optimization
> opportunity) in widening multiplication perception that additionally
> both
>
> __int128 foo(__int128 x, __int128 y) {
>   return (x & 1000) * (y & 1000)
> }
>
> and
>
> unsigned __int128 bar(unsigned __int128 x, unsigned __int128) {
>   return (x >> 80) * (y >> 80);
> }
>
> should be recognized as widening multiplications.  Hence rather than
> test explicitly for BIT_AND_EXPR (as in the first version of this patch)
> the more general solution is to make use of range information, as
> provided by tree_non_zero_bits.
>
> As a demonstration of the observed improvements, function foo above
> currently with -O2 compiles on x86_64 to:
>
> foo:movq%rdi, %rsi
> movq%rdx, %r8
> xorl%edi, %edi
> xorl%r9d, %r9d
> andl$1000, %esi
> andl$1000, %r8d
> movq%rdi, %rcx
> movq%r9, %rdx
> imulq   %rsi, %rdx
> movq%rsi, %rax
> imulq   %r8, %rcx
> addq%rdx, %rcx
> mulq%r8
> addq%rdx, %rcx
> movq%rcx, %rdx
> ret
>
> with this patch, GCC recognizes the *w and instead generates:
>
> foo:movq%rdi, %rsi
> movq%rdx, %r8
> andl$1000, %esi
> andl$1000, %r8d
> movq%rsi, %rax
> imulq   %r8
> ret
>
> which is perhaps easier to understand at the tree-level where
>
> __int128 foo (__int128 x, __int128 y)
> {
>   __int128 _1;
>   __int128 _2;
>   __int128 _5;
>
>[local count: 1073741824]:
>   _1 = x_3(D) & 1000;
>   _2 = y_4(D) & 1000;
>   _5 = _1 * _2;
>   return _5;
> }
>
> gets transformed to:
>
> __int128 foo (__int128 x, __int128 y)
> {
>   __int128 _1;
>   __int128 _2;
>   __int128 _5;
>   signed long _7;
>   signed long _8;
>
>[local count: 1073741824]:
>   _1 = x_3(D) & 1000;
>   _2 = y_4(D) & 1000;
>   _7 = (signed long) _1;
>   _8 = (signed long) _2;
>   _5 = _7 w* _8;
>   return _5;
> }
>
> This patch has been tested on x86_64-pc-linux-gnu with make bootstrap
> and make -k check, both with and without --target_board=unix{-m32}
> with no new failures.  Ok for mainline?

Nice.  I'll note that the range check works on non-assign defs ('stmt')
as well, so can you put this outside of

   stmt = SSA_NAME_DEF_STMT (rhs);
   if (is_gimple_assign (stmt))
{

and then of course, for

+ /* X & MODE_MASK can be simplified to (T)X.  */
+ if (gimple_assign_rhs_code (stmt) == BIT_AND_EXPR
+ && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
+ && wi::to_wide (gimple_assign_rhs2 (stmt))
+== wi::mask (hprec, false, prec))

add is_gimple_assign (stmt) in the condition?

In particular this might help to detect cases where the operand is defined
by a PHI node (aka a conditional).

OK with that change.

Thanks,
Richard.

>
> 2023-01-30  Roger Sayle  
>
> gcc/ChangeLog
> PR target/113560
> * tree-ssa-math-opts.cc (is_widening_mult_rhs_p): Use range
> information via tree_non_zero_bits to check if this operand
> is suitably extended for a widening (or highpart) multiplication.
> (convert_mult_to_widen): Insert explicit casts if the RHS or LHS
> isn't already of the claimed type.
>
> gcc/testsuite/ChangeLog
> PR target/113560
> * g++.target/i386/pr113560.C: New test case.
> * gcc.target/i386/pr113560.c: Likewise.
>
>
> Thanks in advance,
> Roger
> --
>


[PATCH] testsuite, asan, hwsan: Add libstdc++ deps where required.

2024-01-30 Thread Iain Sandoe
tested on i686, x86_64 (and aarch64) Darwin, x86_64, aarch64 Linux,
OK for trunk?
thanks
Iain

--- 8< ---

We use the shared asan/hwasan from both C,C++,D and Fortran.
The sanitizer libraries link to libstdc++.

When we are using the C/gdc/gfortran driver, and the target might
require a path to the libstdc++ (e.g. for handing -static- or
for embedded runpaths), we need to add a suitable option (or we get
fails at execution time because of the missing paths).

Conversely, we do not want to add multiple instances of these
paths (since that leads to failures on tools that report warnings
for duplicate runpaths).

This patch modifies the _init function to allow a single parameter
that determines whether the *asan_init should add a path for
libstdc++ (yes for C driver, no for C++ driver).

gcc/testsuite/ChangeLog:

* g++.dg/asan/asan.exp: Add a parameter to init to say that
we expect the C++ driver to provide paths for libstdc++.
* g++.dg/hwasan/hwasan.exp: Likewise
* gcc.dg/asan/asan.exp: Add a parameter to init to say that
we need a path added for libstdc++.
* gcc.dg/hwasan/hwasan.exp: Likewise.
* gdc.dg/asan/asan.exp: Likewise.
* gfortran.dg/asan/asan.exp: Likewise.
* lib/asan-dg.exp: Handle a single parameter to init that
requests addition of a path to libstdc++ to link flags.
* lib/hwasan-dg.exp: Likewise.
---
 gcc/testsuite/g++.dg/asan/asan.exp  |  3 ++-
 gcc/testsuite/g++.dg/hwasan/hwasan.exp  |  3 ++-
 gcc/testsuite/gcc.dg/asan/asan.exp  |  3 ++-
 gcc/testsuite/gcc.dg/hwasan/hwasan.exp  |  3 ++-
 gcc/testsuite/gdc.dg/asan/asan.exp  |  3 ++-
 gcc/testsuite/gfortran.dg/asan/asan.exp |  3 ++-
 gcc/testsuite/lib/asan-dg.exp   | 21 -
 gcc/testsuite/lib/hwasan-dg.exp |  9 +
 8 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/gcc/testsuite/g++.dg/asan/asan.exp 
b/gcc/testsuite/g++.dg/asan/asan.exp
index 9297bb55eb1..f078bc37800 100644
--- a/gcc/testsuite/g++.dg/asan/asan.exp
+++ b/gcc/testsuite/g++.dg/asan/asan.exp
@@ -22,7 +22,8 @@ load_lib asan-dg.exp
 
 # Initialize `dg'.
 dg-init
-asan_init
+# libasan uses libstdc++ but we assume that's added by the g++ impl.
+asan_init 0
 
 # Main loop.
 if [check_effective_target_fsanitize_address] {
diff --git a/gcc/testsuite/g++.dg/hwasan/hwasan.exp 
b/gcc/testsuite/g++.dg/hwasan/hwasan.exp
index 597033e01d5..12a7a3570a0 100644
--- a/gcc/testsuite/g++.dg/hwasan/hwasan.exp
+++ b/gcc/testsuite/g++.dg/hwasan/hwasan.exp
@@ -22,7 +22,8 @@ load_lib hwasan-dg.exp
 
 # Initialize `dg'.
 dg-init
-hwasan_init
+# libhwasan uses libstdc++ but we assume that's added by the g++ impl.
+hwasan_init 0
 
 # Main loop.
 if [check_effective_target_fsanitize_hwaddress] {
diff --git a/gcc/testsuite/gcc.dg/asan/asan.exp 
b/gcc/testsuite/gcc.dg/asan/asan.exp
index 10c69731fbf..6b8ebf07eae 100644
--- a/gcc/testsuite/gcc.dg/asan/asan.exp
+++ b/gcc/testsuite/gcc.dg/asan/asan.exp
@@ -24,7 +24,8 @@ load_lib asan-dg.exp
 
 # Initialize `dg'.
 dg-init
-asan_init
+# libasan uses libstdc++ so make sure we provide paths for it.
+asan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_address] {
diff --git a/gcc/testsuite/gcc.dg/hwasan/hwasan.exp 
b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp
index 802f1712296..88327d3b223 100644
--- a/gcc/testsuite/gcc.dg/hwasan/hwasan.exp
+++ b/gcc/testsuite/gcc.dg/hwasan/hwasan.exp
@@ -24,7 +24,8 @@ load_lib hwasan-dg.exp
 
 # Initialize `dg'.
 dg-init
-hwasan_init
+# libhwasan uses libstdc++ so make sure we provide paths for it.
+hwasan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_hwaddress] {
diff --git a/gcc/testsuite/gdc.dg/asan/asan.exp 
b/gcc/testsuite/gdc.dg/asan/asan.exp
index 72b36696c4d..89c6bf35ae4 100644
--- a/gcc/testsuite/gdc.dg/asan/asan.exp
+++ b/gcc/testsuite/gdc.dg/asan/asan.exp
@@ -20,7 +20,8 @@ load_lib asan-dg.exp
 
 # Initialize `dg'.
 dg-init
-asan_init
+# libasan uses libstdc++ so make sure we provide paths for it.
+asan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_address] {
diff --git a/gcc/testsuite/gfortran.dg/asan/asan.exp 
b/gcc/testsuite/gfortran.dg/asan/asan.exp
index 25cd19f6133..a1576381e61 100644
--- a/gcc/testsuite/gfortran.dg/asan/asan.exp
+++ b/gcc/testsuite/gfortran.dg/asan/asan.exp
@@ -27,7 +27,8 @@ load_lib asan-dg.exp
 
 # Initialize `dg'.
 dg-init
-asan_init
+# libasan uses libstdc++ so make sure we provide paths for it.
+asan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_address] {
diff --git a/gcc/testsuite/lib/asan-dg.exp b/gcc/testsuite/lib/asan-dg.exp
index beb49e500eb..6bd3c211611 100644
--- a/gcc/testsuite/lib/asan-dg.exp
+++ b/gcc/testsuite/lib/asan-dg.exp
@@ -61,7 +61,7 @@ proc asan_include_flags {} {
 # (originally from g++.exp)
 #
 
-proc asan_link_flags_1 { paths lib } {
+proc asan_link_flags_1 { paths lib need_stdcxx} {
 global srcdir
 global ld_library_path
 global shlib_ext
@@ -73,6 +73,1

[PATCH] testsuite, ubsan: Add libstdc++ deps where required.

2024-01-30 Thread Iain Sandoe
tested on i686, x86_64 (and aarch64) Darwin, x86_64, aarch64 Linux,
OK for trunk?
thanks
Iain

--- 8< ---

We use the ubsan tests from both C, C++, D and Fortran.
the sanitizer libraries link to libstdc++.

When we are using the C/gdc/gfortran driver, and the target might
require a path to the libstdc++ (e.g. for handing -static- or
for embedded runpaths), we need to add a suitable option (or we get
fails at execution time because of the missing paths).

Conversely, we do not want to add multiple instances of these
paths (since that leads to failures on tools that report warnings
for duplicate runpaths).

This patch modifies the _init function to allow a sigle parameter
that determines whether the *asan_init should add a path for
libstdc++ (yes for C driver, no for C++ driver).
gcc/testsuite/ChangeLog:

* g++.dg/ubsan/ubsan.exp:Add a parameter to init to say that
we expect the C++ driver to provide paths for libstdc++.
* gcc.dg/ubsan/ubsan.exp: Add a parameter to init to say that
we need a path added for libstdc++.
* gdc.dg/ubsan/ubsan.exp: Likewise.
* gfortran.dg/ubsan/ubsan.exp: Likewise.
* lib/ubsan-dg.exp: Handle a single parameter to init that
requests addition of a path to libstdc++ to link flags.
---
 gcc/testsuite/g++.dg/ubsan/ubsan.exp  |  3 ++-
 gcc/testsuite/gcc.dg/ubsan/ubsan.exp  |  3 ++-
 gcc/testsuite/gdc.dg/ubsan/ubsan.exp  |  3 ++-
 gcc/testsuite/gfortran.dg/ubsan/ubsan.exp |  4 ++--
 gcc/testsuite/lib/ubsan-dg.exp| 20 +++-
 5 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/gcc/testsuite/g++.dg/ubsan/ubsan.exp 
b/gcc/testsuite/g++.dg/ubsan/ubsan.exp
index d7197070a92..4bab1b83de9 100644
--- a/gcc/testsuite/g++.dg/ubsan/ubsan.exp
+++ b/gcc/testsuite/g++.dg/ubsan/ubsan.exp
@@ -22,7 +22,8 @@ load_lib ubsan-dg.exp
 
 # Initialize `dg'.
 dg-init
-ubsan_init
+# libubsan uses libstdc++ but we assume that's added by the g++ impl.
+ubsan_init 0
 
 # Main loop.
 if [check_effective_target_fsanitize_undefined] {
diff --git a/gcc/testsuite/gcc.dg/ubsan/ubsan.exp 
b/gcc/testsuite/gcc.dg/ubsan/ubsan.exp
index 84170495e28..560e5843be6 100644
--- a/gcc/testsuite/gcc.dg/ubsan/ubsan.exp
+++ b/gcc/testsuite/gcc.dg/ubsan/ubsan.exp
@@ -24,7 +24,8 @@ load_lib ubsan-dg.exp
 
 # Initialize `dg'.
 dg-init
-ubsan_init
+# libubsan uses libstdc++ so make sure we provide paths for it.
+ubsan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_undefined] {
diff --git a/gcc/testsuite/gdc.dg/ubsan/ubsan.exp 
b/gcc/testsuite/gdc.dg/ubsan/ubsan.exp
index 6ad665a1a8d..7613a3b487c 100644
--- a/gcc/testsuite/gdc.dg/ubsan/ubsan.exp
+++ b/gcc/testsuite/gdc.dg/ubsan/ubsan.exp
@@ -20,7 +20,8 @@ load_lib ubsan-dg.exp
 
 # Initialize `dg'.
 dg-init
-ubsan_init
+# libubsan uses libstdc++ so make sure we provide paths for it.
+ubsan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_undefined] {
diff --git a/gcc/testsuite/gfortran.dg/ubsan/ubsan.exp 
b/gcc/testsuite/gfortran.dg/ubsan/ubsan.exp
index 0c61153e68b..b2360785e6c 100644
--- a/gcc/testsuite/gfortran.dg/ubsan/ubsan.exp
+++ b/gcc/testsuite/gfortran.dg/ubsan/ubsan.exp
@@ -22,10 +22,10 @@
 load_lib gfortran-dg.exp
 load_lib ubsan-dg.exp
 
-
 # Initialize `dg'.
 dg-init
-ubsan_init
+# libubsan uses libstdc++ so make sure we provide paths for it.
+ubsan_init 1
 
 # Main loop.
 if [check_effective_target_fsanitize_undefined] {
diff --git a/gcc/testsuite/lib/ubsan-dg.exp b/gcc/testsuite/lib/ubsan-dg.exp
index 108b9980cac..860e78f3975 100644
--- a/gcc/testsuite/lib/ubsan-dg.exp
+++ b/gcc/testsuite/lib/ubsan-dg.exp
@@ -31,7 +31,7 @@ proc check_effective_target_fsanitize_undefined {} {
 # (originally from g++.exp)
 #
 
-proc ubsan_link_flags { paths } {
+proc ubsan_link_flags { paths needs_cxx } {
 global srcdir
 global ld_library_path
 global shlib_ext
@@ -43,15 +43,24 @@ proc ubsan_link_flags { paths } {
 set shlib_ext [get_shlib_extension]
 set ubsan_saved_library_path $ld_library_path
 
+# Providing -B instead of -L means that it works for targets that use
+# spec substitution for handling -static-x, it also works for targets
+# the use the startfile paths to provide a runpath for uninstalled test.
+# Each -B option will produce a -L on the link line (for paths that exist).
 if { $gccpath != "" } {
   if { [file exists "${gccpath}/libsanitizer/ubsan/.libs/libubsan.a"]
   || [file exists 
"${gccpath}/libsanitizer/ubsan/.libs/libubsan.${shlib_ext}"] } {
  append flags " -B${gccpath}/libsanitizer/ "
  append flags " -B${gccpath}/libsanitizer/ubsan/ "
- append flags " -L${gccpath}/libsanitizer/ubsan/.libs"
+ append flags " -B${gccpath}/libsanitizer/ubsan/.libs"
  append ld_library_path ":${gccpath}/libsanitizer/ubsan/.libs"
- append ld_library_path ":${gccpath}/libstdc++-v3/src/.libs"
   }
+  # libasan links to libstdc++, so we must in

Re: [PATCH] Fortran: use name of array component in runtime error message [PR30802]

2024-01-30 Thread Mikael Morin

Le 29/01/2024 à 21:50, Harald Anlauf a écrit :

Am 29.01.24 um 18:25 schrieb Harald Anlauf:

I was talking about the generated format strings of runtime error
messages.

program p
   implicit none
   type t
  real :: zzz(10) = 42
   end type t
   class(t), allocatable :: xx(:)
   integer :: j
   j = 0
   allocate (t :: xx(1))
   print *, xx(1)% zzz(j)
end

This is generating the following error at runtime since at least gcc-7:

Fortran runtime error: Index '0' of dimension 1 of array 'xx%_data%zzz'
below lower bound of 1


Of course this is easily suppressed by:

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 1e0d698a949..fa0e00a28a6 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -4054,7 +4054,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref *
ar, gfc_expr *expr,
  {
    if (ref->type == REF_ARRAY && &ref->u.ar == ar)
  break;
-  if (ref->type == REF_COMPONENT)
+  if (ref->type == REF_COMPONENT
+  && strcmp (ref->u.c.component->name, "_data") != 0)
  {
    strcat (var_name, "%%");
    strcat (var_name, ref->u.c.component->name);


I have been contemplating the generation the full chain of references as
suggested by Mikael and supported by NAG.



To be clear, my suggestion was to have the question marks (or dashes, 
dots, stars, whatever) literally in the array reference, without the 
actual values of the array indexes.


Another (easier) way to clarify the data reference would be rephrasing 
the message so that the array part is separate from the scalar part, 
like so (there are too many 'of', but I lack inspiration):

Index '0' of dimension 1 of component 'zz' of element from 'x1%vv'
below lower bound of 1



The main issue is: how do I easily generate that call?



gfc_trans_runtime_check is a vararg function, but what I would rather
have is a function that takes either a (chained?) list of trees or
an array of trees holding the (co-)indices of the reference.

Is there an example, or a recommendation which variant to prefer?


None that I know.
For a scalarized expression, the values are present (among others) in 
the gfc_loopinfo::ss linked list, maybe just use that?
In any case, I agree it would be nice to have, but it would probably be 
a non-negligible amount of new error-prone code; I would rather not 
attempt this during the stage4 stabilization phase as we are currently.


Re: [PATCH]AArch64: relax cbranch tests to accepted inverted branches [PR113502]

2024-01-30 Thread Richard Sandiford
Richard Biener  writes:
> On Mon, Jan 29, 2024 at 5:00 PM Richard Sandiford
>  wrote:
>>
>> Tamar Christina  writes:
>> > Hi All,
>> >
>> > Recently something in the midend had started inverting the branches by 
>> > inverting
>> > the condition and the branches.
>> >
>> > While this is fine, it makes it hard to actually test.  In RTL I disable
>> > scheduling and BB reordering to prevent this.  But in GIMPLE there seems 
>> > to be
>> > nothing I can do.  __builtin_expect seems to have no impact on the change 
>> > since
>> > I suspect this is happening during expand where conditions can be flipped
>> > regardless of probability during compare_and_branch.
>> >
>> > Since the mid-end has plenty of correctness tests, this weakens the backend
>> > tests to just check that a correct looking sequence is emitted.
>> >
>> > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
>> >
>> > Ok for master?
>> >
>> > Thanks,
>> > Tamar
>> >
>> > gcc/testsuite/ChangeLog:
>> >
>> >   PR testsuite/113502
>> >   * gcc.target/aarch64/sve/vect-early-break-cbranch.c: Ignore exact 
>> > branch.
>> >   * gcc.target/aarch64/vect-early-break-cbranch.c: Likewise.
>>
>> OK I guess, since I agree that the "polarity" of the branch isn't really the
>> thing that we're trying to test.  But the fact that even __builtin_expect
>> doesn't work seems like a bug.  Do we have a PR for that?  Might be worth
>> filing one (for GCC 15+) if we don't.
>
> But that only should affect which edge is fallthru, not the "polarity"
> of the branch, no?

Right, that's what I meant by "polarity".  I should have used a proper
term, sorry.  The conditions in the patch are inverses of each other,
but it seems like the choice between them should be predictable if
the branch is very likely or very unlikely.

Thanks,
Richard



Re: [PATCH] Fortran: use name of array component in runtime error message [PR30802]

2024-01-30 Thread Mikael Morin

Le 30/01/2024 à 11:38, Mikael Morin a écrit :


Another (easier) way to clarify the data reference would be rephrasing 
the message so that the array part is separate from the scalar part, 
like so (there are too many 'of', but I lack inspiration):

Index '0' of dimension 1 of component 'zz' of element from 'x1%vv'
below lower bound of 1


This has the same number of 'of' but sounds better maybe:
Out of bounds accessing component 'zz' of element from 'x1%yy': index 
'0' of dimension 1 below lower bound of 1


Re: [PATCH]AArch64: relax cbranch tests to accepted inverted branches [PR113502]

2024-01-30 Thread Richard Biener
On Tue, Jan 30, 2024 at 11:40 AM Richard Sandiford
 wrote:
>
> Richard Biener  writes:
> > On Mon, Jan 29, 2024 at 5:00 PM Richard Sandiford
> >  wrote:
> >>
> >> Tamar Christina  writes:
> >> > Hi All,
> >> >
> >> > Recently something in the midend had started inverting the branches by 
> >> > inverting
> >> > the condition and the branches.
> >> >
> >> > While this is fine, it makes it hard to actually test.  In RTL I disable
> >> > scheduling and BB reordering to prevent this.  But in GIMPLE there seems 
> >> > to be
> >> > nothing I can do.  __builtin_expect seems to have no impact on the 
> >> > change since
> >> > I suspect this is happening during expand where conditions can be flipped
> >> > regardless of probability during compare_and_branch.
> >> >
> >> > Since the mid-end has plenty of correctness tests, this weakens the 
> >> > backend
> >> > tests to just check that a correct looking sequence is emitted.
> >> >
> >> > Bootstrapped Regtested on aarch64-none-linux-gnu and no issues.
> >> >
> >> > Ok for master?
> >> >
> >> > Thanks,
> >> > Tamar
> >> >
> >> > gcc/testsuite/ChangeLog:
> >> >
> >> >   PR testsuite/113502
> >> >   * gcc.target/aarch64/sve/vect-early-break-cbranch.c: Ignore exact 
> >> > branch.
> >> >   * gcc.target/aarch64/vect-early-break-cbranch.c: Likewise.
> >>
> >> OK I guess, since I agree that the "polarity" of the branch isn't really 
> >> the
> >> thing that we're trying to test.  But the fact that even __builtin_expect
> >> doesn't work seems like a bug.  Do we have a PR for that?  Might be worth
> >> filing one (for GCC 15+) if we don't.
> >
> > But that only should affect which edge is fallthru, not the "polarity"
> > of the branch, no?
>
> Right, that's what I meant by "polarity".  I should have used a proper
> term, sorry.  The conditions in the patch are inverses of each other,
> but it seems like the choice between them should be predictable if
> the branch is very likely or very unlikely.

I'm not sure, esp. if you disable BB reordering which might be the one
flipping the polarity to keep fallthru/backedge in-order.

Richard.

> Thanks,
> Richard
>


[PATCH] tree-optimization/113659 - early exit vectorization and missing VUSE

2024-01-30 Thread Richard Biener
The following handles the case of the main exit going to a path without
virtual use and handles it similar to the alternate exit handling.

Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed.

PR tree-optimization/113659
* tree-vect-loop-manip.cc (slpeel_tree_duplicate_loop_to_edge_cfg):
Handle main exit without virtual use.

* gcc.dg/pr113659.c: New testcase.
---
 gcc/testsuite/gcc.dg/pr113659.c | 14 ++
 gcc/tree-vect-loop-manip.cc | 20 +---
 2 files changed, 31 insertions(+), 3 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/pr113659.c

diff --git a/gcc/testsuite/gcc.dg/pr113659.c b/gcc/testsuite/gcc.dg/pr113659.c
new file mode 100644
index 000..dc1091b647d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr113659.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fno-tree-sra" } */
+/* { dg-additional-options "-msse4.1" { target { x86_64-*-* i?86-*-* } } } */
+
+struct Foo {
+  int *ptr;
+};
+int Baz(struct Foo first)
+{
+  while (first.ptr)
+if (*first.ptr++)
+  return 0;
+  __builtin_unreachable ();
+}
diff --git a/gcc/tree-vect-loop-manip.cc b/gcc/tree-vect-loop-manip.cc
index 873a28d7c56..3f974d6d839 100644
--- a/gcc/tree-vect-loop-manip.cc
+++ b/gcc/tree-vect-loop-manip.cc
@@ -1708,9 +1708,23 @@ slpeel_tree_duplicate_loop_to_edge_cfg (class loop 
*loop, edge loop_exit,
 LC PHI node to feed the merge PHI.  */
  tree *res;
  if (virtual_operand_p (new_arg))
-   /* Use the existing virtual LC SSA from exit block.  */
-   new_arg = gimple_phi_result
-   (get_virtual_phi (main_loop_exit_block));
+   {
+ /* Use the existing virtual LC SSA from exit block.  */
+ gphi *vphi = get_virtual_phi (main_loop_exit_block);
+ /* ???  When the exit yields to a path without
+any virtual use we can miss a LC PHI for the
+live virtual operand.  Simply choosing the
+one live at the start of the loop header isn't
+correct, but we should get here only with
+early-exit vectorization which will move all
+defs after the main exit, so leave a temporarily
+wrong virtual operand in place.  This happens
+for gcc.dg/pr113659.c.  */
+ if (vphi)
+   new_arg = gimple_phi_result (vphi);
+ else
+   new_arg = gimple_phi_result (from_phi);
+   }
  else if ((res = new_phi_args.get (new_arg)))
new_arg = *res;
  else
-- 
2.35.3


Re: [PATCH v3 1/2] arm: Add define_attr to to create a mapping between MVE predicated and unpredicated insns

2024-01-30 Thread Richard Earnshaw (lists)
On 19/01/2024 14:40, Andre Vieira wrote:
> 
> Reposting for testing purposes, no changes from v2 (other than rebase).

We seem to have lost the ChangeLog for this hunk :(

The code itself looks OK, though.


[PATCH] middle-end: Enhance conditional reduction vectorization by re-association in ifcvt [PR109088]

2024-01-30 Thread Juzhe-Zhong
This patch targets GCC-15.

Consider this following case:

unsigned int
single_loop_with_if_condition (unsigned int *restrict a, unsigned int *restrict 
b,
   unsigned int *restrict c, unsigned int loop_size)
{
  unsigned int result = 0;
  for (unsigned int i = 0; i < loop_size; i++)
{
  if (a[i] > b[i])
{
  result += a[i] + 0xa - c[i];
}
}
  return result;
}

After investigation of LLVM, I find LLVM re-associate such case to make it 
easier
to be vectorized.

Take RISC-V ASM as example.

Before this patch:

beq a3,zero,.L5
sllia5,a3,32
srlia3,a5,30
mv  a4,a0
add a7,a0,a3
li  a0,0
.L4:
lw  a3,0(a4)
addiw   a5,a0,10
lw  a6,0(a1)
addia4,a4,4
addwa5,a5,a3
bgeua6,a3,.L3
lw  a0,0(a2)
subwa0,a5,a0
.L3:
addia1,a1,4
addia2,a2,4
bne a7,a4,.L4
ret
.L5:
li  a0,0
ret

After this patch:

beq a3,zero,.L4
sllia3,a3,32
srlia3,a3,32
vsetvli a5,zero,e32,m1,ta,ma
vmv.v.i v2,0
.L3:
vsetvli a5,a3,e32,m1,tu,mu
sllia4,a5,2
sub a3,a3,a5
vle32.v v3,0(a0)
vle32.v v0,0(a1)
add a0,a0,a4
vmsgtu.vv   v0,v3,v0
add a1,a1,a4
vle32.v v1,0(a2),v0.t
add a2,a2,a4
vadd.vi v1,v1,-10
vsub.vv v1,v1,v3
vadd.vv v2,v2,v1,v0.t
bne a3,zero,.L3
li  a5,0
vsetivlizero,1,e32,m1,ta,ma
vmv.s.x v1,a5
vsetvli a5,zero,e32,m1,ta,ma
vredsum.vs  v2,v2,v1
vmv.x.s a0,v2
ret

PR middle-end/109088

gcc/ChangeLog:

* tree-if-conv.cc (is_cond_scalar_reduction): Enhance conditional 
reduction.
(convert_scalar_cond_reduction): Ditto.

gcc/testsuite/ChangeLog:

* gcc.dg/vect/pr109088-1.c: New test.
* gcc.dg/vect/pr109088-2.c: New test.
* gcc.dg/vect/pr109088-3.c: New test.
* gcc.dg/vect/pr109088-4.c: New test.
* gcc.dg/vect/pr109088-5.c: New test.

---
 gcc/testsuite/gcc.dg/vect/pr109088-1.c | 201 
 gcc/testsuite/gcc.dg/vect/pr109088-2.c | 202 
 gcc/testsuite/gcc.dg/vect/pr109088-3.c | 314 +
 gcc/testsuite/gcc.dg/vect/pr109088-4.c |  84 +++
 gcc/testsuite/gcc.dg/vect/pr109088-5.c |  96 
 gcc/tree-if-conv.cc| 150 +++-
 6 files changed, 1042 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr109088-1.c
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr109088-2.c
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr109088-3.c
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr109088-4.c
 create mode 100644 gcc/testsuite/gcc.dg/vect/pr109088-5.c

diff --git a/gcc/testsuite/gcc.dg/vect/pr109088-1.c 
b/gcc/testsuite/gcc.dg/vect/pr109088-1.c
new file mode 100644
index 000..6772e908535
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr109088-1.c
@@ -0,0 +1,201 @@
+/* { dg-require-effective-target vect_int } */
+/* { dg-require-effective-target vect_condition } */
+
+#include "tree-vect.h"
+
+#define N 27
+
+#define COND_REDUC(NAME, TYPE, OP) 
\
+  TYPE __attribute__ ((noipa)) 
\
+  cond_##NAME (TYPE *__restrict a, int *__restrict cond1,  
\
+  int *__restrict cond2, TYPE init, int n)\
+  {
\
+TYPE result = init;
\
+for (int i = 0; i < n; i++)
\
+  if (cond1[i] > cond2[i]) 
\
+   result OP a[i];\
+return result; 
\
+  }
+
+COND_REDUC (reduc_sum_char, char, +=)
+COND_REDUC (reduc_sum_short, short, +=)
+COND_REDUC (reduc_sum_int, int, +=)
+COND_REDUC (reduc_sum_long, long, +=)
+COND_REDUC (reduc_and_char, char, &=)
+COND_REDUC (reduc_and_short, short, &=)
+COND_REDUC (reduc_and_int, int, &=)
+COND_REDUC (reduc_and_long, long, &=)
+COND_REDUC (reduc_ior_char, char, |=)
+COND_REDUC (reduc_ior_short, short, |=)
+COND_REDUC (reduc_ior_int, int, |=)
+COND_REDUC (reduc_ior_long, long, |=)
+COND_REDUC (reduc_xor_char, char, ^=)
+COND_REDUC (reduc_xor_short, short, ^=)
+COND_REDUC (reduc_xor_int, int, ^=)
+COND_REDUC (reduc_xor_long, long, ^=)
+
+int
+main (void)
+{
+  check_vect ();
+  int cond1[N] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 1,  2,  3, 4,
+ 5,  6,  7,  8,  9,  10, 21, 22, 23, 24, 25, 26, 27};
+  int cond2[N] = {15, 5,  6,  7,  8,  

Re: [PATCH v3 2/2] arm: Add support for MVE Tail-Predicated Low Overhead Loops

2024-01-30 Thread Richard Earnshaw (lists)
On 19/01/2024 14:40, Andre Vieira wrote:
> 
> Respin after comments from Kyrill and rebase. I also removed an if-then-else
> construct in arm_mve_check_reg_origin_is_num_elems similar to the other 
> functions
> Kyrill pointed out.
> 
> After an earlier comment from Richard Sandiford I also added comments to the
> two tail predication patterns added to explain the need for the unspecs.

[missing ChangeLog]

I'm just going to focus on loop-doloop.c in this reply, I'll respond to the 
other bits in a follow-up.

  2)  (set (reg) (plus (reg) (const_int -1))
- (set (pc) (if_then_else (reg != 0)
-(label_ref (label))
-(pc))).  
+(set (pc) (if_then_else (reg != 0)
+(label_ref (label))
+(pc))).
 
  Some targets (ARM) do the comparison before the branch, as in the
  following form:
 
- 3) (parallel [(set (cc) (compare ((plus (reg) (const_int -1), 0)))
-   (set (reg) (plus (reg) (const_int -1)))])
-(set (pc) (if_then_else (cc == NE)
...


This comment is becoming confusing.  Really the text leading up to 3)... should 
be inside 3.  Something like:

  3) Some targets (ARM) do the comparison before the branch, as in the
  following form:
 
  (parallel [(set (cc) (compare (plus (reg) (const_int -1)) 0))
 (set (reg) (plus (reg) (const_int -1)))])
  (set (pc) (if_then_else (cc == NE)
  (label_ref (label))
  (pc)))])


The same issue on the comment structure also applies to the new point 4...

+  The ARM target also supports a special case of a counter that decrements
+  by `n` and terminating in a GTU condition.  In that case, the compare and
+  branch are all part of one insn, containing an UNSPEC:
+
+  4) (parallel [
+   (set (pc)
+   (if_then_else (gtu (unspec:SI [(plus:SI (reg:SI 14 lr)
+   (const_int -n))])
+  (const_int n-1]))
+   (label_ref)
+   (pc)))
+   (set (reg:SI 14 lr)
+(plus:SI (reg:SI 14 lr)
+ (const_int -n)))
+ */

I think this needs a bit more clarification.  Specifically that this construct 
supports a predicated vectorized do loop.  Also, the placement of the unspec 
inside the comparison is ugnly and unnecessary.  It should be sufficient to 
have the unspec inside a USE expression, which the mid-end can then ignore 
entirely.  So

(parallel
 [(set (pc) (if_then_else (gtu (plus (reg) (const_int -n))
   (const_int n-1))
  (label_ref) (pc)))
  (set (reg) (plus (reg) (const_int -n)))
  (additional clobbers and uses)])

For Arm, we then add a (use (unspec [(const_int 0)] N)) that is specific to 
this pattern to stop anything else from matching it.

Note that we don't need to mention that the register is 'LR' or the modes, 
those are specific to a particular backend, not the generic pattern we want to 
match.

+  || !CONST_INT_P (XEXP (inc_src, 1))
+  || INTVAL (XEXP (inc_src, 1)) >= 0)
 return 0;
+  int dec_num = abs (INTVAL (XEXP (inc_src, 1)));

We can just use '-INTVAL(...)' here, we've verified just above that the 
constant is negative.

-  if ((XEXP (condition, 0) == reg)
+  /* For the ARM special case of having a GTU: re-form the condition without
+ the unspec for the benefit of the middle-end.  */
+  if (GET_CODE (condition) == GTU)
+{
+  condition = gen_rtx_fmt_ee (GTU, VOIDmode, inc_src,
+ GEN_INT (dec_num - 1));
+  return condition;
+}

If you make the change I mentioned above, this re-forming isn't needed any 
more, so the arm-specific comment goes away
 
-   {
+{
  if (GET_CODE (pattern) != PARALLEL)
  /*  For the second form we expect:

You've fixed the indentation of the brace (good), but the body of the braced 
expression needs re-indenting as well.

R.



[PATCHSET] Update Rust frontend January 2024

2024-01-30 Thread arthur . cohen
Hi everyone,

This is our first upstream of 2024. It includes commits up to the 25th
of January, including fixes for some of the issues reported after our
previous patchset.

The fixes for little-endian platforms have yet to land as we are
investigating a weird scan-assembler regression on our OSX CI.

Best,

Arthur

[COMMITTED 001/101] gccrs: Add visibility to trait item
[COMMITTED 002/101] gccrs: Add a test to highlight public trait type
[COMMITTED 003/101] gccrs: Fix error emission for self pointers
[COMMITTED 004/101] gccrs: Report self parameter parsing error kind
[COMMITTED 005/101] gccrs: Add new test for parsing errors on self
[COMMITTED 006/101] gccrs: ast: Change *Path nodes API
[COMMITTED 007/101] gccrs: rib: Add Namespace enum
[COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic
[COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for
[COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature
[COMMITTED 011/101] gccrs: forever stack: Improve resolve_path
[COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path`
[COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method
[COMMITTED 014/101] gccrs: resolve: Format if properly
[COMMITTED 015/101] gccrs: forever stack: Remove development debug
[COMMITTED 016/101] gccrs: Reject auto traits with generic parameters
[COMMITTED 017/101] gccrs: Add regression test for generic auto
[COMMITTED 018/101] gccrs: Reject auto traits with super trait
[COMMITTED 019/101] gccrs: Add a regression test for super trait on
[COMMITTED 020/101] gccrs: Add check for associated items on auto
[COMMITTED 021/101] gccrs: Emit an error on variadic non extern
[COMMITTED 022/101] gccrs: Add a test regular variadic functions
[COMMITTED 023/101] gccrs: Add ast validation check on union variant
[COMMITTED 024/101] gccrs: Replace TOK suffix with KW
[COMMITTED 025/101] gccrs: Add edition separation for keywords
[COMMITTED 026/101] gccrs: Treat underscore as a keyword
[COMMITTED 027/101] gccrs: Add await keyword
[COMMITTED 028/101] gccrs: Replace some keyword raw values
[COMMITTED 029/101] gccrs: Add a list of weak keyword
[COMMITTED 030/101] gccrs: Replace some weak keyword raw value with
[COMMITTED 031/101] gccrs: Introduce a proper keyword list
[COMMITTED 032/101] gccrs: Added support to Parse ASYNC function
[COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the
[COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution
[COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function
[COMMITTED 036/101] gccrs: nr2.0: Store mappings in
[COMMITTED 037/101] gccrs: late: Start setting up builtin types
[COMMITTED 038/101] gccrs: late: Start storing mappings properly in
[COMMITTED 039/101] gccrs: early: Resolve paths properly
[COMMITTED 040/101] gccrs: toplevel: Add comment about running the
[COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class
[COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to
[COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations
[COMMITTED 044/101] gccrs: Create base class for TupleStructItems and
[COMMITTED 045/101] gccrs: Add unsafety member to modules
[COMMITTED 046/101] gccrs: Parse module safety
[COMMITTED 047/101] gccrs: Emit an error on unsafe modules
[COMMITTED 048/101] gccrs: Add a regression test for unsafe module
[COMMITTED 049/101] gccrs: Remove backend dependancy on resolution
[COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem
[COMMITTED 051/101] gccrs: Split async and const function qualifiers
[COMMITTED 052/101] gccrs: Allow const and async specifiers in
[COMMITTED 053/101] gccrs: Add async const function ast validation
[COMMITTED 054/101] gccrs: Add a regression test for async const
[COMMITTED 055/101] gccrs: Add AST validation check for const in
[COMMITTED 056/101] gccrs: Add regression test for const fn in trait
[COMMITTED 057/101] gccrs: Make feature gate visitor inherit from
[COMMITTED 058/101] gccrs: Change the attribute checker visitor to
[COMMITTED 059/101] gccrs: Make early name resolver inherit from
[COMMITTED 060/101] gccrs: Add multiple regression test in name
[COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0
[COMMITTED 062/101] gccrs: Make function bodies truly optional
[COMMITTED 063/101] gccrs: Add validation for functions without body
[COMMITTED 064/101] gccrs: Add a regression test for function body
[COMMITTED 065/101] gccrs: Generate error for const trait functions
[COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64`
[COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core
[COMMITTED 068/101] gccrs: Make default resolver inherit from default
[COMMITTED 069/101] gccrs: Make expand visitor inherit from default
[COMMITTED 070/101] gccrs: Change cfg stripper to use default visitor
[COMMITTED 071/101] gccrs: refactor builtins initialization and
[COMMITTED 072/101] gccrs: HIR: add missing getters
[COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard
[COMMITTED 074/101] gccrs: BIR: Fix missed nodiscard
[COMMIT

[COMMITTED 001/101] gccrs: Add visibility to trait item

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The compiler shall parse visibility modifiers on trait items and reject
those at a later stage (ast validation).

gcc/rust/ChangeLog:

* ast/rust-item.h (struct Visibility): Move Visibility from here...
* ast/rust-ast.h (struct Visibility): ...to here.
* parse/rust-parse-impl.h (Parser::parse_trait_item): Parse visibility
before giving it back to the item parsing function.
(Parser::parse_trait_type): Add visibility modifier.
* parse/rust-parse.h (RUST_PARSE_H): Change function prototype.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-ast.h  | 248 ---
 gcc/rust/ast/rust-item.h |   5 +-
 gcc/rust/parse/rust-parse-impl.h |  10 +-
 gcc/rust/parse/rust-parse.h  |   3 +-
 4 files changed, 140 insertions(+), 126 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 67ae92fb42d..4dc7f9710f3 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -490,6 +490,126 @@ operator!= (const SimplePath &lhs, const std::string &rhs)
 // forward decl for Attribute
 class AttrInput;
 
+// Visibility of item - if the item has it, then it is some form of public
+struct Visibility
+{
+public:
+  enum VisType
+  {
+PRIV,
+PUB,
+PUB_CRATE,
+PUB_SELF,
+PUB_SUPER,
+PUB_IN_PATH
+  };
+
+private:
+  VisType vis_type;
+  // Only assigned if vis_type is IN_PATH
+  SimplePath in_path;
+  location_t locus;
+
+  // should this store location info?
+
+public:
+  // Creates a Visibility - TODO make constructor protected or private?
+  Visibility (VisType vis_type, SimplePath in_path, location_t locus)
+: vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
+  {}
+
+  VisType get_vis_type () const { return vis_type; }
+
+  // Returns whether visibility is in an error state.
+  bool is_error () const
+  {
+return vis_type == PUB_IN_PATH && in_path.is_empty ();
+  }
+
+  // Returns whether a visibility has a path
+  bool has_path () const { return !is_error () && vis_type >= PUB_CRATE; }
+
+  // Returns whether visibility is public or not.
+  bool is_public () const { return vis_type != PRIV && !is_error (); }
+
+  location_t get_locus () const { return locus; }
+
+  // empty?
+  // Creates an error visibility.
+  static Visibility create_error ()
+  {
+return Visibility (PUB_IN_PATH, SimplePath::create_empty (),
+  UNDEF_LOCATION);
+  }
+
+  // Unique pointer custom clone function
+  /*std::unique_ptr clone_visibility() const {
+  return std::unique_ptr(clone_visibility_impl());
+  }*/
+
+  /* TODO: think of a way to only allow valid Visibility states - polymorphism
+   * is one idea but may be too resource-intensive. */
+
+  // Creates a public visibility with no further features/arguments.
+  // empty?
+  static Visibility create_public (location_t pub_vis_location)
+  {
+return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
+  }
+
+  // Creates a public visibility with crate-relative paths
+  static Visibility create_crate (location_t crate_tok_location,
+ location_t crate_vis_location)
+  {
+return Visibility (PUB_CRATE,
+  SimplePath::from_str ("crate", crate_tok_location),
+  crate_vis_location);
+  }
+
+  // Creates a public visibility with self-relative paths
+  static Visibility create_self (location_t self_tok_location,
+location_t self_vis_location)
+  {
+return Visibility (PUB_SELF,
+  SimplePath::from_str ("self", self_tok_location),
+  self_vis_location);
+  }
+
+  // Creates a public visibility with parent module-relative paths
+  static Visibility create_super (location_t super_tok_location,
+ location_t super_vis_location)
+  {
+return Visibility (PUB_SUPER,
+  SimplePath::from_str ("super", super_tok_location),
+  super_vis_location);
+  }
+
+  // Creates a private visibility
+  static Visibility create_private ()
+  {
+return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
+  }
+
+  // Creates a public visibility with a given path or whatever.
+  static Visibility create_in_path (SimplePath in_path,
+   location_t in_path_vis_location)
+  {
+return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
+  }
+
+  std::string as_string () const;
+  const SimplePath &get_path () const { return in_path; }
+  SimplePath &get_path () { return in_path; }
+
+protected:
+  // Clone function implementation - not currently virtual but may be if
+  // polymorphism used
+  /*virtual*/ Visibility *clone_visibility_impl () const
+  {
+return new Visibility (*this);
+  }
+};
+
 // aka Attr
 // Attribute AST representation
 struct Attribute
@@ -1042,125 +1162,6 @@ protecte

[COMMITTED 002/101] gccrs: Add a test to highlight public trait type parsing

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

This new test highlight the parser's behavior around public trait types.

gcc/testsuite/ChangeLog:

* rust/compile/trait_pub_type.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/trait_pub_type.rs | 6 ++
 1 file changed, 6 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/trait_pub_type.rs

diff --git a/gcc/testsuite/rust/compile/trait_pub_type.rs 
b/gcc/testsuite/rust/compile/trait_pub_type.rs
new file mode 100644
index 000..85f6462e3b5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/trait_pub_type.rs
@@ -0,0 +1,6 @@
+fn main() {}
+
+#[cfg(FALSE)]
+trait T {
+pub type X;
+}
-- 
2.42.1



[COMMITTED 004/101] gccrs: Report self parameter parsing error kind

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Self parameter parsing errors may come from different situations, which
should not be handled in the same way. It is now possible to
differentiate a missing self parameter from a self pointer or a parsing
error.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_function): Early return on
unrecoverable errors.
(Parser::parse_trait_item): Likewise.
(Parser::parse_self_param): Update return type.
* parse/rust-parse.h (enum ParseSelfError): Add enumeration to describe
different self parameter parsing errors.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/parse/rust-parse-impl.h | 72 
 gcc/rust/parse/rust-parse.h  | 12 +-
 2 files changed, 56 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 1ebe1ed442c..de17412c3b6 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2880,8 +2880,13 @@ Parser::parse_function 
(AST::Visibility vis,
   return nullptr;
 }
 
-  std::unique_ptr initial_param = parse_self_param ();
-  if (initial_param != nullptr)
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value ()
+  && initial_param.error () != ParseSelfError::NOT_SELF)
+return nullptr;
+
+  if (initial_param.has_value ())
 skip_token (COMMA);
 
   // parse function parameters (only if next token isn't right paren)
@@ -2891,9 +2896,9 @@ Parser::parse_function 
(AST::Visibility vis,
 function_params
   = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
 function_params.insert (function_params.begin (),
-   std::move (initial_param));
+   std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
 {
@@ -5063,13 +5068,15 @@ Parser::parse_trait_item ()
 
/* now for function vs method disambiguation - method has opening
 * "self" param */
-   std::unique_ptr initial_param = parse_self_param ();
+   auto initial_param = parse_self_param ();
+   if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+ return nullptr;
/* FIXME: ensure that self param doesn't accidently consume tokens for
 * a function */
bool is_method = false;
-   if (initial_param != nullptr)
+   if (initial_param.has_value ())
  {
-   if (initial_param->is_self ())
+   if ((*initial_param)->is_self ())
  is_method = true;
 
/* skip comma so function and method regular params can be parsed
@@ -5089,9 +5096,9 @@ Parser::parse_trait_item ()
return nullptr;
  }
 
-   if (initial_param != nullptr)
+   if (initial_param.has_value ())
  function_params.insert (function_params.begin (),
- std::move (initial_param));
+ std::move (*initial_param));
 
// parse return type (optional)
std::unique_ptr return_type = parse_function_return_type ();
@@ -5609,14 +5616,18 @@ 
Parser::parse_inherent_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+return nullptr;
+
   /* FIXME: ensure that self param doesn't accidently consume tokens for a
* function one idea is to lookahead up to 4 tokens to see whether self is
* one of them */
   bool is_method = false;
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
 {
-  if (initial_param->is_self ())
+  if ((*initial_param)->is_self ())
is_method = true;
 
   /* skip comma so function and method regular params can be parsed in
@@ -5629,9 +5640,9 @@ 
Parser::parse_inherent_impl_function_or_method (
   std::vector> function_params
 = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
 function_params.insert (function_params.begin (),
-   std::move (initial_param));
+   std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
 {
@@ -5817,13 +5828,17 @@ 
Parser::parse_trait_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+return nullptr;
+
   // FIXME: ensure that self param doesn't accidently consume tokens for a
   // function
   bool is_method = false;
-  if (initial_pa

[COMMITTED 008/101] gccrs: forever-stack: Fix basic get logic

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.h: Improve resolve_path API.
* resolve/rust-forever-stack.hxx: Likewise and fix implementation.
---
 gcc/rust/resolve/rust-forever-stack.h   | 19 +++--
 gcc/rust/resolve/rust-forever-stack.hxx | 38 -
 2 files changed, 29 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 7ee08491987..349d0971f61 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -473,7 +473,7 @@ public:
* @return a valid option with the NodeId if the path is present in the
* current map, an empty one otherwise.
*/
-  tl::optional resolve_path (const AST::SimplePath &path);
+  template  tl::optional resolve_path (const P &path);
 
   std::string as_debug_string ();
 
@@ -550,18 +550,19 @@ private:
 
   /* Helper types and functions for `resolve_path` */
 
-  using SegIterator = std::vector::const_iterator;
+  template 
+  using SegIterator = typename std::vector::const_iterator;
 
   Node &find_closest_module (Node &starting_point);
 
-  tl::optional
-  find_starting_point (const std::vector &segments,
-  Node &starting_point);
+  template 
+  tl::optional>
+  find_starting_point (const std::vector &segments, Node &starting_point);
 
-  tl::optional
-  resolve_segments (Node &starting_point,
-   const std::vector &segments,
-   SegIterator iterator);
+  template 
+  tl::optional resolve_segments (Node &starting_point,
+const std::vector &segments,
+SegIterator iterator);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 5acdf06c770..806745eb908 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -208,15 +208,8 @@ ForeverStack::update_cursor (Node &new_cursor)
 }
 
 template 
-tl::optional
-ForeverStack::get (const Identifier &name)
-{
-  return tl::nullopt;
-}
-
-template <>
 inline tl::optional
-ForeverStack::get (const Identifier &name)
+ForeverStack::get (const Identifier &name)
 {
   tl::optional resolved_node = tl::nullopt;
 
@@ -226,9 +219,9 @@ ForeverStack::get (const Identifier 
&name)
 
 return candidate.map_or (
   [&resolved_node] (NodeId found) {
-   // macro resolving does not need to care about various ribs - they are
-   // available from all contexts if defined in the current scope, or an
-   // outermore one. so if we do have a candidate, we can return it
+   // for most namespaces, we do not need to care about various ribs - they
+   // are available from all contexts if defined in the current scope, or
+   // an outermore one. so if we do have a candidate, we can return it
// directly and stop iterating
resolved_node = found;
 
@@ -278,9 +271,9 @@ ForeverStack::find_closest_module (Node &starting_point)
 
 /* If a the given condition is met, emit an error about misused leading path
  * segments */
+template 
 static inline bool
-check_leading_kw_at_start (const AST::SimplePathSegment &segment,
-  bool condition)
+check_leading_kw_at_start (const S &segment, bool condition)
 {
   if (condition)
 rust_error_at (
@@ -297,9 +290,10 @@ check_leading_kw_at_start (const AST::SimplePathSegment 
&segment,
 // `super` segment, we go back to the cursor's parent until we reach the
 // correct one or the root.
 template 
-tl::optional::const_iterator>
-ForeverStack::find_starting_point (
-  const std::vector &segments, Node &starting_point)
+template 
+tl::optional::const_iterator>
+ForeverStack::find_starting_point (const std::vector &segments,
+ Node &starting_point)
 {
   auto iterator = segments.begin ();
 
@@ -357,10 +351,11 @@ ForeverStack::find_starting_point (
 }
 
 template 
+template 
 tl::optional::Node &>
 ForeverStack::resolve_segments (
-  Node &starting_point, const std::vector &segments,
-  std::vector::const_iterator iterator)
+  Node &starting_point, const std::vector &segments,
+  typename std::vector::const_iterator iterator)
 {
   auto *current_node = &starting_point;
   for (; !is_last (iterator, segments); iterator++)
@@ -407,9 +402,14 @@ ForeverStack::resolve_segments (
 }
 
 template 
+template 
 tl::optional
-ForeverStack::resolve_path (const AST::SimplePath &path)
+ForeverStack::resolve_path (const P &path)
 {
+  // if there's only one segment, we just use `get`
+  if (path.get_segments ().size () == 1)
+return get (path.get_final_segment ().as_string ());
+
   auto starting_point = cursor ();
   auto &segments = path.get_segments ();
 
-- 
2.42.1



[COMMITTED 011/101] gccrs: forever stack: Improve resolve_path implementation

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.hxx: Do not copy segment when
dereferencing iterator in `find_starting_point`.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 8f0ab66b18b..642135cda85 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -333,7 +333,7 @@ ForeverStack::find_starting_point (const std::vector 
&segments,
 
   for (; !is_last (iterator, segments); iterator++)
 {
-  auto seg = *iterator;
+  auto &seg = *iterator;
   auto is_self_or_crate
= seg.is_crate_path_seg () || seg.is_lower_self_seg ();
 
-- 
2.42.1



[COMMITTED 003/101] gccrs: Fix error emission for self pointers

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Self pointer checking loop condition was inverted, the latter was
therefore never executed.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_self_param): Fix the loop
exit condition.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/parse/rust-parse-impl.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0ae89dc3907..1ebe1ed442c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7129,7 +7129,7 @@ Parser::parse_self_param ()
   for (auto &s : ptrs)
 {
   size_t i = 0;
-  for (i = 0; i > s.size (); i++)
+  for (i = 0; i < s.size (); i++)
if (lexer.peek_token (i)->get_id () != s[i])
  break;
   if (i == s.size ())
-- 
2.42.1



[COMMITTED 010/101] gccrs: forever stack: Fix resolve_path signature

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.h: Fix `ForeverStack::resolve_path`
signature.
* resolve/rust-forever-stack.hxx: Likewise.
* resolve/rust-early-name-resolver-2.0.cc (Early::visit): Use new API.
(Early::visit_attributes): Likewise.
---
 .../resolve/rust-early-name-resolver-2.0.cc |  8 +---
 gcc/rust/resolve/rust-forever-stack.h   |  5 -
 gcc/rust/resolve/rust-forever-stack.hxx | 17 +
 3 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 57a38078f14..2245ba31772 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -131,7 +131,7 @@ Early::visit (AST::MacroInvocation &invoc)
   // we won't have changed `definition` from `nullopt` if there are more
   // than one segments in our path
   if (!definition.has_value ())
-definition = ctx.macros.resolve_path (path);
+definition = ctx.macros.resolve_path (path.get_segments ());
 
   // if the definition still does not have a value, then it's an error
   if (!definition.has_value ())
@@ -188,7 +188,8 @@ Early::visit_attributes (std::vector &attrs)
  auto traits = attr.get_traits_to_derive ();
  for (auto &trait : traits)
{
- auto definition = ctx.macros.resolve_path (trait.get ());
+ auto definition
+   = ctx.macros.resolve_path (trait.get ().get_segments ());
  if (!definition.has_value ())
{
  // FIXME: Change to proper error message
@@ -210,7 +211,8 @@ Early::visit_attributes (std::vector &attrs)
 ->lookup_builtin (name)
 .is_error ()) // Do not resolve builtins
{
- auto definition = ctx.macros.resolve_path (attr.get_path ());
+ auto definition
+   = ctx.macros.resolve_path (attr.get_path ().get_segments ());
  if (!definition.has_value ())
{
  // FIXME: Change to proper error message
diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 349d0971f61..ec469a9b3fa 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -470,10 +470,13 @@ public:
   /**
* Resolve a path to its definition in the current `ForeverStack`
*
+   * // TODO: Add documentation for `segments`
+   *
* @return a valid option with the NodeId if the path is present in the
* current map, an empty one otherwise.
*/
-  template  tl::optional resolve_path (const P &path);
+  template 
+  tl::optional resolve_path (const std::vector &segments);
 
   std::string as_debug_string ();
 
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 211979fa9b9..8f0ab66b18b 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -429,24 +429,25 @@ ForeverStack::resolve_segments (
 }
 
 template 
-template 
+template 
 tl::optional
-ForeverStack::resolve_path (const P &path)
+ForeverStack::resolve_path (const std::vector &segments)
 {
+  // TODO: What to do if segments.empty() ?
+
   // if there's only one segment, we just use `get`
-  if (path.get_segments ().size () == 1)
-return get (path.get_final_segment ().as_string ());
+  if (segments.size () == 1)
+return get (segments.back ().as_string ());
 
   auto starting_point = cursor ();
-  auto &segments = path.get_segments ();
 
   return find_starting_point (segments, starting_point)
 .and_then ([this, &segments, &starting_point] (
-std::vector::const_iterator iterator) {
+typename std::vector::const_iterator iterator) {
   return resolve_segments (starting_point, segments, iterator);
 })
-.and_then ([&path] (Node final_node) {
-  return final_node.rib.get (path.get_final_segment ().as_string ());
+.and_then ([&segments] (Node final_node) {
+  return final_node.rib.get (segments.back ().as_string ());
 });
 }
 
-- 
2.42.1



[COMMITTED 013/101] gccrs: foreverstack: Add `to_rib` method

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.h: New method.
* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/resolve/rust-forever-stack.h   |  2 ++
 gcc/rust/resolve/rust-forever-stack.hxx | 20 +++-
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index 37277ddb3ad..a540e682e5b 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -585,6 +585,8 @@ private:
   // FIXME: Documentation
   tl::optional> dfs (Node &starting_point,
NodeId to_find);
+  // FIXME: Documentation
+  tl::optional dfs_rib (Node &starting_point, NodeId to_find);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 4e06da235bf..65796172b08 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -532,11 +532,29 @@ ForeverStack::to_canonical_path (NodeId id)
 
 template 
 tl::optional
-ForeverStack::to_rib (NodeId rib_id)
+ForeverStack::dfs_rib (ForeverStack::Node &starting_point, NodeId 
to_find)
 {
+  if (starting_point.id == to_find)
+return starting_point.rib;
+
+  for (auto &child : starting_point.children)
+{
+  auto candidate = dfs_rib (child.second, to_find);
+
+  if (candidate.has_value ())
+   return candidate;
+}
+
   return tl::nullopt;
 }
 
+template 
+tl::optional
+ForeverStack::to_rib (NodeId rib_id)
+{
+  return dfs_rib (root, rib_id);
+}
+
 template 
 void
 ForeverStack::stream_rib (std::stringstream &stream, const Rib &rib,
-- 
2.42.1



[COMMITTED 012/101] gccrs: foreverstack: Add `to_canonical_path` method

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.h: New method.
* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/resolve/rust-forever-stack.h   | 25 ++-
 gcc/rust/resolve/rust-forever-stack.hxx | 90 -
 2 files changed, 110 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index ec469a9b3fa..37277ddb3ad 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -396,7 +396,10 @@ template  class ForeverStack
 {
 public:
   ForeverStack ()
-: root (Node (Rib (Rib::Kind::Normal))), cursor_reference (root)
+// FIXME: Is that valid? Do we use the root? If yes, we should give the
+// crate's node id to ForeverStack's constructor
+: root (Node (Rib (Rib::Kind::Normal), UNKNOWN_NODEID)),
+  cursor_reference (root)
   {
 rust_assert (root.is_root ());
 rust_assert (root.is_leaf ());
@@ -478,6 +481,12 @@ public:
   template 
   tl::optional resolve_path (const std::vector &segments);
 
+  // FIXME: Documentation
+  tl::optional to_canonical_path (NodeId id);
+
+  // FIXME: Documentation
+  tl::optional to_rib (NodeId rib_id);
+
   std::string as_debug_string ();
 
 private:
@@ -509,8 +518,10 @@ private:
   class Node
   {
   public:
-Node (Rib rib) : rib (rib) {}
-Node (Rib rib, Node &parent) : rib (rib), parent (parent) {}
+Node (Rib rib, NodeId id) : rib (rib), id (id) {}
+Node (Rib rib, NodeId id, Node &parent)
+  : rib (rib), id (id), parent (parent)
+{}
 
 bool is_root () const;
 bool is_leaf () const;
@@ -520,6 +531,8 @@ private:
 Rib rib; // this is the "value" of the node - the data it keeps.
 std::map children; // all the other nodes it links to
 
+NodeId id; // The node id of the Node's scope
+
 tl::optional parent; // `None` only if the node is a root
   };
 
@@ -566,6 +579,12 @@ private:
   tl::optional resolve_segments (Node &starting_point,
 const std::vector &segments,
 SegIterator iterator);
+
+  /* Helper functions for forward resolution (to_canonical_path, to_rib...) */
+
+  // FIXME: Documentation
+  tl::optional> dfs (Node &starting_point,
+   NodeId to_find);
 };
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 642135cda85..4e06da235bf 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -66,8 +66,8 @@ ForeverStack::push_inner (Rib rib, Link link)
   // the iterator and a boolean. If the value already exists, the iterator
   // points to it. Otherwise, it points to the newly emplaced value, so we can
   // just update our cursor().
-  auto emplace
-= cursor ().children.emplace (std::make_pair (link, Node (rib, cursor 
(;
+  auto emplace = cursor ().children.emplace (
+std::make_pair (link, Node (rib, link.id, cursor (;
 
   auto it = emplace.first;
   auto existed = !emplace.second;
@@ -451,6 +451,92 @@ ForeverStack::resolve_path (const std::vector 
&segments)
 });
 }
 
+template 
+tl::optional::Node &, std::string>>
+ForeverStack::dfs (ForeverStack::Node &starting_point, NodeId to_find)
+{
+  auto &values = starting_point.rib.get_values ();
+
+  for (auto &kv : values)
+if (kv.second == to_find)
+  return {{starting_point, kv.first}};
+
+  for (auto &child : starting_point.children)
+{
+  auto candidate = dfs (child.second, to_find);
+
+  if (candidate.has_value ())
+   return candidate;
+}
+
+  return tl::nullopt;
+}
+
+template 
+tl::optional
+ForeverStack::to_canonical_path (NodeId id)
+{
+  // find the id in the current forever stack, starting from the root,
+  // performing either a BFS or DFS once the Node containing the ID is found, 
go
+  // back up to the root (parent().parent().parent()...) accumulate link
+  // segments reverse them that's your canonical path
+
+  return dfs (root, id).map ([this, id] (std::pair tuple) 
{
+auto containing_node = tuple.first;
+auto name = tuple.second;
+
+auto segments = std::vector ();
+
+reverse_iter (containing_node, [&segments] (Node ¤t) {
+  if (current.is_root ())
+   return KeepGoing::No;
+
+  auto children = current.parent.value ().children;
+  const Link *outer_link = nullptr;
+
+  for (auto &kv : children)
+   {
+ auto &link = kv.first;
+ auto &child = kv.second;
+
+ if (link.id == child.id)
+   {
+ outer_link = &link;
+ break;
+   }
+   }
+
+  rust_assert (outer_link);
+
+  outer_link->path.map ([&segments, outer_link] (Identifier path) {
+   segments.emplace (segments.begin (),
+ Resolver::CanonicalPath::new_seg (outer_link->id,
+ 

[COMMITTED 005/101] gccrs: Add new test for parsing errors on self pointers

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add new tests to highlight the behavior of errors thrown when meeting a
self pointer.

gcc/testsuite/ChangeLog:

* rust/compile/self_const_ptr.rs: New test.
* rust/compile/self_mut_ptr.rs: New test.
* rust/compile/self_ptr.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/self_const_ptr.rs | 8 
 gcc/testsuite/rust/compile/self_mut_ptr.rs   | 8 
 gcc/testsuite/rust/compile/self_ptr.rs   | 8 
 3 files changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/self_const_ptr.rs
 create mode 100644 gcc/testsuite/rust/compile/self_mut_ptr.rs
 create mode 100644 gcc/testsuite/rust/compile/self_ptr.rs

diff --git a/gcc/testsuite/rust/compile/self_const_ptr.rs 
b/gcc/testsuite/rust/compile/self_const_ptr.rs
new file mode 100644
index 000..014fe1b63d8
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_const_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+pub fn do_something(*const self) {}
+// { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse inherent impl item in inherent impl" "" { 
target *-*-* } .-2 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/rust/compile/self_mut_ptr.rs 
b/gcc/testsuite/rust/compile/self_mut_ptr.rs
new file mode 100644
index 000..2a127b7dcb2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_mut_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+pub fn do_something(*mut self) {}
+// { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse inherent impl item in inherent impl" "" { 
target *-*-* } .-2 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
diff --git a/gcc/testsuite/rust/compile/self_ptr.rs 
b/gcc/testsuite/rust/compile/self_ptr.rs
new file mode 100644
index 000..fd7ff6ce5d2
--- /dev/null
+++ b/gcc/testsuite/rust/compile/self_ptr.rs
@@ -0,0 +1,8 @@
+struct MyStruct;
+
+impl MyStruct {
+pub fn do_something(*self) {}
+// { dg-error "cannot pass .self. by raw pointer" "" { target *-*-* } .-1 }
+// { dg-error "failed to parse inherent impl item in inherent impl" "" { 
target *-*-* } .-2 }
+// { dg-error "failed to parse item in crate" "" { target *-*-* } .-3 }
+}
-- 
2.42.1



[COMMITTED 006/101] gccrs: ast: Change *Path nodes API

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-ast.h: Change Path API to be more consistent.
* ast/rust-path.h: Likewise.
* ast/rust-ast-collector.cc (TokenCollector::visit): Use new API.
* resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise.
* resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): 
Likewise.
* resolve/rust-forever-stack.hxx: Likewise.
---
 gcc/rust/ast/rust-ast-collector.cc| 2 +-
 gcc/rust/ast/rust-ast.h   | 2 +-
 gcc/rust/ast/rust-path.h  | 9 +
 gcc/rust/resolve/rust-ast-resolve-item.cc | 2 +-
 gcc/rust/resolve/rust-ast-resolve-path.cc | 2 +-
 gcc/rust/resolve/rust-forever-stack.hxx   | 7 ---
 6 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index cb8dfd80016..7d3d3e204f7 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -191,7 +191,7 @@ TokenCollector::visit (SimplePathSegment &segment)
 {
   push (Rust::Token::make (SUPER, segment.get_locus ()));
 }
-  else if (segment.is_lower_self ())
+  else if (segment.is_lower_self_seg ())
 {
   push (Rust::Token::make (SELF, segment.get_locus ()));
 }
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4dc7f9710f3..47c02d6ac8b 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -399,7 +399,7 @@ public:
   {
 return as_string ().compare ("crate") == 0;
   }
-  bool is_lower_self () const { return as_string ().compare ("self") == 0; }
+  bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; 
}
   bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index b76664fa7dd..ccac6303bb4 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -536,6 +536,7 @@ public:
   {
 return !has_generic_args () && get_ident_segment ().is_crate_segment ();
   }
+
   bool is_lower_self_seg () const
   {
 return !has_generic_args () && get_ident_segment ().is_lower_self ();
@@ -646,6 +647,14 @@ public:
 outer_attrs = std::move (new_attrs);
   }
 
+  NodeId get_pattern_node_id () const { return get_node_id (); }
+
+  PathExprSegment &get_final_segment () { return get_segments ().back (); }
+  const PathExprSegment &get_final_segment () const
+  {
+return get_segments ().back ();
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc 
b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 1fc6b920c5e..eaee5bc8606 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -1031,7 +1031,7 @@ ResolveItem::visit (AST::UseDeclaration &use_item)
   if (!ok)
continue;
 
-  const AST::SimplePathSegment &final_seg = path.get_final_segment ();
+  const AST::SimplePathSegment &final_seg = path.get_segments ().back ();
 
   auto decl
= CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ());
diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc 
b/gcc/rust/resolve/rust-ast-resolve-path.cc
index fd2a844a506..9e982d0610e 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -367,7 +367,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
   // is_first_segment ? "true" : "false",
   // is_final_segment ? "true" : "false");
   if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
- && is_final_segment && segment.is_lower_self ())
+ && is_final_segment && segment.is_lower_self_seg ())
{
  resolved_node_id = previous_resolved_node_id;
}
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 8bdda67782a..5acdf06c770 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -313,7 +313,8 @@ ForeverStack::find_starting_point (
   for (; !is_last (iterator, segments); iterator++)
 {
   auto seg = *iterator;
-  auto is_self_or_crate = seg.is_crate_path_seg () || seg.is_lower_self ();
+  auto is_self_or_crate
+   = seg.is_crate_path_seg () || seg.is_lower_self_seg ();
 
   // if we're after the first path segment and meet `self` or `crate`, it's
   // an error - we should only be seeing `super` keywords at this point
@@ -327,7 +328,7 @@ ForeverStack::find_starting_point (
  iterator++;
  break;
}
-  if (seg.is_lower_self ())
+  if (seg.is_lower_self_seg ())
{
  // do nothing and exit
  iterator++;
@@ -371,7 +372,7 @@ ForeverStack::resolve_segments (
   // check that we don't encounter *any* leading keywords afterwards
   if (ch

[COMMITTED 014/101] gccrs: resolve: Format if properly

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-ast-resolve-path.cc (ResolvePath::resolve_path): Format.
---
 gcc/rust/resolve/rust-ast-resolve-path.cc | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/gcc/rust/resolve/rust-ast-resolve-path.cc 
b/gcc/rust/resolve/rust-ast-resolve-path.cc
index 9e982d0610e..56c352e13ea 100644
--- a/gcc/rust/resolve/rust-ast-resolve-path.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-path.cc
@@ -368,9 +368,7 @@ ResolvePath::resolve_path (AST::SimplePath *expr)
   // is_final_segment ? "true" : "false");
   if (resolved_node_id == UNKNOWN_NODEID && !is_first_segment
  && is_final_segment && segment.is_lower_self_seg ())
-   {
- resolved_node_id = previous_resolved_node_id;
-   }
+   resolved_node_id = previous_resolved_node_id;
 
   // final check
   if (resolved_node_id == UNKNOWN_NODEID)
-- 
2.42.1



[COMMITTED 022/101] gccrs: Add a test regular variadic functions errors

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add a new regression test for the error message in regular function
variadic errors during ast validation pass.

gcc/testsuite/ChangeLog:

* rust/compile/non_foreign_variadic_function.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/non_foreign_variadic_function.rs | 4 
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/non_foreign_variadic_function.rs

diff --git a/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs 
b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs
new file mode 100644
index 000..2a4d3090a66
--- /dev/null
+++ b/gcc/testsuite/rust/compile/non_foreign_variadic_function.rs
@@ -0,0 +1,4 @@
+pub fn toto(a: i32, ...) {}
+// { dg-error "only foreign or .unsafe extern .C.. functions may be 
C-variadic" "" { target *-*-* } .-1 }
+
+fn main() {}
-- 
2.42.1



[COMMITTED 015/101] gccrs: forever stack: Remove development debug info

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.hxx: Remove debug log.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 2 --
 1 file changed, 2 deletions(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 65796172b08..867144adf92 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -523,8 +523,6 @@ ForeverStack::to_canonical_path (NodeId id)
 
 // Finally, append the name
 path = path.append (Resolver::CanonicalPath::new_seg (id, name));
-rust_debug ("[ARTHUR] found path: %s. Size: %lu", path.get ().c_str (),
-   segments.size ());
 
 return path;
   });
-- 
2.42.1



[COMMITTED 020/101] gccrs: Add check for associated items on auto traits

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Reject rust code with associated items on auto traits.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add auto
trait associated item check in AST validation pass.
* parse/rust-parse-impl.h: Remove old error emission done during
parsing pass.

gcc/testsuite/ChangeLog:

* rust/compile/auto_trait_invalid.rs: Update old test with updated
error message.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc|  7 +++
 gcc/rust/parse/rust-parse-impl.h | 12 
 gcc/testsuite/rust/compile/auto_trait_invalid.rs |  5 +++--
 3 files changed, 10 insertions(+), 14 deletions(-)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index aeae6035db8..673290959f4 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -109,6 +109,13 @@ ASTValidation::visit (AST::Trait &trait)
rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (),
   ErrorCode::E0568,
   "auto traits cannot have super traits");
+  if (trait.has_trait_items ())
+   {
+ rust_error_at (trait.get_identifier ().get_locus (), ErrorCode::E0380,
+"auto traits cannot have methods or associated items");
+ for (const auto &item : trait.get_trait_items ())
+   Error::Hint (item->get_locus (), "remove this item").emit ();
+   }
 }
 
   AST::ContextualASTVisitor::visit (trait);
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index de17412c3b6..45c72e495c2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4989,18 +4989,6 @@ Parser::parse_trait (AST::Visibility 
vis,
   return nullptr;
 }
 
-  if (is_auto_trait && !trait_items.empty ())
-{
-  add_error (Error (locus, ErrorCode::E0380,
-   "auto traits cannot have associated items"));
-
-  // FIXME: unsure if this should be done at parsing time or not
-  for (const auto &item : trait_items)
-   add_error (Error::Hint (item->get_locus (), "remove this item"));
-
-  return nullptr;
-}
-
   trait_items.shrink_to_fit ();
   return std::unique_ptr (
 new AST::Trait (std::move (ident), is_unsafe, is_auto_trait,
diff --git a/gcc/testsuite/rust/compile/auto_trait_invalid.rs 
b/gcc/testsuite/rust/compile/auto_trait_invalid.rs
index 66e45531f5d..3be2acbb53b 100644
--- a/gcc/testsuite/rust/compile/auto_trait_invalid.rs
+++ b/gcc/testsuite/rust/compile/auto_trait_invalid.rs
@@ -2,7 +2,9 @@
 
 #![feature(optin_builtin_traits)]
 
-unsafe auto trait Invalid { // { dg-error "auto traits cannot have associated 
items" }
+auto trait Invalid {
+// { dg-error "auto traits cannot have methods or associated items" "" { 
target *-*-* } .-1 }
+
 fn foo(); // { dg-message "remove this item" }
 
 fn bar() {} // { dg-message "remove this item" }
@@ -13,4 +15,3 @@ unsafe auto trait Invalid { // { dg-error "auto traits cannot 
have associated it
 
 const BAR: i32 = 15; // { dg-message "remove this item" }
 }
-// { dg-error "failed to parse item in crate" "" {target *-*-* } .+1 }
-- 
2.42.1



[COMMITTED 033/101] gccrs: ctx: Add Labels ForeverStack to the resolver.

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

Not sure if dealing with "labels" is the proper way of doing so, so we
might eventually change this to use `resolver.values` later on.

gcc/rust/ChangeLog:

* resolve/rust-name-resolution-context.h: Add a Labels stack.
---
 gcc/rust/resolve/rust-name-resolution-context.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index 64db5d1a580..6d14be35986 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -173,6 +173,7 @@ public:
   ForeverStack values;
   ForeverStack types;
   ForeverStack macros;
+  ForeverStack labels;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1



[COMMITTED 007/101] gccrs: rib: Add Namespace enum

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-rib.h: Add Namespace enum.
---
 gcc/rust/resolve/rust-rib.h | 25 +
 1 file changed, 25 insertions(+)

diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index 37bd90f1f75..4ffd00a5d6c 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -27,6 +27,31 @@
 namespace Rust {
 namespace Resolver2_0 {
 
+/**
+
+pub enum Namespace {
+   /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and
+`mod`s
+   /// (and, by extension, crates).
+   ///
+   /// Note that the type namespace includes other items; this is not an
+   /// exhaustive list.
+   TypeNS,
+   /// The value namespace includes `fn`s, `const`s, `static`s, and local
+variables (including function arguments). ValueNS,
+   /// The macro namespace includes `macro_rules!` macros, declarative 
`macro`s,
+   /// procedural macros, attribute macros, `derive` macros, and non-macro
+attributes
+   /// like `#[inline]` and `#[rustfmt::skip]`.
+   MacroNS,
+}
+
+*/
+
+// FIXME: There's no `labels` namespace, not sure if we need one or how to keep
+// one
+// FIXME: And where are things like loop labels kept?
+
 /**
  * All namespaces that Rust's name resolution needs to handle
  */
-- 
2.42.1



[COMMITTED 018/101] gccrs: Reject auto traits with super trait

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Reject auto traits containing a super trait bound during AST validation
pass.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Reject
auto traits with super traits.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 4 
 1 file changed, 4 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 37d3668a9e0..aeae6035db8 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -105,6 +105,10 @@ ASTValidation::visit (AST::Trait &trait)
rust_error_at (trait.get_generic_params ()[0]->get_locus (),
   ErrorCode::E0567,
   "auto traits cannot have generic parameters");
+  if (trait.has_type_param_bounds ())
+   rust_error_at (trait.get_type_param_bounds ()[0]->get_locus (),
+  ErrorCode::E0568,
+  "auto traits cannot have super traits");
 }
 
   AST::ContextualASTVisitor::visit (trait);
-- 
2.42.1



[COMMITTED 017/101] gccrs: Add regression test for generic auto traits

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Generics are forbidden on auto traits and an error should be emitted.
This commit highlight this behavior.

gcc/testsuite/ChangeLog:

* rust/compile/generic_auto_trait.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/generic_auto_trait.rs | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/generic_auto_trait.rs

diff --git a/gcc/testsuite/rust/compile/generic_auto_trait.rs 
b/gcc/testsuite/rust/compile/generic_auto_trait.rs
new file mode 100644
index 000..ae6a51d0244
--- /dev/null
+++ b/gcc/testsuite/rust/compile/generic_auto_trait.rs
@@ -0,0 +1,2 @@
+auto trait IsCooler {}
+// { dg-error "auto traits cannot have generic parameters .E0567." "" { target 
*-*-* } .-1 }
-- 
2.42.1



[COMMITTED 024/101] gccrs: Replace TOK suffix with KW

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

TOK suffix was chosen to disambiguate some identifiers with c++ reserved
keyword. Even though this list lies within the rust-token header, this
macro is used in many context sometimes unrelated with the lexer and
tokens. This TOK suffix may appear surprising in such context.

gcc/rust/ChangeLog:

* lex/rust-token.h (enum PrimitiveCoreType): Change keyword suffix from
tok to kw.
* ast/rust-ast-collector.cc (TokenCollector::visit): Update suffix to
match the new declaration.
* lex/rust-lex.cc (Lexer::parse_raw_identifier): Likewise.
* parse/rust-parse-impl.h (can_tok_start_type): Likewise.
(Parser::parse_item): Likewise.
(Parser::parse_vis_item): Likewise.
(Parser::parse_extern_crate): Likewise.
(Parser::parse_function): Likewise.
(Parser::parse_function_qualifiers): Likewise.
(Parser::parse_struct): Likewise.
(Parser::parse_enum): Likewise.
(Parser::parse_static_item): Likewise.
(Parser::parse_trait_item): Likewise.
(Parser::parse_inherent_impl_item): Likewise.
(Parser::parse_trait_impl_item): Likewise.
(Parser::parse_extern_block): Likewise.
(Parser::parse_external_item): Likewise.
(Parser::parse_stmt): Likewise.
(Parser::parse_return_expr): Likewise.
(Parser::parse_match_expr): Likewise.
(Parser::parse_type): Likewise.
(Parser::parse_for_prefixed_type): Likewise.
(Parser::parse_type_no_bounds): Likewise.
(Parser::parse_stmt_or_expr): Likewise.
* parse/rust-parse.cc (peculiar_fragment_match_compatible): Likewie.
* util/rust-token-converter.cc (convert): Likewise.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-ast-collector.cc|  30 +++---
 gcc/rust/lex/rust-lex.cc  |   2 +-
 gcc/rust/lex/rust-token.h |  20 ++--
 gcc/rust/parse/rust-parse-impl.h  | 134 +-
 gcc/rust/parse/rust-parse.cc  |  18 ++--
 gcc/rust/util/rust-token-converter.cc |  18 ++--
 6 files changed, 111 insertions(+), 111 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 7d3d3e204f7..8f394e595ed 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -332,7 +332,7 @@ TokenCollector::visit (FunctionQualifiers &qualifiers)
 push (Rust::Token::make (UNSAFE, qualifiers.get_locus ()));
   if (qualifiers.is_extern ())
 {
-  push (Rust::Token::make (EXTERN_TOK, qualifiers.get_locus ()));
+  push (Rust::Token::make (EXTERN_KW, qualifiers.get_locus ()));
   if (qualifiers.has_abi ())
{
  push (Rust::Token::make_string (UNDEF_LOCATION,
@@ -1323,7 +1323,7 @@ TokenCollector::visit (RangeToInclExpr &expr)
 void
 TokenCollector::visit (ReturnExpr &expr)
 {
-  push (Rust::Token::make (RETURN_TOK, expr.get_locus ()));
+  push (Rust::Token::make (RETURN_KW, expr.get_locus ()));
   if (expr.has_returned_expr ())
 visit (expr.get_returned_expr ());
 }
@@ -1463,7 +1463,7 @@ TokenCollector::visit (MatchCase &match_case)
 void
 TokenCollector::visit (MatchExpr &expr)
 {
-  push (Rust::Token::make (MATCH_TOK, expr.get_locus ()));
+  push (Rust::Token::make (MATCH_KW, expr.get_locus ()));
   visit (expr.get_scrutinee_expr ());
   push (Rust::Token::make (LEFT_CURLY, UNDEF_LOCATION));
   newline ();
@@ -1609,7 +1609,7 @@ void
 TokenCollector::visit (ExternCrate &crate)
 {
   visit_items_as_lines (crate.get_outer_attrs ());
-  push (Rust::Token::make (EXTERN_TOK, crate.get_locus ()));
+  push (Rust::Token::make (EXTERN_KW, crate.get_locus ()));
   push (Rust::Token::make (CRATE, UNDEF_LOCATION));
   auto ref = crate.get_referenced_crate ();
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (ref)));
@@ -1717,7 +1717,7 @@ TokenCollector::visit (Function &function)
   auto qualifiers = function.get_qualifiers ();
   visit (qualifiers);
 
-  push (Rust::Token::make (FN_TOK, function.get_locus ()));
+  push (Rust::Token::make (FN_KW, function.get_locus ()));
   auto name = function.get_function_name ().as_string ();
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (name)));
   if (function.has_generics ())
@@ -1778,7 +1778,7 @@ TokenCollector::visit (StructStruct &struct_item)
   if (struct_item.has_visibility ())
 visit (struct_item.get_visibility ());
   auto struct_name = struct_item.get_identifier ().as_string ();
-  push (Rust::Token::make (STRUCT_TOK, struct_item.get_locus ()));
+  push (Rust::Token::make (STRUCT_KW, struct_item.get_locus ()));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move 
(struct_name)));
 
   if (struct_item.has_generics ())
@@ -1800,7 +1800,7 @@ TokenCollector::visit (TupleStruct &tuple_struct)
 {
   visit_items_as_lines (tuple_struct.get_outer_attrs ());
   auto struct_name = tuple_struct.get_identifier ().as_string ();
-  push (Rust::Tok

[COMMITTED 049/101] gccrs: Remove backend dependancy on resolution rib information

2024-01-30 Thread arthur . cohen
From: Philip Herron 

When making more desugaring for the HIR we can need to add new Let bindings
which will require namesolution information but also rib information for
which block the let binding is associated which was very unnessecary. This
patch simply updates the BLOCK_CONTEXT of the current scope as we are
compiling and encounter HIR::LetStmts instead of trying to do it all
upfront which lots of wierd checks

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc 
(HIRCompileBase::compile_locals_for_block): removed
* backend/rust-compile-base.h: update header
* backend/rust-compile-block.cc (CompileBlock::visit): remove old logic
* backend/rust-compile-expr.cc 
(CompileExpr::generate_closure_function): likewise
* backend/rust-compile-stmt.cc (CompileStmt::visit): likewise
* backend/rust-compile-var-decl.h: ensure we setup tuple bindings 
correctly

Signed-off-by: Philip Herron 
---
 gcc/rust/backend/rust-compile-base.cc| 51 +-
 gcc/rust/backend/rust-compile-base.h |  3 --
 gcc/rust/backend/rust-compile-block.cc   | 13 +
 gcc/rust/backend/rust-compile-expr.cc|  5 +-
 gcc/rust/backend/rust-compile-stmt.cc| 16 --
 gcc/rust/backend/rust-compile-var-decl.h | 69 +++-
 6 files changed, 71 insertions(+), 86 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index ae9f6707b72..fcab75bef1c 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -564,35 +564,6 @@ HIRCompileBase::indirect_expression (tree expr, location_t 
locus)
   return build_fold_indirect_ref_loc (locus, expr);
 }
 
-std::vector
-HIRCompileBase::compile_locals_for_block (Context *ctx, Resolver::Rib &rib,
- tree fndecl)
-{
-  std::vector locals;
-  for (auto it : rib.get_declarations ())
-{
-  NodeId node_id = it.first;
-  HirId ref = UNKNOWN_HIRID;
-  if (!ctx->get_mappings ()->lookup_node_to_hir (node_id, &ref))
-   continue;
-
-  // we only care about local patterns
-  HIR::Pattern *pattern = ctx->get_mappings ()->lookup_hir_pattern (ref);
-  if (pattern == nullptr)
-   continue;
-
-  // lookup the type
-  TyTy::BaseType *tyty = nullptr;
-  if (!ctx->get_tyctx ()->lookup_type (ref, &tyty))
-   continue;
-
-  // compile the local
-  tree type = TyTyResolveCompile::compile (ctx, tyty);
-  CompileVarDecl::compile (fndecl, type, pattern, locals, ctx);
-}
-  return locals;
-}
-
 void
 HIRCompileBase::compile_function_body (tree fndecl,
   HIR::BlockExpr &function_body,
@@ -750,21 +721,11 @@ HIRCompileBase::compile_function (
   if (!Backend::function_set_parameters (fndecl, param_vars))
 return error_mark_node;
 
-  // lookup locals
-  auto body_mappings = function_body->get_mappings ();
-  Resolver::Rib *rib = nullptr;
-  bool ok
-= ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib);
-  rust_assert (ok);
-
-  std::vector locals
-= compile_locals_for_block (ctx, *rib, fndecl);
-
   tree enclosing_scope = NULL_TREE;
   location_t start_location = function_body->get_locus ();
   location_t end_location = function_body->get_end_locus ();
 
-  tree code_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
start_location, end_location);
   ctx->push_block (code_block);
 
@@ -820,7 +781,6 @@ HIRCompileBase::compile_constant_item (
   tree fndecl = Backend::function (compiled_fn_type, ident, "", 0, locus);
   TREE_READONLY (fndecl) = 1;
 
-  std::vector locals;
   tree enclosing_scope = NULL_TREE;
   location_t start_location = const_value_expr->get_locus ();
   location_t end_location = const_value_expr->get_locus ();
@@ -830,16 +790,9 @@ HIRCompileBase::compile_constant_item (
= static_cast (const_value_expr);
   start_location = function_body->get_locus ();
   end_location = function_body->get_end_locus ();
-
-  Resolver::Rib *rib = nullptr;
-  bool ok = ctx->get_resolver ()->find_name_rib (
-   function_body->get_mappings ().get_nodeid (), &rib);
-  rust_assert (ok);
-
-  locals = compile_locals_for_block (ctx, *rib, fndecl);
 }
 
-  tree code_block = Backend::block (fndecl, enclosing_scope, locals,
+  tree code_block = Backend::block (fndecl, enclosing_scope, {} /*locals*/,
start_location, end_location);
   ctx->push_block (code_block);
 
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index 65291234b23..c5816584c72 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -145,9 +145,6 @@ protected:
 
   static bool mark_addressable (tree, location_t);
 
-  static std::vector
-  compile_locals_for_block 

[COMMITTED 009/101] gccrs: foreverstack: Specialize `get` for Namespace::Labels

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-forever-stack.hxx: Add specific behavior for
`ForeverStack::get` when dealing with labels.
---
 gcc/rust/resolve/rust-forever-stack.hxx | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 806745eb908..211979fa9b9 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -208,7 +208,7 @@ ForeverStack::update_cursor (Node &new_cursor)
 }
 
 template 
-inline tl::optional
+tl::optional
 ForeverStack::get (const Identifier &name)
 {
   tl::optional resolved_node = tl::nullopt;
@@ -234,6 +234,33 @@ ForeverStack::get (const Identifier &name)
   return resolved_node;
 }
 
+template <>
+tl::optional inline ForeverStack::get (
+  const Identifier &name)
+{
+  tl::optional resolved_node = tl::nullopt;
+
+  reverse_iter ([&resolved_node, &name] (Node ¤t) {
+// looking up for labels cannot go through function ribs
+// TODO: What other ribs?
+if (current.rib.kind == Rib::Kind::Function)
+  return KeepGoing::No;
+
+auto candidate = current.rib.get (name.as_string ());
+
+// FIXME: Factor this in a function with the generic `get`
+return candidate.map_or (
+  [&resolved_node] (NodeId found) {
+   resolved_node = found;
+
+   return KeepGoing::No;
+  },
+  KeepGoing::Yes);
+  });
+
+  return resolved_node;
+}
+
 /* Check if an iterator points to the last element */
 template 
 static bool
-- 
2.42.1



[COMMITTED 035/101] gccrs: toplevel: Use DefaultResolver for Function

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::visit): Use
the DefaultResolver in the toplevel visitor.
---
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index fc62db729b5..fbded3e49e1 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -185,10 +185,7 @@ TopLevel::visit (AST::Function &function)
   insert_or_error_out (function.get_function_name (), function,
   Namespace::Values);
 
-  auto def_fn
-= [this, &function] () { function.get_definition ()->accept_vis (*this); };
-
-  ctx.scoped (Rib::Kind::Function, function.get_node_id (), def_fn);
+  DefaultResolver::visit (function);
 }
 
 void
-- 
2.42.1



[COMMITTED 021/101] gccrs: Emit an error on variadic non extern functions

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Variadic regular functions were recently added in the parser as they
should be rejected in the ast validation pass. This commit add the ast
validation pass rejecting this kind of variadic arguments.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
ast validation pass to reject variadic arguments on regular functions.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 5 +
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 673290959f4..4142cc6317e 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -93,6 +93,11 @@ ASTValidation::visit (AST::Function &function)
   function.get_self_param ()->get_locus (),
   "% parameter is only allowed in associated functions");
 
+  if (function.is_variadic ())
+rust_error_at (
+  function.get_function_params ().back ()->get_locus (),
+  "only foreign or % functions may be C-variadic");
+
   AST::ContextualASTVisitor::visit (function);
 }
 
-- 
2.42.1



[COMMITTED 030/101] gccrs: Replace some weak keyword raw value with constexpr

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Raw values may have typos or contain error, replacing those will
improve the codebase.

gcc/rust/ChangeLog:

* ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value.
* parse/rust-parse-impl.h (Parser::is_macro_rules_def): Likewise.
(Parser::parse_item): Likewise.
(Parser::parse_vis_item): Likewise.
(Parser::parse_macro_rules_def): Likewise.
(Parser::parse_union): Likewise.
(Parser::parse_trait_impl_item): Likewise.
(Parser::parse_stmt): Likewise.
(Parser::parse_stmt_or_expr): Likewise.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-ast-collector.cc |  6 --
 gcc/rust/parse/rust-parse-impl.h   | 24 +---
 2 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 5b12875c349..3e3a959578e 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -1875,7 +1875,8 @@ TokenCollector::visit (Union &union_item)
 {
   visit_items_as_lines (union_item.get_outer_attrs ());
   auto id = union_item.get_identifier ().as_string ();
-  push (Rust::Token::make_identifier (union_item.get_locus (), "union"));
+  push (Rust::Token::make_identifier (union_item.get_locus (),
+ Values::WeakKeywords::UNION));
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id)));
 
   if (union_item.has_generics ())
@@ -2256,7 +2257,8 @@ TokenCollector::visit (MacroRulesDefinition &rules_def)
 
   auto rule_name = rules_def.get_rule_name ().as_string ();
 
-  push (Rust::Token::make_identifier (rules_def.get_locus (), "macro_rules"));
+  push (Rust::Token::make_identifier (rules_def.get_locus (),
+ Values::WeakKeywords::MACRO_RULES));
   push (Rust::Token::make (EXCLAM, UNDEF_LOCATION));
 
   push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (rule_name)));
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 28659060568..37eddc1b753 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1085,7 +1085,7 @@ Parser::is_macro_rules_def 
(const_TokenPtr t)
 
   bool allowed_macro_name = (macro_name == IDENTIFIER || macro_name == TRY);
 
-  return t->get_str () == "macro_rules"
+  return t->get_str () == Values::WeakKeywords::MACRO_RULES
 && lexer.peek_token (1)->get_id () == EXCLAM && allowed_macro_name;
 }
 
@@ -1146,13 +1146,13 @@ Parser::parse_item (bool 
called_from_statement)
 // crappy hack to do union "keyword"
 case IDENTIFIER:
   // TODO: ensure std::string and literal comparison works
-  if (t->get_str () == "union"
+  if (t->get_str () == Values::WeakKeywords::UNION
  && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  return parse_vis_item (std::move (outer_attrs));
  // or should this go straight to parsing union?
}
-  else if (t->get_str () == "default"
+  else if (t->get_str () == Values::WeakKeywords::DEFAULT
   && lexer.peek_token (1)->get_id () != EXCLAM)
{
  add_error (Error (t->get_locus (),
@@ -1357,7 +1357,7 @@ Parser::parse_vis_item (AST::AttrVec 
outer_attrs)
 // TODO: implement union keyword but not really because of
 // context-dependence case UNION: crappy hack to do union "keyword"
 case IDENTIFIER:
-  if (t->get_str () == "union"
+  if (t->get_str () == Values::WeakKeywords::UNION
  && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  return parse_union (std::move (vis), std::move (outer_attrs));
@@ -1436,7 +1436,8 @@ Parser::parse_macro_rules_def 
(AST::AttrVec outer_attrs)
 {
   // ensure that first token is identifier saying "macro_rules"
   const_TokenPtr t = lexer.peek_token ();
-  if (t->get_id () != IDENTIFIER || t->get_str () != "macro_rules")
+  if (t->get_id () != IDENTIFIER
+  || t->get_str () != Values::WeakKeywords::MACRO_RULES)
 {
   Error error (
t->get_locus (),
@@ -4734,7 +4735,7 @@ Parser::parse_union (AST::Visibility 
vis,
   /* hack - "weak keyword" by finding identifier called "union" (lookahead in
* item switch) */
   const_TokenPtr union_keyword = expect_token (IDENTIFIER);
-  rust_assert (union_keyword->get_str () == "union");
+  rust_assert (union_keyword->get_str () == Values::WeakKeywords::UNION);
   location_t locus = union_keyword->get_locus ();
 
   // parse actual union name
@@ -5715,7 +5716,7 @@ Parser::parse_trait_impl_item ()
   // semi
   return parse_macro_invocation_semi (std::move (outer_attrs));
 case IDENTIFIER:
-  if (lexer.peek_token ()->get_str () == "default")
+  if (lexer.peek_token ()->get_str () == Values::WeakKeywords::DEFAULT)
return parse_trait_impl_function_or_method (visibility,
std::move

[COMMITTED 054/101] gccrs: Add a regression test for async const functions

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Functions that are both async and const shall be rejected during the
AST validation pass. This new test highlight this behavior.

gcc/testsuite/ChangeLog:

* rust/compile/const_async_function.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/const_async_function.rs | 3 +++
 1 file changed, 3 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/const_async_function.rs

diff --git a/gcc/testsuite/rust/compile/const_async_function.rs 
b/gcc/testsuite/rust/compile/const_async_function.rs
new file mode 100644
index 000..fb1c4dd4c1d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_async_function.rs
@@ -0,0 +1,3 @@
+// { dg-additional-options "-frust-edition=2018" }
+const async fn weird_function() {}
+// { dg-error "functions cannot be both .const. and .async." "" { target *-*-* 
} .-1 }
-- 
2.42.1



[COMMITTED 025/101] gccrs: Add edition separation for keywords

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

It might be required in the future to get only the keywords from a
specific edition. To do so we need a mean to differentiate keywords based
on their edition. This commit changes the existing keyword macro to
allow such behavior.

gcc/rust/ChangeLog:

* lex/rust-token.h (enum PrimitiveCoreType): Change enum macro calls.
(RS_TOKEN_KEYWORD): Remove generic token keyword macro.
(RS_TOKEN_KEYWORD_2015): Introduce keywords for edition 2015.
(RS_TOKEN_KEYWORD_2018): Likewise with edition 2018.
* lex/rust-token.cc (RS_TOKEN_KEYWORD): Remove old macro definition.
(RS_TOKEN_KEYWORD_2015): Replace with 2015 definition...
(RS_TOKEN_KEYWORD_2018): ... and 2018 definition.
* util/rust-keyword-values.cc (RS_TOKEN_KEYWORD):  Likewise.
(RS_TOKEN_KEYWORD_2015): Likewise.
(RS_TOKEN_KEYWORD_2018): Likewise.
* util/rust-keyword-values.h (RS_TOKEN_KEYWORD): Likewise.
(RS_TOKEN_KEYWORD_2015): Likewise.
(RS_TOKEN_KEYWORD_2018): Likewise.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/lex/rust-token.cc   |  24 --
 gcc/rust/lex/rust-token.h| 114 ++-
 gcc/rust/util/rust-keyword-values.cc |   6 +-
 gcc/rust/util/rust-keyword-values.h  |   6 +-
 4 files changed, 82 insertions(+), 68 deletions(-)

diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc
index ea355051bba..7bb327358a2 100644
--- a/gcc/rust/lex/rust-token.cc
+++ b/gcc/rust/lex/rust-token.cc
@@ -31,9 +31,11 @@ get_token_description (TokenId id)
 #define RS_TOKEN(name, descr)  
\
   case name:   
\
 return descr;
-#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
   RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 default:
   rust_unreachable ();
@@ -50,9 +52,11 @@ token_id_to_str (TokenId id)
 #define RS_TOKEN(name, _)  
\
   case name:   
\
 return #name;
-#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2015(x, y) RS_TOKEN (x, y)
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
   RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 default:
   rust_unreachable ();
@@ -65,10 +69,12 @@ token_id_is_keyword (TokenId id)
 {
   switch (id)
 {
-#define RS_TOKEN_KEYWORD(name, _) case name:
+#define RS_TOKEN_KEYWORD_2015(name, _) case name:
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
 #define RS_TOKEN(a, b)
   RS_TOKEN_LIST return true;
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 default:
   return false;
@@ -81,15 +87,17 @@ token_id_keyword_string (TokenId id)
 {
   switch (id)
 {
-#define RS_TOKEN_KEYWORD(id, str_ptr)  
\
+#define RS_TOKEN_KEYWORD_2015(id, str_ptr) 
\
 case id: { 
\
   static const std::string str (str_ptr);  
\
   return str;  
\
 }  
\
 rust_unreachable ();
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
 #define RS_TOKEN(a, b)
   RS_TOKEN_LIST
-#undef RS_TOKEN_KEYWORD
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
 #undef RS_TOKEN
 default:
   rust_unreachable ();
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 50513acb68d..df321000511 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -59,8 +59,8 @@ enum PrimitiveCoreType
 };
 
 // RS_TOKEN(name, description)
-// RS_TOKEN_KEYWORD(name, identifier)
-//
+// RS_TOKEN_KEYWORD_{2015,2018}(name, identifier)
+
 // Keep RS_TOKEN_KEYWORD sorted
 
 /* note that abstract, async, become, box, do, final, macro, override, priv,
@@ -148,68 +148,70 @@ enum PrimitiveCoreType
   RS_TOKEN (INNER_DOC_COMMENT, "#![doc]")  
\
   RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]")   
\
   /* have "weak" union and 'static keywords? */
\
-  RS_TOKEN_KEYWORD (ABSTRACT, "abstract") /* unused */ 
\
-  RS_TOKEN_KEYWORD (AS, "as")  
\
-  RS_TOKEN_KEYWORD (ASYNC, "async") /* unused */   
\
-  RS_TOKEN_KEYWORD (AUTO, "auto")   

[COMMITTED 052/101] gccrs: Allow const and async specifiers in functions

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

We need to account for const specifiers in async parsing as const
can be used in the syntax before the async keyword.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_vis_item): Allow parsing async
items in const.
(Parser::parse_async_item): Account for const offset during async
lookahead.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/parse/rust-parse-impl.h | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index a1ad4f11993..acceec302a2 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1383,6 +1383,8 @@ Parser::parse_vis_item (AST::AttrVec 
outer_attrs)
  return parse_const_item (std::move (vis), std::move (outer_attrs));
case UNSAFE:
case EXTERN_KW:
+   case ASYNC:
+ return parse_async_item (std::move (vis), std::move (outer_attrs));
case FN_KW:
  return parse_function (std::move (vis), std::move (outer_attrs));
default:
@@ -1445,7 +1447,9 @@ std::unique_ptr
 Parser::parse_async_item (AST::Visibility vis,
  AST::AttrVec outer_attrs)
 {
-  const_TokenPtr t = lexer.peek_token ();
+  auto offset = (lexer.peek_token ()->get_id () == CONST) ? 1 : 0;
+  const_TokenPtr t = lexer.peek_token (offset);
+
   if (Session::get_instance ().options.get_edition ()
   == CompileOptions::Edition::E2015)
 {
@@ -1456,7 +1460,7 @@ Parser::parse_async_item 
(AST::Visibility vis,
 "to use %, switch to Rust 2018 or later"));
 }
 
-  t = lexer.peek_token (1);
+  t = lexer.peek_token (offset + 1);
 
   switch (t->get_id ())
 {
-- 
2.42.1



[COMMITTED 037/101] gccrs: late: Start setting up builtin types

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-late-name-resolver-2.0.cc
(Late::setup_builtin_types): New function.
(Late::go): Setup builtin types.
* resolve/rust-late-name-resolver-2.0.h:
* resolve/rust-name-resolution-context.cc
(NameResolutionContext::map_usage): New function.
* resolve/rust-name-resolution-context.h: Likewise.
---
 .../resolve/rust-late-name-resolver-2.0.cc| 42 +++
 .../resolve/rust-late-name-resolver-2.0.h |  2 +
 .../resolve/rust-name-resolution-context.cc   |  9 
 .../resolve/rust-name-resolution-context.h|  8 +++-
 4 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 352d59b0920..3236886f37d 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -16,18 +16,60 @@
 // along with GCC; see the file COPYING3.  If not see
 // .
 
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-late-name-resolver-2.0.h"
 #include "rust-default-resolver.h"
+#include "rust-tyty.h"
+#include "rust-hir-type-check.h"
 
 namespace Rust {
 namespace Resolver2_0 {
 
 Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
 
+void
+Late::setup_builtin_types ()
+{
+  auto next_id = [this] () { return ctx.mappings.get_next_hir_id (); };
+
+  static const std::pair builtins[] = {
+{"u8", new TyTy::UintType (next_id (), TyTy::UintType::U8)},
+{"u16", new TyTy::UintType (next_id (), TyTy::UintType::U16)},
+{"u32", new TyTy::UintType (next_id (), TyTy::UintType::U32)},
+{"u64", new TyTy::UintType (next_id (), TyTy::UintType::U64)},
+{"u128", new TyTy::UintType (next_id (), TyTy::UintType::U128)},
+{"i8", new TyTy::IntType (next_id (), TyTy::IntType::I8)},
+{"i16", new TyTy::IntType (next_id (), TyTy::IntType::I16)},
+{"i32", new TyTy::IntType (next_id (), TyTy::IntType::I32)},
+{"i64", new TyTy::IntType (next_id (), TyTy::IntType::I64)},
+{"i128", new TyTy::IntType (next_id (), TyTy::IntType::I128)},
+{"f32", new TyTy::FloatType (next_id (), TyTy::FloatType::F32)},
+{"f64", new TyTy::FloatType (next_id (), TyTy::FloatType::F64)},
+{"usize", new TyTy::USizeType (next_id ())},
+{"isize", new TyTy::ISizeType (next_id ())},
+// missing char, str, never, ()
+// does name resolution play a part for this? or is it all at typechecking?
+// yeah it seems to be name resolution as well, which makes sense
+  };
+
+  for (const auto &builtin : builtins)
+{
+  // we should be able to use `insert_at_root` or `insert` here, since 
we're
+  // at the root :) hopefully!
+  auto ok
+   = ctx.types.insert (builtin.first, builtin.second->get_ref ()
+   /* FIXME: Invalid! This returns an *HirId* */);
+
+  rust_assert (ok);
+}
+}
+
 void
 Late::go (AST::Crate &crate)
 {
+  setup_builtin_types ();
+
   for (auto &item : crate.items)
 item->accept_vis (*this);
 }
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 12540c0d220..f54bbf2eea4 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -47,6 +47,8 @@ public:
   void visit (AST::PathInExpression &) override;
 
 private:
+  /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
+  void setup_builtin_types ();
 };
 
 // TODO: Add missing mappings and data structures
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc 
b/gcc/rust/resolve/rust-name-resolution-context.cc
index 8bb7a9a15c1..f71ef91505b 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -43,6 +43,15 @@ NameResolutionContext::insert (Identifier name, NodeId id, 
Namespace ns)
 }
 }
 
+void
+NameResolutionContext::map_usage (NodeId usage, NodeId definition)
+{
+  auto inserted = resolved_nodes.emplace (usage, definition).second;
+
+  // is that valid?
+  rust_assert (inserted);
+}
+
 void
 NameResolutionContext::scoped (Rib rib, NodeId id,
   std::function lambda,
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index d63ee33378b..7a1924581ab 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -19,7 +19,6 @@
 #ifndef RUST_NAME_RESOLVER_2_0_H
 #define RUST_NAME_RESOLVER_2_0_H
 
-#include "optional.h"
 #include "rust-forever-stack.h"
 #include "rust-hir-map.h"
 
@@ -179,6 +178,13 @@ public:
   ForeverStack labels;
 
   Analysis::Mappings &mappings;
+
+  // TODO: Rename
+  void map_usage (NodeId usage, NodeId definition);
+
+private:
+  /* Map of "usage" nodes which have been resolved to a "definition" node */
+  

[COMMITTED 056/101] gccrs: Add regression test for const fn in trait

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Const fn declaration in trait declarations shall emit an error. This new
test highlight this behavior.

gcc/testsuite/ChangeLog:

* rust/compile/const_trait_fn.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/const_trait_fn.rs | 4 
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/const_trait_fn.rs

diff --git a/gcc/testsuite/rust/compile/const_trait_fn.rs 
b/gcc/testsuite/rust/compile/const_trait_fn.rs
new file mode 100644
index 000..cff2f5f096e
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_trait_fn.rs
@@ -0,0 +1,4 @@
+trait Osterkz {
+const fn x();
+// { dg-error "functions in traits cannot be declared const .E0379." "" { 
target *-*-* } .-1 }
+}
-- 
2.42.1



[COMMITTED 053/101] gccrs: Add async const function ast validation pass

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add a check during AST validation pass to ensure functions are either
const or async but not both.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
async const check.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 5 +
 1 file changed, 5 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 4b209908f9e..54276e8fd59 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -98,6 +98,11 @@ ASTValidation::visit (AST::Function &function)
   std::set valid_context
 = {Context::INHERENT_IMPL, Context::TRAIT_IMPL};
 
+  const auto &qualifiers = function.get_qualifiers ();
+  if (qualifiers.is_async () && qualifiers.is_const ())
+rust_error_at (function.get_locus (),
+  "functions cannot be both % and %");
+
   if (valid_context.find (context.back ()) == valid_context.end ()
   && function.has_self_param ())
 rust_error_at (
-- 
2.42.1



[COMMITTED 026/101] gccrs: Treat underscore as a keyword

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Make the underscore token a 2015 keyword.

gcc/rust/ChangeLog:

* lex/rust-token.h (enum PrimitiveCoreType): Change macro for
underscore in token list.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/lex/rust-token.h | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index df321000511..401452f515c 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -120,8 +120,6 @@ enum PrimitiveCoreType
   RS_TOKEN (SCOPE_RESOLUTION, "::") /* dodgy */
\
   RS_TOKEN (SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ 
\
   RS_TOKEN (DOUBLE_QUOTE, "\"")
\
-  RS_TOKEN (UNDERSCORE,
\
-   "_") /* TODO: treat as reserved word like mrustc instead? */   \
   RS_TOKEN (IDENTIFIER, "identifier")  
\
   RS_TOKEN (INT_LITERAL,   
\
"integer literal") /* do different int and float types need\
@@ -194,6 +192,7 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (TRY, "try") /* unused */  
\
   RS_TOKEN_KEYWORD_2015 (TYPE, "type") 
\
   RS_TOKEN_KEYWORD_2015 (TYPEOF, "typeof") /* unused */
\
+  RS_TOKEN_KEYWORD_2015 (UNDERSCORE, "_")  
\
   RS_TOKEN_KEYWORD_2015 (UNSAFE, "unsafe") 
\
   RS_TOKEN_KEYWORD_2015 (UNSIZED, "unsized") /* unused */  
\
   RS_TOKEN_KEYWORD_2015 (USE, "use")   
\
-- 
2.42.1



[COMMITTED 016/101] gccrs: Reject auto traits with generic parameters

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Generic parameters are not allowed on auto traits, the compiler should
emit an error.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
check for generics on auto traits.
* checks/errors/rust-ast-validation.h: Add visit function prototype.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 14 ++
 gcc/rust/checks/errors/rust-ast-validation.h  |  1 +
 2 files changed, 15 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index f6ce45eacca..37d3668a9e0 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -96,4 +96,18 @@ ASTValidation::visit (AST::Function &function)
   AST::ContextualASTVisitor::visit (function);
 }
 
+void
+ASTValidation::visit (AST::Trait &trait)
+{
+  if (trait.is_auto ())
+{
+  if (trait.has_generics ())
+   rust_error_at (trait.get_generic_params ()[0]->get_locus (),
+  ErrorCode::E0567,
+  "auto traits cannot have generic parameters");
+}
+
+  AST::ContextualASTVisitor::visit (trait);
+}
+
 } // namespace Rust
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h 
b/gcc/rust/checks/errors/rust-ast-validation.h
index 44995eb1fbc..49133ee0c3d 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -38,6 +38,7 @@ public:
   virtual void visit (AST::LoopLabel &label);
   virtual void visit (AST::ExternalFunctionItem &item);
   virtual void visit (AST::Function &function);
+  virtual void visit (AST::Trait &trait);
 };
 
 } // namespace Rust
-- 
2.42.1



[COMMITTED 040/101] gccrs: toplevel: Add comment about running the collector twice

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-toplevel-name-resolver-2.0.cc
(TopLevel::insert_or_error_out): Add documentation comment.
(TopLevel::go): Likewise.
---
 gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc | 8 
 1 file changed, 8 insertions(+)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index fbded3e49e1..b9d0bc7c0ac 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -43,6 +43,9 @@ TopLevel::insert_or_error_out (const Identifier &identifier, 
const T &node,
 
   if (!result)
 {
+  // can we do something like check if the node id is the same? if it is 
the
+  // same, it's not an error, just the resolver running multiple times?
+
   rich_location rich_loc (line_table, loc);
   rich_loc.add_range (node_locations[result.error ().existing]);
 
@@ -54,6 +57,11 @@ TopLevel::insert_or_error_out (const Identifier &identifier, 
const T &node,
 void
 TopLevel::go (AST::Crate &crate)
 {
+  // we do not include builtin types in the top-level definition collector, as
+  // they are not used until `Late`. furthermore, we run this visitor multiple
+  // times in a row in a fixed-point fashion, so it would make the code
+  // responsible for this ugly and perfom a lot of error checking.
+
   for (auto &item : crate.items)
 item->accept_vis (*this);
 }
-- 
2.42.1



[COMMITTED 061/101] gccrs: Add execution test for name resolution 2.0

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

We already have some compile tests but it lacked an execution test to
ensure everything compiles correctly to the correct value.

gcc/testsuite/ChangeLog:

* rust/execute/torture/name_resolution.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 .../rust/execute/torture/name_resolution.rs   | 24 +++
 1 file changed, 24 insertions(+)
 create mode 100644 gcc/testsuite/rust/execute/torture/name_resolution.rs

diff --git a/gcc/testsuite/rust/execute/torture/name_resolution.rs 
b/gcc/testsuite/rust/execute/torture/name_resolution.rs
new file mode 100644
index 000..749218352d6
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/name_resolution.rs
@@ -0,0 +1,24 @@
+// { dg-additional-options "-frust-name-resolution-2.0" }
+// { dg-output "Value is 10\r*\n" }
+
+const BAZ: i32 = 10;
+
+extern "C" {
+fn printf(s: *const i8, ...);
+}
+
+fn foo() {
+fn bar() {
+let e = BAZ;
+unsafe {
+printf("Value is %i\n" as *const str as *const i8, e);
+}
+}
+
+bar();
+}
+
+fn main() -> i32 {
+foo();
+0
+}
-- 
2.42.1



[COMMITTED 058/101] gccrs: Change the attribute checker visitor to default one

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Make the attribute checker visitor inherit from the default visitor
in order to keep visit behavior shared.

gcc/rust/ChangeLog:

* util/rust-attributes.cc (AttributeChecker::visit): Add visit function
for crates.
* util/rust-attributes.h (class AttributeChecker): Update function
prototypes.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/util/rust-attributes.cc |  23 ++-
 gcc/rust/util/rust-attributes.h  | 319 ---
 2 files changed, 171 insertions(+), 171 deletions(-)

diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 981bc738d6c..a1e23082e88 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // .
 
+#include "rust-ast-visitor.h"
 #include "rust-system.h"
 #include "rust-session-manager.h"
 #include "rust-attributes.h"
@@ -94,6 +95,12 @@ AttributeChecker::AttributeChecker () {}
 
 void
 AttributeChecker::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+AttributeChecker::visit (AST::Crate &crate)
 {
   check_attributes (crate.get_inner_attrs ());
 
@@ -468,8 +475,8 @@ AttributeChecker::visit (AST::BlockExpr &expr)
  check_proc_macro_non_root (item->get_outer_attrs (),
 item->get_locus ());
}
-  stmt->accept_vis (*this);
 }
+  AST::DefaultASTVisitor::visit (expr);
 }
 
 void
@@ -512,12 +519,6 @@ void
 AttributeChecker::visit (AST::ReturnExpr &)
 {}
 
-void
-AttributeChecker::visit (AST::UnsafeBlockExpr &expr)
-{
-  expr.get_block_expr ()->accept_vis (*this);
-}
-
 void
 AttributeChecker::visit (AST::LoopExpr &)
 {}
@@ -582,8 +583,8 @@ AttributeChecker::visit (AST::Module &module)
   for (auto &item : module.get_items ())
 {
   check_proc_macro_non_root (item->get_outer_attrs (), item->get_locus ());
-  item->accept_vis (*this);
 }
+  AST::DefaultASTVisitor::visit (module);
 }
 
 void
@@ -754,16 +755,14 @@ void
 AttributeChecker::visit (AST::InherentImpl &impl)
 {
   check_proc_macro_non_function (impl.get_outer_attrs ());
-  for (auto &item : impl.get_impl_items ())
-item->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 }
 
 void
 AttributeChecker::visit (AST::TraitImpl &impl)
 {
   check_proc_macro_non_function (impl.get_outer_attrs ());
-  for (auto &item : impl.get_impl_items ())
-item->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (impl);
 }
 
 void
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index 9db371e81c6..eecc4c0050b 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -77,7 +77,7 @@ private:
  * as checking the "arguments" or input given to these attributes, making sure
  * it is appropriate and valid.
  */
-class AttributeChecker : public AST::ASTVisitor
+class AttributeChecker : public AST::DefaultASTVisitor
 {
 public:
   AttributeChecker ();
@@ -88,6 +88,7 @@ public:
   void go (AST::Crate &crate);
 
 private:
+  using AST::DefaultASTVisitor::visit;
   /* Check the validity of a given attribute */
   void check_attribute (const AST::Attribute &attribute);
 
@@ -95,178 +96,178 @@ private:
   void check_attributes (const AST::AttrVec &attributes);
 
   // rust-ast.h
-  void visit (AST::Token &tok);
-  void visit (AST::DelimTokenTree &delim_tok_tree);
-  void visit (AST::AttrInputMetaItemContainer &input);
-  void visit (AST::IdentifierExpr &ident_expr);
-  void visit (AST::Lifetime &lifetime);
-  void visit (AST::LifetimeParam &lifetime_param);
-  void visit (AST::ConstGenericParam &const_param);
+  void visit (AST::Crate &crate) override;
+  void visit (AST::Token &tok) override;
+  void visit (AST::DelimTokenTree &delim_tok_tree) override;
+  void visit (AST::AttrInputMetaItemContainer &input) override;
+  void visit (AST::IdentifierExpr &ident_expr) override;
+  void visit (AST::Lifetime &lifetime) override;
+  void visit (AST::LifetimeParam &lifetime_param) override;
+  void visit (AST::ConstGenericParam &const_param) override;
 
   // rust-path.h
-  void visit (AST::PathInExpression &path);
-  void visit (AST::TypePathSegment &segment);
-  void visit (AST::TypePathSegmentGeneric &segment);
-  void visit (AST::TypePathSegmentFunction &segment);
-  void visit (AST::TypePath &path);
-  void visit (AST::QualifiedPathInExpression &path);
-  void visit (AST::QualifiedPathInType &path);
+  void visit (AST::PathInExpression &path) override;
+  void visit (AST::TypePathSegment &segment) override;
+  void visit (AST::TypePathSegmentGeneric &segment) override;
+  void visit (AST::TypePathSegmentFunction &segment) override;
+  void visit (AST::TypePath &path) override;
+  void visit (AST::QualifiedPathInExpression &path) override;
+  void visit (AST::QualifiedPathInType &path) override;
 
   // rust-expr.h
-  void visit (AST::LiteralExpr &expr);
-  void visit (

[COMMITTED 034/101] gccrs: nr2.0: Add base for late name resolution

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* Make-lang.in: Compile late name resolver.
* resolve/rust-late-name-resolver-2.0.cc: New file.
* resolve/rust-late-name-resolver-2.0.h: New file.
---
 gcc/rust/Make-lang.in |   1 +
 .../resolve/rust-late-name-resolver-2.0.cc| 105 ++
 .../resolve/rust-late-name-resolver-2.0.h |  57 ++
 3 files changed, 163 insertions(+)
 create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.cc
 create mode 100644 gcc/rust/resolve/rust-late-name-resolver-2.0.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index f2cadd55eed..47cc87750be 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -116,6 +116,7 @@ GRS_OBJS = \
 rust/rust-default-resolver.o \
 rust/rust-toplevel-name-resolver-2.0.o \
 rust/rust-early-name-resolver-2.0.o \
+rust/rust-late-name-resolver-2.0.o \
 rust/rust-early-name-resolver.o \
 rust/rust-name-resolver.o \
 rust/rust-ast-resolve.o \
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
new file mode 100644
index 000..352d59b0920
--- /dev/null
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -0,0 +1,105 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-ast-full.h"
+#include "rust-late-name-resolver-2.0.h"
+#include "rust-default-resolver.h"
+
+namespace Rust {
+namespace Resolver2_0 {
+
+Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
+
+void
+Late::go (AST::Crate &crate)
+{
+  for (auto &item : crate.items)
+item->accept_vis (*this);
+}
+
+void
+Late::new_label (Identifier name, NodeId id)
+{
+  // labels can always shadow, so `insert` should never fail. if it does, we're
+  // in big trouble!
+  auto ok = ctx.labels.insert (name, id);
+
+  rust_assert (ok);
+}
+
+void
+Late::visit (AST::LetStmt &let)
+{
+  // so we don't need that method
+  DefaultResolver::visit (let);
+
+  // how do we deal with the fact that `let a = blipbloup` should look for a
+  // label and cannot go through function ribs, but `let a = blipbloup()` can?
+
+  // how do we insert ribs here, and only pop them when we exit the current
+  // function?
+  // keep a list of ribs to pop when a scope exits? so only for blocks?
+  // how do we pop ribs that need to be popped not in order?
+  // I think it's not important if we have shadowing, correct?
+
+  // if we have shadowing, it should work! we'll see
+
+  // ctx.insert(Identifier name, NodeId id, Namespace ns)
+  // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
+  // Namespace::Labels,
+  //  let.get_node_id (), [] () {});
+}
+
+void
+Late::visit (AST::IdentifierPattern &identifier)
+{
+  // do we insert in labels or in values
+  // but values does not allow shadowing... since functions cannot shadow
+  // do we insert functions in labels as well?
+  new_label (identifier.get_ident (), identifier.get_node_id ());
+}
+
+void
+Late::visit (AST::IdentifierExpr &expr)
+{
+  // TODO: same thing as visit(PathInExpression) here?
+
+  auto label = ctx.labels.get (expr.get_ident ());
+  auto value = ctx.values.get (expr.get_ident ());
+
+  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
+  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+}
+
+void
+Late::visit (AST::PathInExpression &expr)
+{
+  // TODO: How do we have a nice error with `can't capture dynamic environment
+  // in a function item` error here?
+  // do we emit it in `get`?
+
+  auto label = ctx.labels.resolve_path (expr.get_segments ());
+
+  auto value = ctx.values.resolve_path (expr.get_segments ());
+
+  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
+  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+}
+
+} // namespace Resolver2_0
+} // namespace Rust
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
new file mode 100644
index 000..12540c0d220
--- /dev/null
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as

[COMMITTED 019/101] gccrs: Add a regression test for super trait on auto trait

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add a new regression test to highlight the error behavior with a super
trait on an auto trait.

gcc/testsuite/ChangeLog:

* rust/compile/auto_trait_super_trait.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/auto_trait_super_trait.rs | 4 
 1 file changed, 4 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/auto_trait_super_trait.rs

diff --git a/gcc/testsuite/rust/compile/auto_trait_super_trait.rs 
b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs
new file mode 100644
index 000..1080afb5124
--- /dev/null
+++ b/gcc/testsuite/rust/compile/auto_trait_super_trait.rs
@@ -0,0 +1,4 @@
+trait Cold {}
+
+auto trait IsCool: Cold {}
+// { dg-error "auto traits cannot have super traits .E0568." "" { target *-*-* 
} .-1 }
-- 
2.42.1



[COMMITTED 042/101] gccrs: early: Move `use` declaration resolving to TopLevel

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver-2.0.cc
(Early::visit): Remove visitors.
* resolve/rust-early-name-resolver-2.0.h: Likewise.
---
 gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 16 
 gcc/rust/resolve/rust-early-name-resolver-2.0.h  |  5 +
 2 files changed, 1 insertion(+), 20 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 48bb4c68d26..a5d5b191c88 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -188,22 +188,6 @@ Early::visit (AST::MacroInvocation &invoc)
   mappings->insert_macro_invocation (invoc, rules_def);
 }
 
-void
-Early::visit (AST::UseDeclaration &use)
-{}
-
-void
-Early::visit (AST::UseTreeRebind &use)
-{}
-
-void
-Early::visit (AST::UseTreeList &use)
-{}
-
-void
-Early::visit (AST::UseTreeGlob &use)
-{}
-
 void
 Early::visit_attributes (std::vector &attrs)
 {
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index 46c4b936866..d9f985fe575 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -50,10 +50,7 @@ public:
   void visit (AST::Module &) override;
 
   void visit (AST::MacroInvocation &) override;
-  void visit (AST::UseDeclaration &) override;
-  void visit (AST::UseTreeRebind &) override;
-  void visit (AST::UseTreeList &) override;
-  void visit (AST::UseTreeGlob &) override;
+
   void visit (AST::Function &) override;
   void visit (AST::StructStruct &) override;
 
-- 
2.42.1



[COMMITTED 065/101] gccrs: Generate error for const trait functions

2024-01-30 Thread arthur . cohen
From: Nobel Singh 

Fixes issue #2040

Add check to assure that a function cant be declared const inside trait impl
blocks.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
check for const funtion.

gcc/testsuite/ChangeLog:

* rust/compile/issue-2040.rs: New test.

Signed-off-by: Nobel Singh 
---
 gcc/rust/checks/errors/rust-ast-validation.cc |  4 
 gcc/testsuite/rust/compile/issue-2040.rs  | 12 
 2 files changed, 16 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2040.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 6fb142c7845..cd197fc1ea7 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -103,6 +103,10 @@ ASTValidation::visit (AST::Function &function)
 rust_error_at (function.get_locus (),
   "functions cannot be both % and %");
 
+  if (qualifiers.is_const () && context.back () == Context::TRAIT_IMPL)
+rust_error_at (function.get_locus (), ErrorCode::E0379,
+  "functions in traits cannot be declared const");
+
   if (valid_context.find (context.back ()) == valid_context.end ()
   && function.has_self_param ())
 rust_error_at (
diff --git a/gcc/testsuite/rust/compile/issue-2040.rs 
b/gcc/testsuite/rust/compile/issue-2040.rs
new file mode 100644
index 000..fbac168b9f3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2040.rs
@@ -0,0 +1,12 @@
+trait Foo {
+fn f() -> u32;
+}
+
+impl Foo for u32 {
+const fn f() -> u32 {
+// { dg-error "functions in traits cannot be declared const" "" { 
target *-*-* } .-1 }
+22
+}
+}
+
+fn main() {}
-- 
2.42.1



[COMMITTED 059/101] gccrs: Make early name resolver inherit from default one

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Many visit functions in the early name resolver are just plain old
traversal visit functions like the ones from the default visitor.

gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver.cc 
(EarlyNameResolver::resolve_generic_args):
Move function.
(EarlyNameResolver::resolve_qualified_path_type): Likewise.
(EarlyNameResolver::visit): Add a top level visit function for crate
and remove duplicated code.
* resolve/rust-early-name-resolver.h (class EarlyNameResolver): Update
overriden function list.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/resolve/rust-early-name-resolver.cc | 683 +--
 gcc/rust/resolve/rust-early-name-resolver.h  |  94 +--
 2 files changed, 28 insertions(+), 749 deletions(-)

diff --git a/gcc/rust/resolve/rust-early-name-resolver.cc 
b/gcc/rust/resolve/rust-early-name-resolver.cc
index 38a16408436..422dd92e462 100644
--- a/gcc/rust/resolve/rust-early-name-resolver.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver.cc
@@ -79,6 +79,31 @@ EarlyNameResolver::EarlyNameResolver ()
 
 void
 EarlyNameResolver::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
+{
+  for (auto &arg : generic_args.get_generic_args ())
+arg.accept_vis (*this);
+
+  for (auto &arg : generic_args.get_binding_args ())
+arg.get_type ()->accept_vis (*this);
+}
+
+void
+EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
+{
+  path.get_type ()->accept_vis (*this);
+
+  if (path.has_as_clause ())
+path.get_as_type_path ().accept_vis (*this);
+}
+
+void
+EarlyNameResolver::visit (AST::Crate &crate)
 {
   std::vector> new_items;
   auto items = crate.take_items ();
@@ -106,29 +131,6 @@ EarlyNameResolver::go (AST::Crate &crate)
   });
 }
 
-void
-EarlyNameResolver::resolve_generic_args (AST::GenericArgs &generic_args)
-{
-  for (auto &arg : generic_args.get_generic_args ())
-arg.accept_vis (*this);
-
-  for (auto &arg : generic_args.get_binding_args ())
-arg.get_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::resolve_qualified_path_type (AST::QualifiedPathType &path)
-{
-  path.get_type ()->accept_vis (*this);
-
-  if (path.has_as_clause ())
-path.get_as_type_path ().accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::Token &)
-{}
-
 void
 EarlyNameResolver::visit (AST::DelimTokenTree &)
 {}
@@ -141,10 +143,6 @@ void
 EarlyNameResolver::visit (AST::IdentifierExpr &)
 {}
 
-void
-EarlyNameResolver::visit (AST::Lifetime &)
-{}
-
 void
 EarlyNameResolver::visit (AST::LifetimeParam &)
 {}
@@ -163,10 +161,6 @@ EarlyNameResolver::visit (AST::PathInExpression &path)
   resolve_generic_args (segment.get_generic_args ());
 }
 
-void
-EarlyNameResolver::visit (AST::TypePathSegment &)
-{}
-
 void
 EarlyNameResolver::visit (AST::TypePathSegmentGeneric &segment)
 {
@@ -174,22 +168,6 @@ EarlyNameResolver::visit (AST::TypePathSegmentGeneric 
&segment)
 resolve_generic_args (segment.get_generic_args ());
 }
 
-void
-EarlyNameResolver::visit (AST::TypePathSegmentFunction &segment)
-{
-  for (auto &type : segment.get_type_path_function ().get_params ())
-type->accept_vis (*this);
-
-  segment.get_type_path_function ().get_return_type ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypePath &path)
-{
-  for (auto &seg : path.get_segments ())
-seg->accept_vis (*this);
-}
-
 void
 EarlyNameResolver::visit (AST::QualifiedPathInExpression &path)
 {
@@ -229,117 +207,6 @@ void
 EarlyNameResolver::visit (AST::MetaItemPathLit &)
 {}
 
-void
-EarlyNameResolver::visit (AST::BorrowExpr &expr)
-{
-  expr.get_borrowed_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::DereferenceExpr &expr)
-{
-  expr.get_dereferenced_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ErrorPropagationExpr &expr)
-{
-  expr.get_propagating_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::NegationExpr &expr)
-{
-  expr.get_negated_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ArithmeticOrLogicalExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::ComparisonExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::LazyBooleanExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::TypeCastExpr &expr)
-{
-  expr.get_casted_expr ()->accept_vis (*this);
-  expr.get_type_to_cast_to ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::AssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-EarlyNameResolver::visit (AST::CompoundAssig

[COMMITTED 038/101] gccrs: late: Start storing mappings properly in the resolver

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-late-name-resolver-2.0.cc (Late::visit): Store mappings
after having resolved them.
* resolve/rust-late-name-resolver-2.0.h: Add `TypePath` visitor.
---
 .../resolve/rust-late-name-resolver-2.0.cc| 33 ---
 .../resolve/rust-late-name-resolver-2.0.h |  1 +
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index 3236886f37d..5f70f575582 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -20,6 +20,7 @@
 #include "rust-ast-full.h"
 #include "rust-late-name-resolver-2.0.h"
 #include "rust-default-resolver.h"
+#include "rust-path.h"
 #include "rust-tyty.h"
 #include "rust-hir-type-check.h"
 
@@ -121,11 +122,24 @@ Late::visit (AST::IdentifierExpr &expr)
 {
   // TODO: same thing as visit(PathInExpression) here?
 
+  tl::optional resolved = tl::nullopt;
   auto label = ctx.labels.get (expr.get_ident ());
   auto value = ctx.values.get (expr.get_ident ());
 
-  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
-  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+  if (label)
+resolved = label;
+  else if (value)
+resolved = value;
+  // TODO: else emit error?
+
+  ctx.map_usage (expr.get_node_id (), *resolved);
+
+  // in the old resolver, resolutions are kept in the resolver, not the 
mappings
+  // :/ how do we deal with that?
+  // ctx.mappings.insert_resolved_name(expr, resolved);
+
+  // For empty types, do we perform a lookup in ctx.types or should the
+  // toplevel instead insert a name in ctx.values? (like it currently does)
 }
 
 void
@@ -136,11 +150,20 @@ Late::visit (AST::PathInExpression &expr)
   // do we emit it in `get`?
 
   auto label = ctx.labels.resolve_path (expr.get_segments ());
-
   auto value = ctx.values.resolve_path (expr.get_segments ());
+}
+
+void
+Late::visit (AST::TypePath &type)
+{
+  // should we add type path resolution in `ForeverStack` directly? Since it's
+  // quite more complicated.
+  // maybe we can overload `resolve_path` to only do
+  // typepath-like path resolution? that sounds good
+
+  auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ());
 
-  rust_debug ("[ARTHUR] label: %d", label ? *label : -1);
-  rust_debug ("[ARTHUR] value: %d", value ? *value : -1);
+  ctx.map_usage (type.get_node_id (), *resolved);
 }
 
 } // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index f54bbf2eea4..15940d053ae 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -45,6 +45,7 @@ public:
   // resolutions
   void visit (AST::IdentifierExpr &) override;
   void visit (AST::PathInExpression &) override;
+  void visit (AST::TypePath &) override;
 
 private:
   /* Setup Rust's builtin types (u8, i32, !...) in the resolver */
-- 
2.42.1



[COMMITTED 023/101] gccrs: Add ast validation check on union variant number

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Unions with zero fields are forbidden. Add regression test for empty
unions.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
zero field check during ast validation pass.
* checks/errors/rust-ast-validation.h: Add union visit function
prototype.

gcc/testsuite/ChangeLog:

* rust/compile/const_generics_8.rs: Fill the union with dummy values.
* rust/compile/empty_union.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc  | 10 ++
 gcc/rust/checks/errors/rust-ast-validation.h   |  2 ++
 gcc/testsuite/rust/compile/const_generics_8.rs |  7 ++-
 gcc/testsuite/rust/compile/empty_union.rs  |  2 ++
 4 files changed, 20 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/empty_union.rs

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 4142cc6317e..dad7f5edded 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -18,6 +18,7 @@
 
 #include "rust-ast-validation.h"
 #include "rust-diagnostics.h"
+#include "rust-item.h"
 #include "rust-keyword-values.h"
 
 namespace Rust {
@@ -81,6 +82,15 @@ ASTValidation::visit (AST::ExternalFunctionItem &item)
   AST::ContextualASTVisitor::visit (item);
 }
 
+void
+ASTValidation::visit (AST::Union &item)
+{
+  if (item.get_variants ().empty ())
+rust_error_at (item.get_locus (), "unions cannot have zero fields");
+
+  AST::ContextualASTVisitor::visit (item);
+}
+
 void
 ASTValidation::visit (AST::Function &function)
 {
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h 
b/gcc/rust/checks/errors/rust-ast-validation.h
index 49133ee0c3d..1052168ea72 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -21,6 +21,7 @@
 
 #include "rust-ast-visitor.h"
 #include "rust-ast-full.h"
+#include "rust-item.h"
 
 namespace Rust {
 
@@ -37,6 +38,7 @@ public:
   virtual void visit (AST::Lifetime &lifetime);
   virtual void visit (AST::LoopLabel &label);
   virtual void visit (AST::ExternalFunctionItem &item);
+  virtual void visit (AST::Union &item);
   virtual void visit (AST::Function &function);
   virtual void visit (AST::Trait &trait);
 };
diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs 
b/gcc/testsuite/rust/compile/const_generics_8.rs
index c7810830f46..bb34652b9a6 100644
--- a/gcc/testsuite/rust/compile/const_generics_8.rs
+++ b/gcc/testsuite/rust/compile/const_generics_8.rs
@@ -8,7 +8,12 @@ enum Bidoule {}
 type Bipboupe = Bidule;
 trait Fooable {}
 
-union Bidoulepe {} // { dg-error "default values for const 
generic parameters are not allowed in .union. items" }
+union Bidoulepe {
+// { dg-error "default values for const generic parameters are not allowed 
in .union. items"  "" {target *-*-* } .-1 }
+int: i32,
+float: f32,
+}
+
 fn const_default() {} // { dg-error "default values for 
const generic parameters are not allowed in .function. items" }
 
 // Note - missing generic parameter - needs name resolution on const generics
diff --git a/gcc/testsuite/rust/compile/empty_union.rs 
b/gcc/testsuite/rust/compile/empty_union.rs
new file mode 100644
index 000..6114df5d9c0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/empty_union.rs
@@ -0,0 +1,2 @@
+#[repr(C)]
+union MyUnion {} // { dg-error "unions cannot have zero fields" }
-- 
2.42.1



[COMMITTED 045/101] gccrs: Add unsafety member to modules

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The rust syntax allows unsafe module even if those are rejected at a
later stage.

gcc/rust/ChangeLog:

* ast/rust-item.h: Add safety status to Modules in the AST.
* parse/rust-parse-impl.h (Parser::parse_module): Adapt constructors.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-item.h | 13 -
 gcc/rust/parse/rust-parse-impl.h |  8 +---
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 3480d126bc0..6c3715e1eeb 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -736,6 +736,7 @@ private:
   Identifier module_name;
   location_t locus;
   ModuleKind kind;
+  Unsafety safety;
 
   // Name of the file including the module
   std::string outer_filename;
@@ -766,11 +767,12 @@ public:
 
   // Unloaded module constructor
   Module (Identifier module_name, Visibility visibility,
- std::vector outer_attrs, location_t locus,
+ std::vector outer_attrs, location_t locus, Unsafety safety,
  std::string outer_filename, std::vector module_scope)
 : VisItem (std::move (visibility), std::move (outer_attrs)),
   module_name (module_name), locus (locus), kind (ModuleKind::UNLOADED),
-  outer_filename (outer_filename), inner_attrs (std::vector ()),
+  safety (safety), outer_filename (outer_filename),
+  inner_attrs (std::vector ()),
   items (std::vector> ()),
   module_scope (std::move (module_scope))
   {}
@@ -779,18 +781,19 @@ public:
   Module (Identifier name, location_t locus,
  std::vector> items,
  Visibility visibility = Visibility::create_error (),
+ Unsafety safety = Unsafety::Normal,
  std::vector inner_attrs = std::vector (),
  std::vector outer_attrs = std::vector ())
 : VisItem (std::move (visibility), std::move (outer_attrs)),
   module_name (name), locus (locus), kind (ModuleKind::LOADED),
-  outer_filename (std::string ()), inner_attrs (std::move (inner_attrs)),
-  items (std::move (items))
+  safety (safety), outer_filename (std::string ()),
+  inner_attrs (std::move (inner_attrs)), items (std::move (items))
   {}
 
   // Copy constructor with vector clone
   Module (Module const &other)
 : VisItem (other), module_name (other.module_name), locus (other.locus),
-  kind (other.kind), inner_attrs (other.inner_attrs),
+  kind (other.kind), safety (other.safety), inner_attrs 
(other.inner_attrs),
   module_scope (other.module_scope)
   {
 // We need to check whether we are copying a loaded module or an unloaded
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 53b3839db37..2e24a66123b 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -22,6 +22,7 @@
 /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
  * This is also the reason why there are no include guards. */
 
+#include "rust-common.h"
 #include "rust-item.h"
 #include "rust-token.h"
 #define INCLUDE_ALGORITHM
@@ -2446,8 +2447,8 @@ Parser::parse_module (AST::Visibility 
vis,
   // Construct an external module
   return std::unique_ptr (
new AST::Module (std::move (name), std::move (vis),
-std::move (outer_attrs), locus, lexer.get_filename (),
-inline_module_stack));
+std::move (outer_attrs), locus, Unsafety::Normal,
+lexer.get_filename (), inline_module_stack));
   case LEFT_CURLY: {
lexer.skip_token ();
 
@@ -2503,7 +2504,8 @@ Parser::parse_module (AST::Visibility 
vis,
 
return std::unique_ptr (
  new AST::Module (std::move (name), locus, std::move (items),
-  std::move (vis), std::move (inner_attrs),
+  std::move (vis), Unsafety::Normal,
+  std::move (inner_attrs),
   std::move (outer_attrs))); // module name?
   }
 default:
-- 
2.42.1



[COMMITTED 066/101] gccrs: Renamed `WIN64` to `WIN_64`

2024-01-30 Thread arthur . cohen
From: Kushal Pal 

Fixes issue #2768

gcc/rust/ChangeLog:

* backend/rust-compile-base.cc (HIRCompileBase::setup_abi_options):
Renamed `WIN64` to `WIN_64`
* util/rust-abi.cc (get_abi_from_string): Likewise
(get_string_from_abi): Likewise
* util/rust-abi.h (enum ABI): Likewise

Signed-off-by: Kushal Pal 
---
 gcc/rust/backend/rust-compile-base.cc | 2 +-
 gcc/rust/util/rust-abi.cc | 4 ++--
 gcc/rust/util/rust-abi.h  | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/backend/rust-compile-base.cc 
b/gcc/rust/backend/rust-compile-base.cc
index fcab75bef1c..984492f6607 100644
--- a/gcc/rust/backend/rust-compile-base.cc
+++ b/gcc/rust/backend/rust-compile-base.cc
@@ -463,7 +463,7 @@ HIRCompileBase::setup_abi_options (tree fndecl, ABI abi)
 
   break;
 
-case Rust::ABI::WIN64:
+case Rust::ABI::WIN_64:
   abi_tree = get_identifier ("ms_abi");
 
   break;
diff --git a/gcc/rust/util/rust-abi.cc b/gcc/rust/util/rust-abi.cc
index 05739e16660..d17402e163e 100644
--- a/gcc/rust/util/rust-abi.cc
+++ b/gcc/rust/util/rust-abi.cc
@@ -40,7 +40,7 @@ get_abi_from_string (const std::string &abi)
   else if (abi.compare ("sysv64") == 0)
 return Rust::ABI::SYSV64;
   else if (abi.compare ("win64") == 0)
-return Rust::ABI::WIN64;
+return Rust::ABI::WIN_64;
 
   return Rust::ABI::UNKNOWN;
 }
@@ -64,7 +64,7 @@ get_string_from_abi (Rust::ABI abi)
   return "fastcall";
 case Rust::ABI::SYSV64:
   return "sysv64";
-case Rust::ABI::WIN64:
+case Rust::ABI::WIN_64:
   return "win64";
 
 case Rust::ABI::UNKNOWN:
diff --git a/gcc/rust/util/rust-abi.h b/gcc/rust/util/rust-abi.h
index d794cc35fb3..a0180ed4d95 100644
--- a/gcc/rust/util/rust-abi.h
+++ b/gcc/rust/util/rust-abi.h
@@ -30,7 +30,7 @@ enum ABI
   CDECL,
   STDCALL,
   FASTCALL,
-  WIN64,
+  WIN_64,
   SYSV64
 };
 
-- 
2.42.1



[COMMITTED 067/101] gccrs: Allow enabling lang_items and no_core features

2024-01-30 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* checks/errors/rust-feature.cc
(Feature::name_hash_map):
Add entries for Name::LANG_ITEMS and Name::NO_CORE.
* checks/errors/rust-feature.h
(Feature::Name::LANG_ITEMS): New.
(Feature::Name::NO_CORE): New.

gcc/testsuite/ChangeLog:

* rust/compile/sized-stub.rs: New test.

Signed-off-by: Owen Avery 
---
 gcc/rust/checks/errors/rust-feature.cc   | 2 ++
 gcc/rust/checks/errors/rust-feature.h| 2 ++
 gcc/testsuite/rust/compile/sized-stub.rs | 6 ++
 3 files changed, 10 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/sized-stub.rs

diff --git a/gcc/rust/checks/errors/rust-feature.cc 
b/gcc/rust/checks/errors/rust-feature.cc
index 88649f14e60..c12710ae2e1 100644
--- a/gcc/rust/checks/errors/rust-feature.cc
+++ b/gcc/rust/checks/errors/rust-feature.cc
@@ -56,6 +56,8 @@ const std::map 
Feature::name_hash_map = {
   // later Rust versions
   {"optin_builtin_traits", Feature::Name::AUTO_TRAITS},
   {"extern_types", Feature::Name::EXTERN_TYPES},
+  {"lang_items", Feature::Name::LANG_ITEMS},
+  {"no_core", Feature::Name::NO_CORE},
 }; // namespace Rust
 
 tl::optional
diff --git a/gcc/rust/checks/errors/rust-feature.h 
b/gcc/rust/checks/errors/rust-feature.h
index 4ff059c6167..e6bc2362e39 100644
--- a/gcc/rust/checks/errors/rust-feature.h
+++ b/gcc/rust/checks/errors/rust-feature.h
@@ -43,6 +43,8 @@ public:
 DECL_MACRO,
 AUTO_TRAITS,
 EXTERN_TYPES,
+LANG_ITEMS,
+NO_CORE,
   };
 
   const std::string &as_string () { return m_name_str; }
diff --git a/gcc/testsuite/rust/compile/sized-stub.rs 
b/gcc/testsuite/rust/compile/sized-stub.rs
new file mode 100644
index 000..4e89b1fb134
--- /dev/null
+++ b/gcc/testsuite/rust/compile/sized-stub.rs
@@ -0,0 +1,6 @@
+#![feature(lang_items)]
+#![feature(no_core)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
-- 
2.42.1



[COMMITTED 039/101] gccrs: early: Resolve paths properly

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-early-name-resolver-2.0.cc
(Early::insert_once): New function.
(Early::visit): Likewise.
* resolve/rust-early-name-resolver-2.0.h: Likewise.
---
 .../resolve/rust-early-name-resolver-2.0.cc   | 30 +++
 .../resolve/rust-early-name-resolver-2.0.h| 10 +++
 2 files changed, 40 insertions(+)

diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index 2245ba31772..48bb4c68d26 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -26,6 +26,33 @@ namespace Resolver2_0 {
 
 Early::Early (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
 
+void
+Early::insert_once (AST::MacroInvocation &invocation, NodeId resolved)
+{
+  // TODO: Should we use `ctx.mark_resolved()`?
+  AST::MacroRulesDefinition *definition;
+  auto ok = ctx.mappings.lookup_macro_def (resolved, &definition);
+
+  rust_assert (ok);
+
+  AST::MacroRulesDefinition *existing;
+  auto exists = ctx.mappings.lookup_macro_invocation (invocation, &existing);
+
+  if (!exists)
+ctx.mappings.insert_macro_invocation (invocation, definition);
+}
+
+void
+Early::insert_once (AST::MacroRulesDefinition &def)
+{
+  // TODO: Should we use `ctx.mark_resolved()`?
+  AST::MacroRulesDefinition *definition;
+  auto exists = ctx.mappings.lookup_macro_def (def.get_node_id (), 
&definition);
+
+  if (!exists)
+ctx.mappings.insert_macro_def (&def);
+}
+
 void
 Early::go (AST::Crate &crate)
 {
@@ -89,6 +116,7 @@ Early::visit (AST::MacroRulesDefinition &def)
   DefaultResolver::visit (def);
 
   textual_scope.insert (def.get_rule_name ().as_string (), def.get_node_id ());
+  insert_once (def);
 }
 
 void
@@ -141,6 +169,8 @@ Early::visit (AST::MacroInvocation &invoc)
   return;
 }
 
+  insert_once (invoc, *definition);
+
   // now do we need to keep mappings or something? or insert "uses" into our
   // ForeverStack? can we do that? are mappings simpler?
   auto mappings = Analysis::Mappings::get ();
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
index dc273196473..46c4b936866 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.h
@@ -60,6 +60,16 @@ public:
 private:
   void visit_attributes (std::vector &attrs);
 
+  /**
+   * Insert a resolved macro invocation into the mappings once, meaning that we
+   * can call this function each time the early name resolution pass is 
underway
+   * and it will not trigger assertions for already resolved invocations.
+   */
+  // TODO: Rename
+  void insert_once (AST::MacroInvocation &invocation, NodeId resolved);
+  // TODO: Rename
+  void insert_once (AST::MacroRulesDefinition &definition);
+
   /**
* Macros can either be resolved through textual scoping or regular path
* scoping - which this class represents. Textual scoping works similarly to 
a
-- 
2.42.1



[COMMITTED 027/101] gccrs: Add await keyword

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The 2018 edition await keyword was missing from the keyword list.

gcc/rust/ChangeLog:

* lex/rust-token.h (enum PrimitiveCoreType): Add await keyword
definition.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/lex/rust-token.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index 401452f515c..e38c3cf9943 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -150,6 +150,7 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (AS, "as") 
\
   RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */  
\
   RS_TOKEN_KEYWORD_2015 (AUTO, "auto") 
\
+  RS_TOKEN_KEYWORD_2018 (AWAIT, "await")   
\
   RS_TOKEN_KEYWORD_2015 (BECOME, "become") /* unused */
\
   RS_TOKEN_KEYWORD_2015 (BOX, "box")  /* unused */\
   RS_TOKEN_KEYWORD_2015 (BREAK, "break")   
\
-- 
2.42.1



[COMMITTED 046/101] gccrs: Parse module safety

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Unsafe module are rejected at a later stage but could not be parsed
properly. This commit changes the parser in order to allow unsafe module
in the AST.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_vis_item): Dispatch to parse
module when meeting an unsafe module.
(Parser::parse_module): Set unsafe status when the parser encounter an
unsafe keyword.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/parse/rust-parse-impl.h | 14 +++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 2e24a66123b..8087e0c2b94 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1418,6 +1418,8 @@ Parser::parse_vis_item (AST::AttrVec 
outer_attrs)
  return parse_function (std::move (vis), std::move (outer_attrs));
case IMPL:
  return parse_impl (std::move (vis), std::move (outer_attrs));
+   case MOD:
+ return parse_module (std::move (vis), std::move (outer_attrs));
default:
  add_error (
Error (t->get_locus (),
@@ -2427,6 +2429,13 @@ std::unique_ptr
 Parser::parse_module (AST::Visibility vis,
  AST::AttrVec outer_attrs)
 {
+  Unsafety safety = Unsafety::Normal;
+  if (lexer.peek_token ()->get_id () == UNSAFE)
+{
+  safety = Unsafety::Unsafe;
+  skip_token (UNSAFE);
+}
+
   location_t locus = lexer.peek_token ()->get_locus ();
   skip_token (MOD);
 
@@ -2447,7 +2456,7 @@ Parser::parse_module (AST::Visibility 
vis,
   // Construct an external module
   return std::unique_ptr (
new AST::Module (std::move (name), std::move (vis),
-std::move (outer_attrs), locus, Unsafety::Normal,
+std::move (outer_attrs), locus, safety,
 lexer.get_filename (), inline_module_stack));
   case LEFT_CURLY: {
lexer.skip_token ();
@@ -2504,8 +2513,7 @@ Parser::parse_module (AST::Visibility 
vis,
 
return std::unique_ptr (
  new AST::Module (std::move (name), locus, std::move (items),
-  std::move (vis), Unsafety::Normal,
-  std::move (inner_attrs),
+  std::move (vis), safety, std::move (inner_attrs),
   std::move (outer_attrs))); // module name?
   }
 default:
-- 
2.42.1



[COMMITTED 062/101] gccrs: Make function bodies truly optional

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Missing body on a function should be rejected at a later stage in the
compiler, not during parsing.

gcc/rust/ChangeLog:

* ast/rust-ast-collector.cc (TokenCollector::visit): Adapt defintion
getter.
* ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
* expand/rust-cfg-strip.cc (CfgStrip::visit): Likewise.
* expand/rust-expand-visitor.cc (ExpandVisitor::visit): Likewise.
* hir/rust-ast-lower-implitem.h: Likewise.
* hir/rust-ast-lower-item.cc (ASTLoweringItem::visit): Likewise.
* resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise.
* resolve/rust-ast-resolve-stmt.h: Likewise.
* resolve/rust-default-resolver.cc (DefaultResolver::visit): Likewise.
* util/rust-attributes.cc (AttributeChecker::visit):  Likewise.
* parse/rust-parse-impl.h: Allow empty function body during parsing.
* ast/rust-ast.cc (Function::Function): Constructor now take an
optional for the body.
(Function::operator=): Adapt to new optional member.
(Function::as_string): Likewise.
* ast/rust-item.h (class Function): Make body optional and do not
rely on nullptr anymore.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-ast-collector.cc|   7 +-
 gcc/rust/ast/rust-ast-visitor.cc  |   3 +-
 gcc/rust/ast/rust-ast.cc  |  24 +++--
 gcc/rust/ast/rust-item.h  |  13 +--
 gcc/rust/expand/rust-cfg-strip.cc |  16 ++--
 gcc/rust/expand/rust-expand-visitor.cc|   8 +-
 gcc/rust/hir/rust-ast-lower-implitem.h|   2 +-
 gcc/rust/hir/rust-ast-lower-item.cc   |   2 +-
 gcc/rust/parse/rust-parse-impl.h  | 105 ++
 gcc/rust/resolve/rust-ast-resolve-item.cc |   2 +-
 gcc/rust/resolve/rust-ast-resolve-stmt.h  |   2 +-
 gcc/rust/resolve/rust-default-resolver.cc |   3 +-
 gcc/rust/util/rust-attributes.cc  |   3 +-
 13 files changed, 92 insertions(+), 98 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 647724bec11..d5a98f1ccc7 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -1730,11 +1730,10 @@ TokenCollector::visit (Function &function)
   if (function.has_where_clause ())
 visit (function.get_where_clause ());
 
-  auto &block = function.get_definition ();
-  if (!block)
-push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
+  if (function.has_body ())
+visit (*function.get_definition ());
   else
-visit (block);
+push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION));
   newline ();
 }
 
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 4ec5c7cf1d0..230a152b05b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -777,7 +777,8 @@ DefaultASTVisitor::visit (AST::Function &function)
   if (function.has_return_type ())
 visit (function.get_return_type ());
   visit (function.get_where_clause ());
-  visit (function.get_definition ());
+  if (function.has_body ())
+visit (*function.get_definition ());
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 607f07955d4..b9096032d41 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -18,6 +18,7 @@ along with GCC; see the file COPYING3.  If not see
 .  */
 
 #include "rust-ast.h"
+#include "optional.h"
 #include "rust-system.h"
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
@@ -1100,8 +1101,10 @@ Function::Function (Function const &other)
 return_type = other.return_type->clone_type ();
 
   // guard to prevent null dereference (only required if error state)
-  if (other.function_body != nullptr)
-function_body = other.function_body->clone_block_expr ();
+  if (other.has_body ())
+function_body = other.function_body.value ()->clone_block_expr ();
+  else
+function_body = tl::nullopt;
 
   generic_params.reserve (other.generic_params.size ());
   for (const auto &e : other.generic_params)
@@ -1131,10 +1134,10 @@ Function::operator= (Function const &other)
 return_type = nullptr;
 
   // guard to prevent null dereference (only required if error state)
-  if (other.function_body != nullptr)
-function_body = other.function_body->clone_block_expr ();
+  if (other.has_body ())
+function_body = other.function_body.value ()->clone_block_expr ();
   else
-function_body = nullptr;
+function_body = tl::nullopt;
 
   generic_params.reserve (other.generic_params.size ());
   for (const auto &e : other.generic_params)
@@ -1221,15 +1224,8 @@ Function::as_string () const
 
   str += "\n";
 
-  // DEBUG: null pointer check
-  if (function_body == nullptr)
-{
-  rust_debug (
-   "something really terrible has gone wrong - null pointer function "
-   "body in function.");
-  return "NULL_POINTER_MARK

[COMMITTED 082/101] gccrs: ast: Fix lifetime type parsing

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

There was a mismatch whether lifetime 'static is parsed as "static"
or "'static".

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::lifetime_from_token): Fix matched 
pattern.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/parse/rust-parse-impl.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 378b9ada5ed..90bc2e214e4 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4158,11 +4158,11 @@ Parser::lifetime_from_token 
(const_TokenPtr tok)
   location_t locus = tok->get_locus ();
   std::string lifetime_ident = tok->get_str ();
 
-  if (lifetime_ident == "'static")
+  if (lifetime_ident == "static")
 {
   return AST::Lifetime (AST::Lifetime::STATIC, "", locus);
 }
-  else if (lifetime_ident == "'_")
+  else if (lifetime_ident == "_")
 {
   return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus);
 }
-- 
2.42.1



[COMMITTED 041/101] gccrs: ast: Add NodeId to UseTree base class

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* ast/rust-item.h (class UseTree): Add `node_id` member.
---
 gcc/rust/ast/rust-item.h | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 2c0e45962ce..3480d126bc0 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -940,6 +940,7 @@ protected:
 class UseTree
 {
   location_t locus;
+  NodeId node_id;
 
 public:
   enum Kind
@@ -975,6 +976,7 @@ public:
   virtual Kind get_kind () const = 0;
 
   location_t get_locus () const { return locus; }
+  NodeId get_node_id () const { return node_id; }
 
   virtual void accept_vis (ASTVisitor &vis) = 0;
 
@@ -982,7 +984,9 @@ protected:
   // Clone function implementation as pure virtual method
   virtual UseTree *clone_use_tree_impl () const = 0;
 
-  UseTree (location_t locus) : locus (locus) {}
+  UseTree (location_t locus)
+: locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
+  {}
 };
 
 // Use tree with a glob (wildcard) operator
@@ -1182,7 +1186,7 @@ public:
 
   Kind get_kind () const override { return Rebind; }
 
-  SimplePath get_path () const
+  const SimplePath &get_path () const
   {
 rust_assert (has_path ());
 return path;
-- 
2.42.1



[COMMITTED 029/101] gccrs: Add a list of weak keyword

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Retrieving a weak keyword value is done using raw values. Introducing a
list of weak keywords means this could change.

gcc/rust/ChangeLog:

* util/rust-keyword-values.h (class WeakKeywords): Add new class with
weak keyword constexpr.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/util/rust-keyword-values.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/gcc/rust/util/rust-keyword-values.h 
b/gcc/rust/util/rust-keyword-values.h
index 769b2100c41..4a6f1df525d 100644
--- a/gcc/rust/util/rust-keyword-values.h
+++ b/gcc/rust/util/rust-keyword-values.h
@@ -41,6 +41,20 @@ public:
 #undef RS_TOKEN
 };
 
+class WeakKeywords
+{
+public:
+  static constexpr auto &AUTO = "auto";
+  static constexpr auto &BUILTIN = "builtin";
+  static constexpr auto &CATCH = "catch";
+  static constexpr auto &DEFAULT = "default";
+  static constexpr auto &GEN = "gen";
+  static constexpr auto &MACRO_RULES = "macro_rules";
+  static constexpr auto &RAW = "raw";
+  static constexpr auto &UNION = "union";
+  static constexpr auto &YEET = "yeet";
+};
+
 } // namespace Values
 } // namespace Rust
 
-- 
2.42.1



[COMMITTED 050/101] gccrs: Remove class AST::InherentImplItem

2024-01-30 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* ast/rust-ast-full-decls.h
(class InherentImplItem): Remove.
* ast/rust-ast.h
(class InherentImplItem): Remove.
(class SingleASTNode):
Store pointer to AssociatedItem instead of InherentImplItem.

* ast/rust-ast.cc
(SingleASTNode::SingleASTNode):
Use clone_associated_item instead of clone_inherent_impl_item.
(SingleASTNode::operator=): Likewise.

* ast/rust-item.h
(class InherentImpl):
Use AssociatedItem rather than InherentImplItem.
(class Function): Likewise.
(class ConstantItem): Likewise.
* ast/rust-macro.h
(class MacroInvocation): Likewise.
* expand/rust-expand-visitor.cc
(ExpandVisitor::visit): Likewise.
* parse/rust-parse-impl.h
(Parser::parse_impl): Likewise.
(Parser::parse_inherent_impl_item): Likewise.
(Parser::parse_inherent_impl_function_or_method): Likewise.
* parse/rust-parse.h
(Parser::parse_inherent_impl_item): Likewise.
(Parser::parse_inherent_impl_function_or_method): Likewise.

Signed-off-by: Owen Avery 
---
 gcc/rust/ast/rust-ast-full-decls.h |  1 -
 gcc/rust/ast/rust-ast.cc   |  4 ++--
 gcc/rust/ast/rust-ast.h| 22 +++---
 gcc/rust/ast/rust-item.h   | 18 ++
 gcc/rust/ast/rust-macro.h  |  2 +-
 gcc/rust/expand/rust-expand-visitor.cc |  2 +-
 gcc/rust/parse/rust-parse-impl.h   |  8 
 gcc/rust/parse/rust-parse.h|  4 ++--
 8 files changed, 23 insertions(+), 38 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index e2d05bae0c4..5bfaaa8ba3c 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -52,7 +52,6 @@ class GenericParam;
 class LifetimeParam;
 class ConstGenericParam;
 class TraitItem;
-class InherentImplItem;
 class TraitImplItem;
 struct Crate;
 class PathExpr;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 43820d38e28..17f82d67430 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -64,7 +64,7 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
   break;
 
 case IMPL:
-  impl_item = other.impl_item->clone_inherent_impl_item ();
+  impl_item = other.impl_item->clone_associated_item ();
   break;
 
 case TRAIT_IMPL:
@@ -104,7 +104,7 @@ SingleASTNode::operator= (SingleASTNode const &other)
   break;
 
 case IMPL:
-  impl_item = other.impl_item->clone_inherent_impl_item ();
+  impl_item = other.impl_item->clone_associated_item ();
   break;
 
 case TRAIT_IMPL:
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4049e4d2607..b193c67c69e 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1687,22 +1687,6 @@ public:
   location_t get_locus () const override { return locus; }
 };
 
-/* Abstract base class for items used within an inherent impl block (the impl
- * name {} one) */
-class InherentImplItem : virtual public AssociatedItem
-{
-protected:
-  // Clone function implementation as pure virtual method
-  virtual InherentImplItem *clone_associated_item_impl () const override = 0;
-
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr clone_inherent_impl_item () const
-  {
-return std::unique_ptr (clone_associated_item_impl ());
-  }
-};
-
 // Abstract base class for items used in a trait impl
 class TraitImplItem : virtual public AssociatedItem
 {
@@ -1860,7 +1844,7 @@ private:
   std::unique_ptr stmt;
   std::unique_ptr external_item;
   std::unique_ptr trait_item;
-  std::unique_ptr impl_item;
+  std::unique_ptr impl_item;
   std::unique_ptr trait_impl_item;
   std::unique_ptr type;
 
@@ -1885,7 +1869,7 @@ public:
 : kind (TRAIT), trait_item (std::move (item))
   {}
 
-  SingleASTNode (std::unique_ptr item)
+  SingleASTNode (std::unique_ptr item)
 : kind (IMPL), impl_item (std::move (item))
   {}
 
@@ -1959,7 +1943,7 @@ public:
 return std::move (external_item);
   }
 
-  std::unique_ptr take_impl_item ()
+  std::unique_ptr take_impl_item ()
   {
 rust_assert (!is_error ());
 return std::move (impl_item);
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 3bf023b3c5a..b34aca0d56c 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1285,7 +1285,9 @@ protected:
 class LetStmt;
 
 // Rust function declaration AST node
-class Function : public VisItem, public InherentImplItem, public TraitImplItem
+class Function : public VisItem,
+virtual public AssociatedItem,
+public TraitImplItem
 {
   FunctionQualifiers qualifiers;
   Identifier function_name;
@@ -2308,7 +2310,7 @@ protected:
 /* "Constant item" AST node - used for constant, compile-time expressions
  * within module scope (like constexpr) */
 c

[COMMITTED 069/101] gccrs: Make expand visitor inherit from default visitor

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Many visit functions in the expand visitor simply visit their components
like the default visitor. Making the expand visitor inherit from the
default visitor allows us to keep all visitor in sync without having to
change every visitor.

gcc/rust/ChangeLog:

* expand/rust-expand-visitor.cc (ExpandVisitor::go): Add call to visit
on the crate.
(ExpandVisitor::visit): Remove some visit functions in favor of their
default visitor counterpart.
* expand/rust-expand-visitor.h (class ExpandVisitor): Inherit from
default visitor and remove now useless function prototypes.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/expand/rust-expand-visitor.cc | 492 +
 gcc/rust/expand/rust-expand-visitor.h  |  82 +
 2 files changed, 9 insertions(+), 565 deletions(-)

diff --git a/gcc/rust/expand/rust-expand-visitor.cc 
b/gcc/rust/expand/rust-expand-visitor.cc
index ad473c2dcb0..a60c4728926 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -39,7 +39,7 @@ is_builtin (AST::Attribute &attr)
 void
 ExpandVisitor::go (AST::Crate &crate)
 {
-  expand_inner_items (crate.items);
+  visit (crate);
 }
 
 static std::unique_ptr
@@ -474,8 +474,10 @@ ExpandVisitor::expand_trait_method_decl 
(AST::TraitMethodDecl &decl)
 }
 
 void
-ExpandVisitor::visit (AST::Token &)
-{}
+ExpandVisitor::visit (AST::Crate &crate)
+{
+  expand_inner_items (crate.items);
+}
 
 void
 ExpandVisitor::visit (AST::DelimTokenTree &)
@@ -489,10 +491,6 @@ void
 ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
 {}
 
-void
-ExpandVisitor::visit (AST::Lifetime &)
-{}
-
 void
 ExpandVisitor::visit (AST::LifetimeParam &)
 {}
@@ -516,10 +514,6 @@ ExpandVisitor::visit (AST::PathInExpression &path)
   expand_generic_args (segment.get_generic_args ());
 }
 
-void
-ExpandVisitor::visit (AST::TypePathSegment &)
-{}
-
 void
 ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
 {}
@@ -536,13 +530,6 @@ ExpandVisitor::visit (AST::TypePathSegmentFunction 
&segment)
 maybe_expand_type (type_path_function.get_return_type ());
 }
 
-void
-ExpandVisitor::visit (AST::TypePath &path)
-{
-  for (auto &segment : path.get_segments ())
-visit (segment);
-}
-
 void
 ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
 {
@@ -585,30 +572,12 @@ void
 ExpandVisitor::visit (AST::MetaItemPathLit &)
 {}
 
-void
-ExpandVisitor::visit (AST::BorrowExpr &expr)
-{
-  visit (expr.get_borrowed_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::DereferenceExpr &expr)
-{
-  visit (expr.get_dereferenced_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
 {
   visit (expr.get_propagating_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::NegationExpr &expr)
-{
-  visit (expr.get_negated_expr ());
-}
-
 void
 ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
 {
@@ -630,14 +599,6 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
   maybe_expand_expr (expr.get_right_expr ());
 }
 
-void
-ExpandVisitor::visit (AST::TypeCastExpr &expr)
-{
-  visit (expr.get_casted_expr ());
-
-  visit (expr.get_type_to_cast_to ());
-}
-
 void
 ExpandVisitor::visit (AST::AssignmentExpr &expr)
 {
@@ -658,84 +619,10 @@ ExpandVisitor::visit (AST::GroupedExpr &expr)
   maybe_expand_expr (expr.get_expr_in_parens ());
 }
 
-void
-ExpandVisitor::visit (AST::ArrayElemsValues &elems)
-{
-  for (auto &elem : elems.get_values ())
-visit (elem);
-}
-
-void
-ExpandVisitor::visit (AST::ArrayElemsCopied &elems)
-{
-  visit (elems.get_elem_to_copy ());
-  visit (elems.get_num_copies ());
-}
-
-void
-ExpandVisitor::visit (AST::ArrayExpr &expr)
-{
-  visit (expr.get_array_elems ());
-}
-
-void
-ExpandVisitor::visit (AST::ArrayIndexExpr &expr)
-{
-  visit (expr.get_array_expr ());
-  visit (expr.get_index_expr ());
-}
-
-void
-ExpandVisitor::visit (AST::TupleExpr &expr)
-{
-  for (auto &element : expr.get_tuple_elems ())
-visit (element);
-}
-
-void
-ExpandVisitor::visit (AST::TupleIndexExpr &expr)
-{
-  visit (expr.get_tuple_expr ());
-
-  // We can't have macro invocations for tuple indexes, right? Need a test!
-}
-
 void
 ExpandVisitor::visit (AST::StructExprStruct &expr)
 {}
 
-void
-ExpandVisitor::visit (AST::StructExprFieldIdentifier &)
-{}
-
-void
-ExpandVisitor::visit (AST::StructExprFieldIdentifierValue &field)
-{
-  visit (field.get_value ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprFieldIndexValue &field)
-{
-  visit (field.get_value ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprStructFields &expr)
-{
-  for (auto &field : expr.get_fields ())
-visit (field);
-
-  if (expr.has_struct_base ())
-visit (expr.get_struct_base ().get_base_struct ());
-}
-
-void
-ExpandVisitor::visit (AST::StructExprStructBase &expr)
-{
-  visit (expr.get_struct_base ().get_base_struct ());
-}
-
 void
 ExpandVisitor::visit (AST::CallExpr &expr)
 {
@@ -754,12 +641,6 @@ ExpandVisitor::visit (AST::MethodCallExpr &ex

[COMMITTED 084/101] gccrs: ast: Full lifetime elision handling

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_generic_param): Lifetime 
elision control.
(Parser::parse_lifetime_where_clause_item): Lifetime elision control.
(Parser::parse_type_param_bound): Lifetime elision control.
(Parser::parse_lifetime_bounds): Lifetime elision control.
(Parser::parse_lifetime): Lifetime elision control.
(Parser::parse_path_generic_args): Lifetime elision control.
(Parser::parse_self_param): Lifetime elision control.
(Parser::parse_break_expr): Lifetime elision control.
(Parser::parse_continue_expr): Lifetime elision control.
(Parser::parse_reference_type_inner): Lifetime elision control.
* parse/rust-parse.h: Lifetime elision control.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/parse/rust-parse-impl.h | 25 +
 gcc/rust/parse/rust-parse.h  |  2 +-
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 0e2cfce1e19..dfa2762c5c3 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3099,7 +3099,7 @@ Parser::parse_generic_param 
(EndTokenPred is_end_token)
   switch (token->get_id ())
 {
   case LIFETIME: {
-   auto lifetime = parse_lifetime ();
+   auto lifetime = parse_lifetime (false);
if (lifetime.is_error ())
  {
rust_error_at (
@@ -3808,7 +3808,7 @@ template 
 std::unique_ptr
 Parser::parse_lifetime_where_clause_item ()
 {
-  AST::Lifetime lifetime = parse_lifetime ();
+  AST::Lifetime lifetime = parse_lifetime (false);
   if (lifetime.is_error ())
 {
   // TODO: error here?
@@ -4001,7 +4001,7 @@ Parser::parse_type_param_bound ()
 {
 case LIFETIME:
   return std::unique_ptr (
-   new AST::Lifetime (parse_lifetime ()));
+   new AST::Lifetime (parse_lifetime (false)));
 case LEFT_PAREN:
 case QUESTION_MARK:
 case FOR:
@@ -4075,7 +4075,7 @@ Parser::parse_lifetime_bounds ()
 
   while (true)
 {
-  AST::Lifetime lifetime = parse_lifetime ();
+  AST::Lifetime lifetime = parse_lifetime (false);
 
   // quick exit for parsing failure
   if (lifetime.is_error ())
@@ -4105,7 +4105,7 @@ Parser::parse_lifetime_bounds 
(EndTokenPred is_end_token)
 
   while (!is_end_token (lexer.peek_token ()->get_id ()))
 {
-  AST::Lifetime lifetime = parse_lifetime ();
+  AST::Lifetime lifetime = parse_lifetime (false);
 
   if (lifetime.is_error ())
{
@@ -4136,12 +4136,13 @@ Parser::parse_lifetime_bounds 
(EndTokenPred is_end_token)
  * existing. */
 template 
 AST::Lifetime
-Parser::parse_lifetime ()
+Parser::parse_lifetime (bool allow_elided)
 {
   const_TokenPtr lifetime_tok = lexer.peek_token ();
   if (lifetime_tok->get_id () != LIFETIME)
 {
-  return AST::Lifetime::elided ();
+  return (allow_elided) ? AST::Lifetime::elided ()
+   : AST::Lifetime::error ();
 }
   lexer.skip_token ();
 
@@ -6606,7 +6607,7 @@ Parser::parse_path_generic_args ()
   location_t locus = t->get_locus ();
   while (!is_right_angle_tok (t->get_id ()))
 {
-  AST::Lifetime lifetime = parse_lifetime ();
+  AST::Lifetime lifetime = parse_lifetime (false);
   if (lifetime.is_error ())
{
  // not necessarily an error
@@ -7227,7 +7228,7 @@ Parser::parse_self_param ()
   // now test whether it has a lifetime
   if (lexer.peek_token ()->get_id () == LIFETIME)
{
- lifetime = parse_lifetime ();
+ lifetime = parse_lifetime (true);
 
  // something went wrong somehow
  if (lifetime.is_error ())
@@ -7763,7 +7764,7 @@ Parser::parse_break_expr 
(AST::AttrVec outer_attrs,
   AST::Lifetime label = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
 {
-  label = parse_lifetime ();
+  label = parse_lifetime (false);
 }
 
   // parse break return expression if it exists
@@ -7794,7 +7795,7 @@ Parser::parse_continue_expr 
(AST::AttrVec outer_attrs,
   AST::Lifetime label = AST::Lifetime::error ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
 {
-  label = parse_lifetime ();
+  label = parse_lifetime (false);
 }
 
   return std::unique_ptr (
@@ -9838,7 +9839,7 @@ Parser::parse_reference_type_inner 
(location_t locus)
   AST::Lifetime lifetime = AST::Lifetime::elided ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
 {
-  lifetime = parse_lifetime ();
+  lifetime = parse_lifetime (true);
   if (lifetime.is_error ())
{
  Error error (lexer.peek_token ()->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 4291e4198a5..3fc86206de7 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -303,7 +303,7 @@ private:
   std::vector parse_lifetime_bounds ();
   template 
   std::vector parse_lif

[COMMITTED 044/101] gccrs: Create base class for TupleStructItems and TuplePatternItems

2024-01-30 Thread arthur . cohen
From: Owen Avery 

gcc/rust/ChangeLog:

* hir/tree/rust-hir-pattern.h
(class TupleItems): New.
(class TupleStructItems): Inherit from TupleItems.
(class TuplePatternItems): Likewise.

Signed-off-by: Owen Avery 
---
 gcc/rust/hir/tree/rust-hir-pattern.h | 47 ++--
 1 file changed, 23 insertions(+), 24 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h 
b/gcc/rust/hir/tree/rust-hir-pattern.h
index 33025bfdb6b..e65a62f20a8 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -777,8 +777,8 @@ protected:
   }
 };
 
-// Base abstract class for patterns used in TupleStructPattern
-class TupleStructItems : public FullVisitable
+// Base abstract class for TupleStructItems and TuplePatternItems
+class TupleItems : public FullVisitable
 {
 public:
   enum ItemType
@@ -787,25 +787,38 @@ public:
 RANGED,
   };
 
-  virtual ~TupleStructItems () {}
+  virtual ~TupleItems () {}
 
   // TODO: should this store location data?
 
   // Unique pointer custom clone function
-  std::unique_ptr clone_tuple_struct_items () const
+  std::unique_ptr clone_tuple_items () const
   {
-return std::unique_ptr (clone_tuple_items_impl ());
+return std::unique_ptr (clone_tuple_items_impl ());
   }
 
+  virtual ItemType get_item_type () const = 0;
+
   virtual std::string as_string () const = 0;
 
-  virtual void accept_vis (HIRFullVisitor &vis) = 0;
+protected:
+  // pure virtual clone implementation
+  virtual TupleItems *clone_tuple_items_impl () const = 0;
+};
 
-  virtual ItemType get_item_type () const = 0;
+// Base abstract class for patterns used in TupleStructPattern
+class TupleStructItems : public TupleItems
+{
+public:
+  // Unique pointer custom clone function
+  std::unique_ptr clone_tuple_struct_items () const
+  {
+return std::unique_ptr (clone_tuple_items_impl ());
+  }
 
 protected:
   // pure virtual clone implementation
-  virtual TupleStructItems *clone_tuple_items_impl () const = 0;
+  virtual TupleStructItems *clone_tuple_items_impl () const override = 0;
 };
 
 // Class for non-ranged tuple struct pattern patterns
@@ -1011,32 +1024,18 @@ protected:
 };
 
 // Base abstract class representing TuplePattern patterns
-class TuplePatternItems : public FullVisitable
+class TuplePatternItems : public TupleItems
 {
 public:
-  enum ItemType
-  {
-MULTIPLE,
-RANGED,
-  };
-
-  virtual ~TuplePatternItems () {}
-
-  // TODO: should this store location data?
-
   // Unique pointer custom clone function
   std::unique_ptr clone_tuple_pattern_items () const
   {
 return std::unique_ptr (clone_tuple_items_impl ());
   }
 
-  virtual std::string as_string () const = 0;
-
-  virtual ItemType get_item_type () const = 0;
-
 protected:
   // pure virtual clone implementation
-  virtual TuplePatternItems *clone_tuple_items_impl () const = 0;
+  virtual TuplePatternItems *clone_tuple_items_impl () const override = 0;
 };
 
 // Class representing TuplePattern patterns where there are multiple patterns
-- 
2.42.1



[COMMITTED 031/101] gccrs: Introduce a proper keyword list

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The old "keyword" list was used for the lexer, and could therefore not
be used with keyword spanning over multiple tokens as those tokens should
remain lexed as is. Hence the introduction of a new list macro for
keyword exclusive tasks. This also means we can no longer match a token
id for each keyword. The token id map has been renamed to keep it's
properties.

gcc/rust/ChangeLog:

* lex/rust-lex.cc (Lexer::classify_keyword): Update keyword map name.
* lex/rust-token.h (enum PrimitiveCoreType): Remove some deprecated
comments.
* util/rust-keyword-values.cc (get_keywords): Update the keyword map
name.
(RS_TOKEN): Define as empty
(RS_TOKEN_KEYWORD_2015): Add the emission value.
(RS_TOKEN_KEYWORD_2018): Likewise.
* util/rust-keyword-values.h (RS_KEYWORD_LIST): Introduce the keyword
list.
(RS_TOKEN_KEYWORD_2018): Define multiple new keywords.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/lex/rust-lex.cc |  2 +-
 gcc/rust/lex/rust-token.h|  2 --
 gcc/rust/util/rust-keyword-values.cc | 13 -
 gcc/rust/util/rust-keyword-values.h  | 13 +++--
 4 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 2d41c114f73..5bff2d9125c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -260,7 +260,7 @@ Lexer::replace_current_token (TokenPtr replacement)
 TokenId
 Lexer::classify_keyword (const std::string &str)
 {
-  auto &keywords = Rust::Values::Keywords::keywords;
+  auto &keywords = Rust::Values::Keywords::keywords_tokens;
   auto keyword = keywords.find (str);
 
   if (keyword == keywords.end ())
diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h
index e38c3cf9943..438b29b4957 100644
--- a/gcc/rust/lex/rust-token.h
+++ b/gcc/rust/lex/rust-token.h
@@ -145,7 +145,6 @@ enum PrimitiveCoreType
   /* Doc Comments */   
\
   RS_TOKEN (INNER_DOC_COMMENT, "#![doc]")  
\
   RS_TOKEN (OUTER_DOC_COMMENT, "#[doc]")   
\
-  /* have "weak" union and 'static keywords? */
\
   RS_TOKEN_KEYWORD_2015 (ABSTRACT, "abstract") /* unused */
\
   RS_TOKEN_KEYWORD_2015 (AS, "as") 
\
   RS_TOKEN_KEYWORD_2018 (ASYNC, "async") /* unused */  
\
@@ -157,7 +156,6 @@ enum PrimitiveCoreType
   RS_TOKEN_KEYWORD_2015 (CONST, "const")   
\
   RS_TOKEN_KEYWORD_2015 (CONTINUE, "continue") 
\
   RS_TOKEN_KEYWORD_2015 (CRATE, "crate")   
\
-  /* FIXME: Do we need to add $crate (DOLLAR_CRATE) as a reserved kw? */   
\
   RS_TOKEN_KEYWORD_2015 (DO, "do") /* unused */
\
   RS_TOKEN_KEYWORD_2018 (DYN, "dyn")   
\
   RS_TOKEN_KEYWORD_2015 (ELSE, "else") 
\
diff --git a/gcc/rust/util/rust-keyword-values.cc 
b/gcc/rust/util/rust-keyword-values.cc
index 8aa5ef1371a..9e1d2bcdef6 100644
--- a/gcc/rust/util/rust-keyword-values.cc
+++ b/gcc/rust/util/rust-keyword-values.cc
@@ -38,7 +38,18 @@ get_keywords ()
   return m;
 }
 
-const std::map Keywords::keywords = get_keywords ();
+const std::map Keywords::keywords_tokens
+  = get_keywords ();
+
+const std::set Keywords::keywords = {
+#define RS_TOKEN(x, y)
+#define RS_TOKEN_KEYWORD_2015(tok, key) {key},
+#define RS_TOKEN_KEYWORD_2018 RS_TOKEN_KEYWORD_2015
+  RS_KEYWORD_LIST
+#undef RS_TOKEN_KEYWORD_2015
+#undef RS_TOKEN_KEYWORD_2018
+#undef RS_TOKEN
+};
 
 } // namespace Values
 } // namespace Rust
diff --git a/gcc/rust/util/rust-keyword-values.h 
b/gcc/rust/util/rust-keyword-values.h
index 4a6f1df525d..01c98a2cde4 100644
--- a/gcc/rust/util/rust-keyword-values.h
+++ b/gcc/rust/util/rust-keyword-values.h
@@ -21,6 +21,14 @@
 
 #include "rust-token.h"
 
+// Append keywords made from multiple tokens to the existing token-keyword list
+#define RS_KEYWORD_LIST
\
+  RS_TOKEN_LIST
\
+  RS_TOKEN_KEYWORD_2015 (DOLLAR_CRATE, "$crate")   
\
+  RS_TOKEN_KEYWORD_2015 (PATH_ROOT, "{{root}}")
\
+  RS_TOKEN_KEYWORD_2015 (STATIC_LIFETIME, "'static")   
\
+  RS_TOKEN_KEYWORD_2015 (UNDERSCORE_LIFETIME, "'_")
+
 namespace Rust {
 namespace Values {
 
@@ -28,14 +36,15 @@ namespace Values {
 class Keywords
 {
 public:
-  const static std::map keywords;
+  const static std::map keywords_tokens;
 
+  const static std::set keywords;
   // Rust keyword values
 public:
 #define RS_TOKEN(x, y)
 #define RS_TOKEN_KEYWORD_2015(tok,

[COMMITTED 060/101] gccrs: Add multiple regression test in name resolution

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Local variables and functions or global variables have different
resolution when binded to a variable. This was not covered before, even
though it was handled by the new name resolution. This commit highlight
this behavior from the new name resolution mechanism.

gcc/testsuite/ChangeLog:

* rust/compile/name_resolution11.rs: New test.
* rust/compile/name_resolution12.rs: New test.
* rust/compile/name_resolution13.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/name_resolution11.rs |  7 +++
 gcc/testsuite/rust/compile/name_resolution12.rs | 10 ++
 gcc/testsuite/rust/compile/name_resolution13.rs |  9 +
 3 files changed, 26 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/name_resolution11.rs
 create mode 100644 gcc/testsuite/rust/compile/name_resolution12.rs
 create mode 100644 gcc/testsuite/rust/compile/name_resolution13.rs

diff --git a/gcc/testsuite/rust/compile/name_resolution11.rs 
b/gcc/testsuite/rust/compile/name_resolution11.rs
new file mode 100644
index 000..a464d2a0fd3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution11.rs
@@ -0,0 +1,7 @@
+// { dg-additional-options "-frust-name-resolution-2.0 
-frust-compile-until=lowering" }
+fn foo() {
+let b = 10;
+fn bar() {
+let a = foo;
+}
+}
diff --git a/gcc/testsuite/rust/compile/name_resolution12.rs 
b/gcc/testsuite/rust/compile/name_resolution12.rs
new file mode 100644
index 000..9cce31ceb5c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution12.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-frust-name-resolution-2.0 
-frust-compile-until=lowering" }
+
+const TOTO: i32 = 10;
+
+fn foo() {
+let b = 10;
+fn bar() {
+let e = TOTO;
+}
+}
diff --git a/gcc/testsuite/rust/compile/name_resolution13.rs 
b/gcc/testsuite/rust/compile/name_resolution13.rs
new file mode 100644
index 000..52a152bf51a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/name_resolution13.rs
@@ -0,0 +1,9 @@
+// { dg-additional-options "-frust-name-resolution-2.0 
-frust-compile-until=lowering" }
+
+fn foo() {
+let b = 10;
+fn bar() {
+let c = b;
+// { dg-error "cannot find value .b. in this scope .E0425." "" { 
target *-*-* } .-1 }
+}
+}
-- 
2.42.1



[COMMITTED 073/101] gccrs: TyTy: Fix missed nodiscard

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

gcc/rust/ChangeLog:

* typecheck/rust-tyty.h: Fix nodiscard to warn unused.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/typecheck/rust-tyty.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 8bfa83da8d8..da4b901724d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -177,7 +177,7 @@ public:
   virtual BaseType *clone () const = 0;
 
   // Check if TyTy::BaseType is of a specific type.
-  template [[nodiscard]] bool is () const
+  template  WARN_UNUSED_RESULT bool is () const
   {
 static_assert (std::is_base_of::value,
   "Can only safely cast to TyTy types.");
-- 
2.42.1



[COMMITTED 091/101] gccrs: Handle `async` keyword for regular implementations

2024-01-30 Thread arthur . cohen
From: Kushal Pal 

Fixes #2788

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_inherent_impl_item):
Added switch-case for ASYNC token.

gcc/testsuite/ChangeLog:

* rust/compile/issue-2788.rs: New test.

Signed-off-by: Kushal Pal 
---
 gcc/rust/parse/rust-parse-impl.h |  1 +
 gcc/testsuite/rust/compile/issue-2788.rs | 10 ++
 2 files changed, 11 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2788.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 3055a3959cf..c14c75ce70d 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5600,6 +5600,7 @@ Parser::parse_inherent_impl_item ()
return nullptr;
  }
   }
+case ASYNC:
 case EXTERN_KW:
 case UNSAFE:
 case FN_KW:
diff --git a/gcc/testsuite/rust/compile/issue-2788.rs 
b/gcc/testsuite/rust/compile/issue-2788.rs
new file mode 100644
index 000..b3828fca6cb
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2788.rs
@@ -0,0 +1,10 @@
+// { dg-additional-options "-frust-compile-until=lowering" }
+struct Foo {
+arg_1: u32,
+arg_2: i32,
+}
+
+impl Foo {
+async fn asynchronous_function_1(&self) {}
+async fn asynchronous_function_2() {}
+}
-- 
2.42.1



[COMMITTED 043/101] gccrs: toplevel: Resolve `use` declarations

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-toplevel-name-resolver-2.0.cc
(TopLevel::insert_or_error_out): New functions.
(TopLevel::handle_use_dec): New function.
(flatten_rebind): Likewise.
(flatten_list): Likewise.
(flatten_glob): Likewise.
(flatten): Likewise.
(TopLevel::visit): Visit various `use` declaration nodes.
* resolve/rust-toplevel-name-resolver-2.0.h: Declare functions and
visitors.
---
 .../rust-toplevel-name-resolver-2.0.cc| 187 +-
 .../resolve/rust-toplevel-name-resolver-2.0.h |  11 ++
 2 files changed, 194 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
index b9d0bc7c0ac..46113a8a46b 100644
--- a/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-toplevel-name-resolver-2.0.cc
@@ -17,6 +17,7 @@
 // .
 
 #include "rust-toplevel-name-resolver-2.0.h"
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-hir-map.h"
 #include "rust-attribute-values.h"
@@ -33,11 +34,16 @@ void
 TopLevel::insert_or_error_out (const Identifier &identifier, const T &node,
   Namespace ns)
 {
-  auto loc = node.get_locus ();
-  auto node_id = node.get_node_id ();
+  insert_or_error_out (identifier, node.get_locus (), node.get_node_id (), ns);
+}
 
+void
+TopLevel::insert_or_error_out (const Identifier &identifier,
+  const location_t &locus, const NodeId &node_id,
+  Namespace ns)
+{
   // keep track of each node's location to provide useful errors
-  node_locations.emplace (node_id, loc);
+  node_locations.emplace (node_id, locus);
 
   auto result = ctx.insert (identifier, node_id, ns);
 
@@ -46,7 +52,7 @@ TopLevel::insert_or_error_out (const Identifier &identifier, 
const T &node,
   // can we do something like check if the node id is the same? if it is 
the
   // same, it's not an error, just the resolver running multiple times?
 
-  rich_location rich_loc (line_table, loc);
+  rich_location rich_loc (line_table, locus);
   rich_loc.add_range (node_locations[result.error ().existing]);
 
   rust_error_at (rich_loc, ErrorCode::E0428, "%qs defined multiple times",
@@ -308,5 +314,178 @@ TopLevel::visit (AST::ConstantItem &const_item)
   ctx.scoped (Rib::Kind::ConstantItem, const_item.get_node_id (), expr_vis);
 }
 
+bool
+TopLevel::handle_use_dec (AST::SimplePath path)
+{
+  // TODO: Glob imports can get shadowed by regular imports and regular items.
+  // So we need to store them in a specific way in the ForeverStack - which can
+  // also probably be used by labels and macros etc. Like store it as a
+  // `Shadowable(NodeId)` instead of just a `NodeId`
+
+  auto locus = path.get_final_segment ().get_locus ();
+  auto declared_name = path.get_final_segment ().as_string ();
+
+  // in what namespace do we perform path resolution? All of them? see which 
one
+  // matches? Error out on ambiguities?
+  // so, apparently, for each one that matches, add it to the proper namespace
+  // :(
+
+  auto found = false;
+
+  auto resolve_and_insert = [this, &found, &declared_name,
+locus] (Namespace ns,
+const AST::SimplePath &path) {
+tl::optional resolved = tl::nullopt;
+
+// FIXME: resolve_path needs to return an `expected` so
+// that we can improve it with hints or location or w/ever. and maybe
+// only emit it the first time.
+switch (ns)
+  {
+  case Namespace::Values:
+   resolved = ctx.values.resolve_path (path.get_segments ());
+   break;
+  case Namespace::Types:
+   resolved = ctx.types.resolve_path (path.get_segments ());
+   break;
+  case Namespace::Macros:
+   resolved = ctx.macros.resolve_path (path.get_segments ());
+   break;
+  case Namespace::Labels:
+   // TODO: Is that okay?
+   rust_unreachable ();
+  }
+
+// FIXME: Ugly
+(void) resolved.map ([this, &found, &declared_name, locus, ns] (NodeId id) 
{
+  found = true;
+
+  // what do we do with the id?
+  insert_or_error_out (declared_name, locus, id, ns);
+
+  return id;
+});
+  };
+
+  // do this for all namespaces (even Labels?)
+
+  resolve_and_insert (Namespace::Values, path);
+  resolve_and_insert (Namespace::Types, path);
+  resolve_and_insert (Namespace::Macros, path);
+
+  // TODO: No labels? No, right?
+
+  return found;
+}
+
+static void
+flatten_rebind (const AST::UseTreeRebind &glob,
+   std::vector &paths);
+static void
+flatten_list (const AST::UseTreeList &glob,
+ std::vector &paths);
+static void
+flatten_glob (const AST::UseTreeGlob &glob,
+ std::vector &paths);
+
+static void
+flatten (const AST::UseTree *tree, std::vector &paths)
+{
+  switch 

[COMMITTED 028/101] gccrs: Replace some keyword raw values

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Raw values cannot be understood easily by most tools. This commit replace
some raw values with their variable counterpart.

gcc/rust/ChangeLog:

* ast/rust-ast-collector.cc (TokenCollector::visit): Replace raw value
with keyword call.
* ast/rust-ast.h: Likewise.
* parse/rust-parse-impl.h (Parser::parse_path_ident_segment): Likewise.
(Parser::parse_macro_match_fragment): Likewise.
(Parser::parse_extern_crate): Likewise.
(Parser::parse_use_tree): Likewise.
(Parser::parse_const_item): Likewise.
(Parser::parse_literal_expr): Likewise.
(Parser::parse_maybe_named_param): Likewise.
(Parser::parse_pattern_no_alt): Likewise.
(Parser::left_denotation): Likewise.
(Parser::parse_path_in_expression_pratt): Likewise.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/ast/rust-ast-collector.cc | 13 
 gcc/rust/ast/rust-ast.h| 24 ++
 gcc/rust/parse/rust-parse-impl.h   | 52 +-
 3 files changed, 53 insertions(+), 36 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 8f394e595ed..5b12875c349 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -17,6 +17,7 @@
 // .
 #include "rust-ast-collector.h"
 #include "rust-item.h"
+#include "rust-keyword-values.h"
 
 namespace Rust {
 namespace AST {
@@ -461,11 +462,11 @@ TokenCollector::visit (Lifetime &lifetime)
   break;
 case Lifetime::LifetimeType::STATIC:
   push (Rust::Token::make_lifetime (lifetime.get_locus (),
-   std::move ("static")));
+   Values::Keywords::STATIC_KW));
   break;
 case Lifetime::LifetimeType::WILDCARD:
-  push (
-   Rust::Token::make_lifetime (lifetime.get_locus (), std::move ("_")));
+  push (Rust::Token::make_lifetime (lifetime.get_locus (),
+   Values::Keywords::UNDERSCORE));
   break;
 }
 }
@@ -787,9 +788,9 @@ TokenCollector::visit (Literal &lit, location_t locus)
 lit.get_type_hint ()));
   break;
   case Literal::LitType::BOOL: {
-   if (value == "false")
+   if (value == Values::Keywords::FALSE_LITERAL)
  push (Rust::Token::make (FALSE_LITERAL, locus));
-   else if (value == "true")
+   else if (value == Values::Keywords::TRUE_LITERAL)
  push (Rust::Token::make (TRUE_LITERAL, locus));
else
  rust_unreachable (); // Not a boolean
@@ -1484,7 +1485,7 @@ TokenCollector::visit (AwaitExpr &expr)
   visit (expr.get_awaited_expr ());
   push (Rust::Token::make (DOT, expr.get_locus ()));
   // TODO: Check status of await keyword (Context dependant ?)
-  push (Rust::Token::make_identifier (UNDEF_LOCATION, "await"));
+  push (Rust::Token::make_identifier (UNDEF_LOCATION, 
Values::Keywords::AWAIT));
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 47c02d6ac8b..4049e4d2607 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -25,6 +25,7 @@
 #include "rust-token.h"
 #include "rust-location.h"
 #include "rust-diagnostics.h"
+#include "rust-keyword-values.h"
 
 namespace Rust {
 // TODO: remove typedefs and make actual types for these
@@ -393,14 +394,20 @@ public:
   const std::string &get_segment_name () const { return segment_name; }
   bool is_super_path_seg () const
   {
-return as_string ().compare ("super") == 0;
+return as_string ().compare (Values::Keywords::SUPER) == 0;
   }
   bool is_crate_path_seg () const
   {
-return as_string ().compare ("crate") == 0;
+return as_string ().compare (Values::Keywords::CRATE) == 0;
+  }
+  bool is_lower_self_seg () const
+  {
+return as_string ().compare (Values::Keywords::SELF) == 0;
+  }
+  bool is_big_self () const
+  {
+return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
   }
-  bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; 
}
-  bool is_big_self () const { return as_string ().compare ("Self") == 0; }
 };
 
 // A simple path without generic or type arguments
@@ -562,7 +569,8 @@ public:
  location_t crate_vis_location)
   {
 return Visibility (PUB_CRATE,
-  SimplePath::from_str ("crate", crate_tok_location),
+  SimplePath::from_str (Values::Keywords::CRATE,
+crate_tok_location),
   crate_vis_location);
   }
 
@@ -571,7 +579,8 @@ public:
 location_t self_vis_location)
   {
 return Visibility (PUB_SELF,
-  SimplePath::from_str ("self", self_tok_location),
+  SimplePath::from_str (Values::Keywords::SELF,
+  

[COMMITTED 068/101] gccrs: Make default resolver inherit from default visitor

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

The default resolver put some scope in place but mostly has traversal
functions similar to the default ast visitor, making it inherit from the
default visitor allows us to avoid code duplication.

gcc/rust/ChangeLog:

* resolve/rust-default-resolver.cc (DefaultResolver::visit): Remove
duplicated functions.
* resolve/rust-default-resolver.h (class DefaultResolver): Make the
default resolver inherit from the default visitor.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/resolve/rust-default-resolver.cc | 240 +-
 gcc/rust/resolve/rust-default-resolver.h  |  44 +---
 2 files changed, 5 insertions(+), 279 deletions(-)

diff --git a/gcc/rust/resolve/rust-default-resolver.cc 
b/gcc/rust/resolve/rust-default-resolver.cc
index c1ed3cea113..ab4d5e8b70d 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -18,6 +18,7 @@
 
 #include "rust-default-resolver.h"
 #include "rust-ast-full.h"
+#include "rust-ast-visitor.h"
 #include "rust-item.h"
 
 namespace Rust {
@@ -148,26 +149,11 @@ DefaultResolver::visit (AST::StructStruct &type)
   // we also can't visit `StructField`s by default, so there's nothing to do -
   // correct? or should we do something like
 
-  for (auto &field : type.get_fields ())
-field.get_field_type ()->accept_vis (*this);
+  AST::DefaultASTVisitor::visit (type);
 
   // FIXME: ???
 }
 
-void
-DefaultResolver::visit (AST::TupleStruct &type)
-{
-  for (auto &field : type.get_fields ())
-field.get_field_type ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::Union &type)
-{
-  for (auto &field : type.get_variants ())
-field.get_field_type ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::Enum &type)
 {
@@ -182,118 +168,6 @@ DefaultResolver::visit (AST::Enum &type)
  variant_fn, type.get_identifier ());
 }
 
-void
-DefaultResolver::visit (AST::BorrowExpr &expr)
-{
-  expr.get_borrowed_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::DereferenceExpr &expr)
-{
-  expr.get_dereferenced_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ErrorPropagationExpr &expr)
-{
-  expr.get_propagating_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::NegationExpr &expr)
-{
-  expr.get_negated_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArithmeticOrLogicalExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ComparisonExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::LazyBooleanExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TypeCastExpr &expr)
-{
-  expr.get_type_to_cast_to ()->accept_vis (*this);
-  expr.get_casted_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::AssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::CompoundAssignmentExpr &expr)
-{
-  expr.get_left_expr ()->accept_vis (*this);
-  expr.get_right_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::GroupedExpr &expr)
-{
-  expr.get_expr_in_parens ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayElemsValues &array)
-{
-  for (auto &value : array.get_values ())
-value->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayElemsCopied &array)
-{
-  array.get_elem_to_copy ()->accept_vis (*this);
-  array.get_num_copies ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayExpr &expr)
-{
-  expr.get_array_elems ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::ArrayIndexExpr &expr)
-{
-  expr.get_array_expr ()->accept_vis (*this);
-  expr.get_index_expr ()->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TupleExpr &expr)
-{
-  for (auto &element : expr.get_tuple_elems ())
-element->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::TupleIndexExpr &expr)
-{
-  expr.get_tuple_expr ()->accept_vis (*this);
-}
-
 void
 DefaultResolver::visit (AST::StructExprFieldIdentifierValue &)
 {}
@@ -302,28 +176,6 @@ void
 DefaultResolver::visit (AST::StructExprFieldIndexValue &)
 {}
 
-void
-DefaultResolver::visit (AST::CallExpr &expr)
-{
-  expr.get_function_expr ()->accept_vis (*this);
-  for (auto ¶m : expr.get_params ())
-param->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::MethodCallExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-  for (auto ¶m : expr.get_params ())
-param->accept_vis (*this);
-}
-
-void
-DefaultResolver::visit (AST::FieldAccessExpr &expr)
-{
-  expr.get_receiver_expr ()->accept_vis (*this);
-}
-
 void
 DefaultRe

[COMMITTED 080/101] gccrs: Handle `async` qualifier inside trait

2024-01-30 Thread arthur . cohen
From: Kushal Pal 

Fixes #2778

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_trait_impl_item):
Handled `async` items

Signed-off-by: Kushal Pal 
---
 gcc/rust/parse/rust-parse-impl.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 52766afd9c4..378b9ada5ed 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -5784,6 +5784,8 @@ Parser::parse_trait_impl_item ()
   // function or method
   return parse_trait_impl_function_or_method (visibility,
  std::move (outer_attrs));
+case ASYNC:
+  return parse_async_item (visibility, std::move (outer_attrs));
 case CONST:
   // lookahead to resolve production - could be function/method or const
   // item
-- 
2.42.1



[COMMITTED 095/101] gccrs: Test: fix missing lifetime in a test

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

This test did not compile with rustc.

gcc/testsuite/ChangeLog:

* rust/compile/torture/utf8_identifiers.rs: add mising lifetime

Signed-off-by: Jakub Dupak 
---
 gcc/testsuite/rust/compile/torture/utf8_identifiers.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs 
b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
index 01c95cf..696fcc0a3d8 100644
--- a/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
+++ b/gcc/testsuite/rust/compile/torture/utf8_identifiers.rs
@@ -1,7 +1,7 @@
 #[lang = "sized"]
 pub trait Sized {}
 
-pub fn f() {
+pub fn f<'かに>() {
 let crab = ();
 
 let Κάβουρας = 0.001;
-- 
2.42.1



[COMMITTED 048/101] gccrs: Add a regression test for unsafe module validation

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add a new test to check for unsafe modules during AST validation pass.

gcc/testsuite/ChangeLog:

* rust/compile/unsafe_module.rs: New test.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/testsuite/rust/compile/unsafe_module.rs | 2 ++
 1 file changed, 2 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/unsafe_module.rs

diff --git a/gcc/testsuite/rust/compile/unsafe_module.rs 
b/gcc/testsuite/rust/compile/unsafe_module.rs
new file mode 100644
index 000..74bc170be5b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unsafe_module.rs
@@ -0,0 +1,2 @@
+unsafe mod toto {}
+// { dg-error "module cannot be declared unsafe" "" { target *-*-* } .-1 }
-- 
2.42.1



[COMMITTED 032/101] gccrs: Added support to Parse ASYNC function

2024-01-30 Thread arthur . cohen
From: M V V S Manoj Kumar 

Fixes issue #2650
The parser now parses ASYNC functions. Added ASYNC case to parse_item
Added a new function parse_async_item which is called in
parse_vis_item to handle the ASYNC case. Parse_async_item
also checks the current Rust edition and generates an error if the
edition is 2015

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_item): Likewise.
(Parser::parse_vis_item): Likewise.
(Parser::parse_async_item): Likewise.
* parse/rust-parse.h: Made declaration for parse_async_item.

gcc/testsuite/ChangeLog:

* rust/compile/issue-2650-1.rs: New test.(edition=2018)
* rust/compile/issue-2650-2.rs: New test.(edition=2015)

Signed-off-by: M V V S Manoj Kumar 
---
 gcc/rust/parse/rust-parse-impl.h   | 40 ++
 gcc/rust/parse/rust-parse.h|  2 ++
 gcc/testsuite/rust/compile/issue-2650-1.rs |  5 +++
 gcc/testsuite/rust/compile/issue-2650-2.rs |  5 +++
 4 files changed, 52 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/issue-2650-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-2650-2.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 37eddc1b753..53b3839db37 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -30,6 +30,7 @@
 #include "rust-dir-owner.h"
 #include "rust-attribute-values.h"
 #include "rust-keyword-values.h"
+#include "rust-session-manager.h"
 
 #include "optional.h"
 
@@ -1113,6 +1114,8 @@ Parser::parse_item (bool 
called_from_statement)
  add_error (std::move (error));
}
   return nullptr;
+
+case ASYNC:
 case PUB:
 case MOD:
 case EXTERN_KW:
@@ -1389,6 +1392,10 @@ Parser::parse_vis_item (AST::AttrVec 
outer_attrs)
  lexer.skip_token (1); // TODO: is this right thing to do?
  return nullptr;
}
+// for async functions
+case ASYNC:
+  return parse_async_item (std::move (vis), std::move (outer_attrs));
+
 case STATIC_KW:
   return parse_static_item (std::move (vis), std::move (outer_attrs));
 case AUTO:
@@ -1429,6 +1436,39 @@ Parser::parse_vis_item (AST::AttrVec 
outer_attrs)
   return nullptr;
 }
 
+template 
+std::unique_ptr
+Parser::parse_async_item (AST::Visibility vis,
+ AST::AttrVec outer_attrs)
+{
+  const_TokenPtr t = lexer.peek_token ();
+  if (Session::get_instance ().options.get_edition ()
+  == CompileOptions::Edition::E2015)
+{
+  add_error (Error (t->get_locus (), ErrorCode::E0670,
+   "% is not permitted in Rust 2015"));
+  add_error (
+   Error::Hint (t->get_locus (),
+"to use %, switch to Rust 2018 or later"));
+}
+
+  t = lexer.peek_token (1);
+
+  switch (t->get_id ())
+{
+case UNSAFE:
+case FN_KW:
+  return parse_function (std::move (vis), std::move (outer_attrs));
+
+default:
+  add_error (
+   Error (t->get_locus (), "expected item, found keyword %"));
+
+  lexer.skip_token (1);
+  return nullptr;
+}
+}
+
 // Parses a macro rules definition syntax extension whatever thing.
 template 
 std::unique_ptr
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index e873d5292cd..d3718467b48 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -357,6 +357,8 @@ private:
   std::unique_ptr
   parse_extern_block (AST::Visibility vis, AST::AttrVec outer_attrs);
   std::unique_ptr parse_method ();
+  std::unique_ptr parse_async_item (AST::Visibility vis,
+  AST::AttrVec outer_attrs);
 
   // Expression-related (Pratt parsed)
   std::unique_ptr
diff --git a/gcc/testsuite/rust/compile/issue-2650-1.rs 
b/gcc/testsuite/rust/compile/issue-2650-1.rs
new file mode 100644
index 000..381398e19f5
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2650-1.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-frust-edition=2018" }
+
+pub async fn a() -> u32 {
+1
+}
diff --git a/gcc/testsuite/rust/compile/issue-2650-2.rs 
b/gcc/testsuite/rust/compile/issue-2650-2.rs
new file mode 100644
index 000..5132e6e1158
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2650-2.rs
@@ -0,0 +1,5 @@
+// { dg-additional-options "-frust-edition=2015" }
+
+pub async fn a() -> u32 { // { dg-error "'async fn' is not permitted in Rust 
2015" }
+1
+}
-- 
2.42.1



[COMMITTED 077/101] gccrs: TyTy: SubstitutionRef cast specialization

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

Allows skipping parent check when casting.

gcc/rust/ChangeLog:

* typecheck/rust-tyty.h (BaseType::is): Cast API.
(SubstitutionRef>): Cast API.
(BaseType::as): Cast API.
(BaseType::try_as): Cast API.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/typecheck/rust-tyty.h | 78 ++
 1 file changed, 78 insertions(+)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 6ce760df66e..2ed407ee169 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1575,6 +1575,84 @@ BaseType::is () const
   return this->is ();
 }
 
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is () const
+{
+  auto kind = this->get_kind ();
+  return kind == FNPTR || kind == FNDEF || kind == CLOSURE || kind == ADT
+|| kind == PROJECTION;
+}
+
+template <>
+WARN_UNUSED_RESULT inline bool
+BaseType::is () const
+{
+  return this->is ();
+}
+
+template <>
+WARN_UNUSED_RESULT inline SubstitutionRef *
+BaseType::as ()
+{
+  auto kind = this->get_kind ();
+  switch (kind)
+{
+case FNDEF:
+  return static_cast (this);
+case CLOSURE:
+  return static_cast (this);
+case ADT:
+  return static_cast (this);
+case PROJECTION:
+  return static_cast (this);
+default:
+  rust_unreachable ();
+}
+}
+
+template <>
+WARN_UNUSED_RESULT inline const SubstitutionRef *
+BaseType::as () const
+{
+  auto kind = this->get_kind ();
+  switch (kind)
+{
+case FNDEF:
+  return static_cast (this);
+case CLOSURE:
+  return static_cast (this);
+case ADT:
+  return static_cast (this);
+case PROJECTION:
+  return static_cast (this);
+default:
+  rust_unreachable ();
+}
+}
+
+template <>
+WARN_UNUSED_RESULT inline SubstitutionRef *
+BaseType::try_as ()
+{
+  if (this->is ())
+{
+  return this->as ();
+}
+  return nullptr;
+}
+
+template <>
+WARN_UNUSED_RESULT inline const SubstitutionRef *
+BaseType::try_as () const
+{
+  if (this->is ())
+{
+  return this->as ();
+}
+  return nullptr;
+}
+
 } // namespace TyTy
 } // namespace Rust
 
-- 
2.42.1



[COMMITTED 079/101] gccrs: split rust-mangle.cc into two files

2024-01-30 Thread arthur . cohen
From: Raiki Tamura 

gcc/rust/ChangeLog:

* Make-lang.in: Add .o files
* backend/rust-mangle.cc (struct V0Path): moved to splitted files
(v0_path): Likewise.
(legacy_mangle_name): Likewise.
(legacy_mangle_canonical_path): Likewise.
(legacy_hash): Likewise.
(v0_tuple_prefix): Likewise.
(v0_numeric_prefix): Likewise.
(v0_simple_type_prefix): Likewise.
(v0_complex_type_prefix): Likewise.
(v0_integer_62): Likewise.
(v0_opt_integer_62): Likewise.
(v0_disambiguator): Likewise.
(v0_type_prefix): Likewise.
(v0_generic_args): Likewise.
(v0_identifier): Likewise.
(v0_type_path): Likewise.
(v0_function_path): Likewise.
(v0_scope_path): Likewise.
(v0_crate_path): Likewise.
(v0_inherent_or_trait_impl_path): Likewise.
(v0_closure): Likewise.
(legacy_mangle_item): Likewise.
(v0_mangle_item): Likewise.
* backend/rust-mangle.h (legacy_mangle_item): Likewise.
(v0_mangle_item): Likewise.
* backend/rust-mangle-legacy.cc: New file.
* backend/rust-mangle-v0.cc: New file.

Signed-off-by: Raiki Tamura 
---
 gcc/rust/Make-lang.in  |   2 +
 gcc/rust/backend/rust-mangle-legacy.cc | 164 +++
 gcc/rust/backend/rust-mangle-v0.cc | 508 +++
 gcc/rust/backend/rust-mangle.cc| 648 +
 gcc/rust/backend/rust-mangle.h |   8 +
 5 files changed, 700 insertions(+), 630 deletions(-)
 create mode 100644 gcc/rust/backend/rust-mangle-legacy.cc
 create mode 100644 gcc/rust/backend/rust-mangle-v0.cc

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index b138ba26801..bdaef41c419 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -85,6 +85,8 @@ GRS_OBJS = \
 rust/rust-session-manager.o \
 rust/rust-compile.o \
 rust/rust-mangle.o \
+rust/rust-mangle-v0.o \
+rust/rust-mangle-legacy.o \
 rust/rust-compile-resolve-path.o \
 rust/rust-macro-expand.o \
 rust/rust-cfg-strip.o \
diff --git a/gcc/rust/backend/rust-mangle-legacy.cc 
b/gcc/rust/backend/rust-mangle-legacy.cc
new file mode 100644
index 000..fd0ba1b3745
--- /dev/null
+++ b/gcc/rust/backend/rust-mangle-legacy.cc
@@ -0,0 +1,164 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// .
+
+#include "rust-mangle.h"
+#include "fnv-hash.h"
+#include "rust-unicode.h"
+#include "rust-diagnostics.h"
+#include "rust-system.h"
+#include 
+
+namespace Rust {
+namespace Compile {
+
+const std::string kLegacySymbolPrefix = "_ZN";
+static const std::string kLegacySymbolDelim = "E";
+static const std::string kLegacyGenericDelim = "$C$";
+static const std::string kLegacySubstBegin = "$LT$";
+static const std::string kLegacySubstEnd = "$GT$";
+static const std::string kLegacySpace = "$u20$";
+static const std::string kLegacyRef = "$RF$";
+static const std::string kLegacyPtr = "$BP$";
+static const std::string kLegacyLeftSqParen = "$u5b$"; // [
+static const std::string kLegacyRightSqParen = "$u5d$"; // ]
+static const std::string kLegacyLeftBrace = "$u7b$";   // {
+static const std::string kLegacyRightBrace = "$u7d$";  // }
+static const std::string kQualPathBegin = "_" + kLegacySubstBegin;
+static const std::string kLegacyComma = "$C$";
+
+static std::string
+legacy_mangle_name (const std::string &name)
+{
+  // example
+  //  <&T as core::fmt::Debug>::fmt:
+  //  _ZN42_$LT$$RF$T$u20$as$u20$core..fmt..Debug$GT$3fmt17h6dac924c0051eef7E
+  // replace all white space with $ and & with RF
+  //
+  // ::fooA:
+  // _ZN43_$LT$example..Bar$u20$as$u20$example..A$GT$4fooA17hfc615fa76c7db7a0E:
+  //
+  // core::ptr::const_ptrcast:
+  // 
_ZN4core3ptr9const_ptr33_$LT$impl$u20$$BP$const$u20$T$GT$4cast17hb79f4617226f1d55E:
+  //
+  // core::ptr::const_ptras_ptr:
+  // 
_ZN4core3ptr9const_ptr43_$LT$impl$u20$$BP$const$u20$$u5b$T$u5d$$GT$6as_ptr17he16e0dcd9473b04fE:
+  //
+  // example::Foo::new:
+  // _ZN7example12Foo$LT$T$GT$3new17h9a2aacb7fd783515E:
+  //
+  // >::call
+  // 
_ZN74_$LT$example..Identity$u20$as$u20$example..FnLike$LT$$RF$T$C$$RF$T$GT$$GT$4call17ha9ee58935895acb3E
+
+  tl::optional utf8_name = Utf8String::make_utf8_string (name);
+  rust_assert (utf8_name.has_value ());
+  std::vector

[COMMITTED 101/101] gccrs: Fix output line ending patterns.

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/testsuite/ChangeLog:

* rust/execute/torture/builtin_macros1.rs: Fix output pattern.
* rust/execute/torture/coercion3.rs: Likewise.
* rust/execute/torture/issue-2080.rs: Likewise.
* rust/execute/torture/issue-2179.rs: Likewise.
* rust/execute/torture/issue-2180.rs: Likewise.
* rust/execute/torture/iter1.rs: Likewise.
---
 gcc/testsuite/rust/execute/torture/builtin_macros1.rs | 2 +-
 gcc/testsuite/rust/execute/torture/coercion3.rs   | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2080.rs  | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2179.rs  | 2 +-
 gcc/testsuite/rust/execute/torture/issue-2180.rs  | 2 +-
 gcc/testsuite/rust/execute/torture/iter1.rs   | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs 
b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
index f5dcbd6423c..04d00581897 100644
--- a/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
+++ b/gcc/testsuite/rust/execute/torture/builtin_macros1.rs
@@ -1,4 +1,4 @@
-// { dg-output "rust/execute/torture/builtin_macros1.rs\r*" }
+// { dg-output "rust/execute/torture/builtin_macros1.rs\r*\n" }
 #![feature(rustc_attrs)]
 
 #[rustc_builtin_macro]
diff --git a/gcc/testsuite/rust/execute/torture/coercion3.rs 
b/gcc/testsuite/rust/execute/torture/coercion3.rs
index e88338ae2f3..0686056de4e 100644
--- a/gcc/testsuite/rust/execute/torture/coercion3.rs
+++ b/gcc/testsuite/rust/execute/torture/coercion3.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/issue-2080.rs 
b/gcc/testsuite/rust/execute/torture/issue-2080.rs
index dbdbf41ff92..5fdf911efe1 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2080.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2080.rs
@@ -1,4 +1,4 @@
-// { dg-output "hello world: gccrs\n" }
+// { dg-output "hello world: gccrs\r*\n" }
 // { dg-additional-options "-w" }
 static TEST_1: &str = "gccrs";
 static TEST_2: i32 = 123;
diff --git a/gcc/testsuite/rust/execute/torture/issue-2179.rs 
b/gcc/testsuite/rust/execute/torture/issue-2179.rs
index 86ed11f51c5..8a5ec1bf32e 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2179.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2179.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/issue-2180.rs 
b/gcc/testsuite/rust/execute/torture/issue-2180.rs
index beed69620a0..6bd71720e48 100644
--- a/gcc/testsuite/rust/execute/torture/issue-2180.rs
+++ b/gcc/testsuite/rust/execute/torture/issue-2180.rs
@@ -1,4 +1,4 @@
-// { dg-output "123\n" }
+// { dg-output "123\r*\n" }
 #[lang = "sized"]
 pub trait Sized {}
 
diff --git a/gcc/testsuite/rust/execute/torture/iter1.rs 
b/gcc/testsuite/rust/execute/torture/iter1.rs
index 08f06456e36..c3b6c7bc3f8 100644
--- a/gcc/testsuite/rust/execute/torture/iter1.rs
+++ b/gcc/testsuite/rust/execute/torture/iter1.rs
@@ -1,4 +1,4 @@
-// { dg-output "1\n2\n" }
+// { dg-output "1\r*\n2\r*\n" }
 #![feature(intrinsics)]
 
 pub use option::Option::{self, None, Some};
-- 
2.42.1



[COMMITTED 036/101] gccrs: nr2.0: Store mappings in NameResolutionContext

2024-01-30 Thread arthur . cohen
From: Arthur Cohen 

gcc/rust/ChangeLog:

* resolve/rust-name-resolution-context.h: Store a reference to the
mappings.
* resolve/rust-name-resolution-context.cc
(NameResolutionContext::NameResolutionContext): Likewise.
---
 gcc/rust/resolve/rust-name-resolution-context.cc | 4 
 gcc/rust/resolve/rust-name-resolution-context.h  | 5 +
 2 files changed, 9 insertions(+)

diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc 
b/gcc/rust/resolve/rust-name-resolution-context.cc
index 82771cdd923..8bb7a9a15c1 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -21,6 +21,10 @@
 namespace Rust {
 namespace Resolver2_0 {
 
+NameResolutionContext::NameResolutionContext ()
+  : mappings (*Analysis::Mappings::get ())
+{}
+
 tl::expected
 NameResolutionContext::insert (Identifier name, NodeId id, Namespace ns)
 {
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index 6d14be35986..d63ee33378b 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -21,6 +21,7 @@
 
 #include "optional.h"
 #include "rust-forever-stack.h"
+#include "rust-hir-map.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -136,6 +137,8 @@ correct
 class NameResolutionContext
 {
 public:
+  NameResolutionContext ();
+
   /**
* Insert a new value in the current rib.
*
@@ -174,6 +177,8 @@ public:
   ForeverStack types;
   ForeverStack macros;
   ForeverStack labels;
+
+  Analysis::Mappings &mappings;
 };
 
 } // namespace Resolver2_0
-- 
2.42.1



[COMMITTED 055/101] gccrs: Add AST validation check for const in trait

2024-01-30 Thread arthur . cohen
From: Pierre-Emmanuel Patry 

Add a new check in AST validation pass that checks that no function
declaration in traits are declared const.

gcc/rust/ChangeLog:

* checks/errors/rust-ast-validation.cc (ASTValidation::visit): Add
const check.
* checks/errors/rust-ast-validation.h: Add visit function prototype.

Signed-off-by: Pierre-Emmanuel Patry 
---
 gcc/rust/checks/errors/rust-ast-validation.cc | 10 ++
 gcc/rust/checks/errors/rust-ast-validation.h  |  1 +
 2 files changed, 11 insertions(+)

diff --git a/gcc/rust/checks/errors/rust-ast-validation.cc 
b/gcc/rust/checks/errors/rust-ast-validation.cc
index 54276e8fd59..2743eb0ca29 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.cc
+++ b/gcc/rust/checks/errors/rust-ast-validation.cc
@@ -117,6 +117,16 @@ ASTValidation::visit (AST::Function &function)
   AST::ContextualASTVisitor::visit (function);
 }
 
+void
+ASTValidation::visit (AST::TraitFunctionDecl &decl)
+{
+  const auto &qualifiers = decl.get_qualifiers ();
+
+  if (context.back () == Context::TRAIT && qualifiers.is_const ())
+rust_error_at (decl.get_identifier ().get_locus (), ErrorCode::E0379,
+  "functions in traits cannot be declared const");
+}
+
 void
 ASTValidation::visit (AST::Trait &trait)
 {
diff --git a/gcc/rust/checks/errors/rust-ast-validation.h 
b/gcc/rust/checks/errors/rust-ast-validation.h
index 01d923ceff3..963357f86cd 100644
--- a/gcc/rust/checks/errors/rust-ast-validation.h
+++ b/gcc/rust/checks/errors/rust-ast-validation.h
@@ -42,6 +42,7 @@ public:
   virtual void visit (AST::Union &item);
   virtual void visit (AST::Function &function);
   virtual void visit (AST::Trait &trait);
+  virtual void visit (AST::TraitFunctionDecl &decl);
 };
 
 } // namespace Rust
-- 
2.42.1



[COMMITTED 076/101] gccrs: TyTy: Common interface for fucntion-like types

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

gcc/rust/ChangeLog:

* typecheck/rust-tyty.h (class ClosureType): Inherit interface.
(class FnPtr): Inherit interface.
(class FnType): Inherit interface.
(class CallableTypeInterface): New interface.
(BaseType::is): Detect interface members API.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/typecheck/rust-tyty.h | 116 -
 1 file changed, 98 insertions(+), 18 deletions(-)

diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index da4b901724d..6ce760df66e 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -38,6 +38,10 @@ class AssociatedImplTrait;
 } // namespace Resolver
 
 namespace TyTy {
+class ClosureType;
+class FnPtr;
+class FnType;
+class CallableTypeInterface;
 
 // 
https://rustc-dev-guide.rust-lang.org/type-inference.html#inference-variables
 // 
https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants
@@ -242,6 +246,22 @@ protected:
   Analysis::Mappings *mappings;
 };
 
+/** Unified interface for all function-like types. */
+class CallableTypeInterface : public BaseType
+{
+public:
+  explicit CallableTypeInterface (HirId ref, HirId ty_ref, TypeKind kind,
+ RustIdent ident,
+ std::set refs = std::set ())
+: BaseType (ref, ty_ref, kind, ident, refs)
+  {}
+
+  WARN_UNUSED_RESULT virtual size_t get_num_params () const = 0;
+  WARN_UNUSED_RESULT virtual BaseType *
+  get_param_type_at (size_t index) const = 0;
+  WARN_UNUSED_RESULT virtual BaseType *get_return_type () const = 0;
+};
+
 class InferType : public BaseType
 {
 public:
@@ -736,7 +756,7 @@ private:
   ReprOptions repr;
 };
 
-class FnType : public BaseType, public SubstitutionRef
+class FnType : public CallableTypeInterface, public SubstitutionRef
 {
 public:
   static constexpr auto KIND = TypeKind::FNDEF;
@@ -751,7 +771,7 @@ public:
  std::vector> params,
  BaseType *type, std::vector subst_refs,
  std::set refs = std::set ())
-: BaseType (ref, ref, TypeKind::FNDEF, ident, refs),
+: CallableTypeInterface (ref, ref, TypeKind::FNDEF, ident, refs),
   SubstitutionRef (std::move (subst_refs),
   SubstitutionArgumentMappings::error ()),
   params (std::move (params)), type (type), flags (flags),
@@ -766,7 +786,7 @@ public:
  std::vector> params,
  BaseType *type, std::vector subst_refs,
  std::set refs = std::set ())
-: BaseType (ref, ty_ref, TypeKind::FNDEF, ident, refs),
+: CallableTypeInterface (ref, ty_ref, TypeKind::FNDEF, ident, refs),
   SubstitutionRef (std::move (subst_refs),
   SubstitutionArgumentMappings::error ()),
   params (params), type (type), flags (flags), identifier (identifier),
@@ -832,8 +852,6 @@ public:
 return params.at (idx);
   }
 
-  BaseType *get_return_type () const { return type; }
-
   BaseType *clone () const final override;
 
   FnType *
@@ -842,6 +860,21 @@ public:
   ABI get_abi () const { return abi; }
   uint8_t get_flags () const { return flags; }
 
+  WARN_UNUSED_RESULT size_t get_num_params () const override
+  {
+return params.size ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_param_type_at (size_t index) const override
+  {
+return param_at (index).second;
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_return_type () const override
+  {
+return type;
+  }
+
 private:
   std::vector> params;
   BaseType *type;
@@ -851,33 +884,50 @@ private:
   ABI abi;
 };
 
-class FnPtr : public BaseType
+class FnPtr : public CallableTypeInterface
 {
 public:
   static constexpr auto KIND = TypeKind::FNPTR;
 
   FnPtr (HirId ref, location_t locus, std::vector params,
 TyVar result_type, std::set refs = std::set ())
-: BaseType (ref, ref, TypeKind::FNPTR,
-   {Resolver::CanonicalPath::create_empty (), locus}, refs),
+: CallableTypeInterface (ref, ref, TypeKind::FNPTR,
+{Resolver::CanonicalPath::create_empty (), locus},
+refs),
   params (std::move (params)), result_type (result_type)
   {}
 
   FnPtr (HirId ref, HirId ty_ref, location_t locus, std::vector params,
 TyVar result_type, std::set refs = std::set ())
-: BaseType (ref, ty_ref, TypeKind::FNPTR,
-   {Resolver::CanonicalPath::create_empty (), locus}, refs),
+: CallableTypeInterface (ref, ty_ref, TypeKind::FNPTR,
+{Resolver::CanonicalPath::create_empty (), locus},
+refs),
   params (params), result_type (result_type)
   {}
 
   std::string get_name () const override final { return as_string (); }
 
-  BaseType *get_return_type () const { return result_type.get_tyty (); }
+  WARN_UNUSED_RESULT size_t get_num_params () const override
+  {
+return params.size ();
+  }
+
+  WARN_UNUSED_RESULT BaseType *get_param_ty

[COMMITTED 083/101] gccrs: ast: Unify explicitly and implicitly elided lifettimes

2024-01-30 Thread arthur . cohen
From: Jakub Dupak 

gcc/rust/ChangeLog:

* ast/rust-ast.h: Elided lifetime static constructor
* ast/rust-type.h: Default lifetime to elided.
* parse/rust-parse-impl.h (Parser::parse_lifetime_param): Use elided 
lifetime.
(Parser::parse_lifetime): Use elided lifetime/
(Parser::lifetime_from_token): Use elided lifetime.
(Parser::parse_self_param): Use elided lifetime.
(Parser::parse_reference_type_inner): Use elided lifetime.

Signed-off-by: Jakub Dupak 
---
 gcc/rust/ast/rust-ast.h  |  2 ++
 gcc/rust/ast/rust-type.h |  2 +-
 gcc/rust/parse/rust-parse-impl.h | 10 --
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index b193c67c69e..a45085489e8 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1512,6 +1512,8 @@ public:
   // Creates an "error" lifetime.
   static Lifetime error () { return Lifetime (NAMED, ""); }
 
+  static Lifetime elided () { return Lifetime (WILDCARD, ""); }
+
   // Returns true if the lifetime is in an error state.
   bool is_error () const
   {
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 1637367791c..91a9d2f5999 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -547,7 +547,7 @@ public:
 
   // Constructor
   ReferenceType (bool is_mut, std::unique_ptr type_no_bounds,
-location_t locus, Lifetime lifetime = Lifetime::error ())
+location_t locus, Lifetime lifetime = Lifetime::elided ())
 : lifetime (std::move (lifetime)), has_mut (is_mut),
   type (std::move (type_no_bounds)), locus (locus)
   {}
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 90bc2e214e4..0e2cfce1e19 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3470,8 +3470,6 @@ Parser::parse_lifetime_param ()
   return AST::LifetimeParam::create_error ();
 }
   lexer.skip_token ();
-  /* TODO: does this always create a named lifetime? or can a different type
-   * be made? */
   AST::Lifetime lifetime (AST::Lifetime::NAMED, lifetime_tok->get_str (),
  lifetime_tok->get_locus ());
 
@@ -4141,10 +4139,9 @@ AST::Lifetime
 Parser::parse_lifetime ()
 {
   const_TokenPtr lifetime_tok = lexer.peek_token ();
-  // create error lifetime if doesn't exist
   if (lifetime_tok->get_id () != LIFETIME)
 {
-  return AST::Lifetime::error ();
+  return AST::Lifetime::elided ();
 }
   lexer.skip_token ();
 
@@ -4164,6 +4161,7 @@ Parser::lifetime_from_token 
(const_TokenPtr tok)
 }
   else if (lifetime_ident == "_")
 {
+  // Explicitly and implicitly elided lifetimes follow the same rules.
   return AST::Lifetime (AST::Lifetime::WILDCARD, "", locus);
 }
   else
@@ -7177,7 +7175,7 @@ tl::expected, ParseSelfError>
 Parser::parse_self_param ()
 {
   bool has_reference = false;
-  AST::Lifetime lifetime = AST::Lifetime::error ();
+  AST::Lifetime lifetime = AST::Lifetime::elided ();
 
   location_t locus = lexer.peek_token ()->get_locus ();
 
@@ -9837,7 +9835,7 @@ std::unique_ptr
 Parser::parse_reference_type_inner (location_t locus)
 {
   // parse optional lifetime
-  AST::Lifetime lifetime = AST::Lifetime::error ();
+  AST::Lifetime lifetime = AST::Lifetime::elided ();
   if (lexer.peek_token ()->get_id () == LIFETIME)
 {
   lifetime = parse_lifetime ();
-- 
2.42.1



  1   2   3   >