Re: debian-i386 target (Was: ppc64le added to buildbot)

2021-06-02 Thread Mark Wielaard
Hi Philip,

On Wed, Jun 02, 2021 at 11:22:43AM +0100, Philip Herron wrote:
> > Analyzing compilation unit
> > /home/mark/gccrs/gcc/testsuite/rust.test/compile/methods1.rs: In function
> > ‘Rectangle_sum_x’:
> > /home/mark/gccrs/gcc/testsuite/rust.test/compile/methods1.rs:26:5: error:
> > type mismatch in binary expression
> >26 | fn sum_x(self) -> f64 {
> >   | ^
> > f64
> >
> > 
> >
> > 
> >
> > D.227 = _2 + _4;
> > /home/mark/gccrs/gcc/testsuite/rust.test/compile/methods1.rs:26:5:
> > internal compiler error: ‘verify_gimple’ failed
> > 0x8b114e4 verify_gimple_in_seq(gimple*)
> > ../../gccrs/gcc/tree-cfg.c:5157
> > 0x881a9e3 gimplify_body(tree_node*, bool)
> > ../../gccrs/gcc/gimplify.c:15401
> > 0x881abb2 gimplify_function_tree(tree_node*)
> > ../../gccrs/gcc/gimplify.c:15472
> > 0x8675c88 cgraph_node::analyze()
> > ../../gccrs/gcc/cgraphunit.c:670
> > 0x8678a58 analyze_functions
> > ../../gccrs/gcc/cgraphunit.c:1236
> > 0x8679641 symbol_table::finalize_compilation_unit()
> > ../../gccrs/gcc/cgraphunit.c:2514
> 
> This is a good find I will open an issue to track this, I have a local
> Debian 32 bit machine at home so I can try this on later in the week. Off
> the top of my head I am wondering if there is something wrong with how we
> are building up the integer tree nodes. The relevant code starts in
> gcc/rust/backend/rust-compile-tyty.h inside ```  void visit (TyTy::IntType
> &type) override```.
> 
> Let me know if you get anywhere with this before Friday since I will should
> be able to look into this issue then.

I looked a bit but am still struggling with how to debug the gimple generation.
The following is a simpler variant that shows the issue:

fn sum(x: f64, y: f64) -> f64
{
  x + y
}

fn main()
{
  let _sum = sum(3.0, 4.0);
}

Interestingly the following, using an mutable temporary variable to hold the 
result does pass:

fn sum(x: f64, y: f64) -> f64
{
   let mut z:f64 = x;
   z += y;
   z
}

fn main()
{
  let _sum = sum(3.0, 4.0);
}

As far as I can tell the second variant still uses float:80 for the
temporaries, but because z is f64 it gets cast to (f64) when
returning, making the gimple check pass.

So I assumed it was because the arguments got the wrong type somehow.
But the following also doesn't pass:

fn sum(x: f64, y: f64) -> f64
{
   let a:f64 = x;
   let b:f64 = y;
   a + b
}

fn main()
{
  let _sum = sum(3.0, 4.0);
}

So it is as if the plus expression gets its variable types wrong.
I don't know where that is generated though, or why it is using float:80.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Test results for gccrs on Debian unstable aarch64

2021-06-03 Thread Mark Wielaard
On Thu, Jun 03, 2021 at 12:58:46PM +0100, Philip Herron wrote:
> I just had a thought it would be nice if we could keep a matrix of
> different platforms gccrs has been tested on, and they could have states of:
> 
> 1. Build Failure
> 2. Test Failures link to log
> 3. Tests pass, no unexpected results

Note that the buildbot could provide that (for the arches it supports).
If you look at:
https://builder.wildebeest.org/buildbot/#/builders?tags=gccrust
you can see which arches are green.
And for each build it publishes the rust.sum and rust.log files
(under the make check link)

Currently I have only enabled the arches that I know are fully green
(x86_64, arm64 and ppc64le). I should add ppc64[be] because that
should also be fully green. I am not sure about enabling enabling
others (arm32, i386 and s390x). It seems a bit pointless to run builds
we know are currently broken.

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Use PRIx64 to print 64bit hex values in legacy_hash

2021-06-03 Thread Mark Wielaard
* gcc/rust/backend/rust-compile.cc (legacy_hash): lo and hi are 
uint64_t use
PRIx64 to print them as hex values instead of %lx which is target 
specific.
---
 gcc/rust/backend/rust-compile.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 480afc8b72b..ea21ad3f92b 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -442,7 +442,7 @@ legacy_hash (const std::string &fingerprint)
 
   char hex[16 + 1];
   memset (hex, 0, sizeof hex);
-  snprintf (hex, sizeof hex, "%08lx%08lx", lo, hi);
+  snprintf (hex, sizeof hex, "%08" PRIx64 "%08" PRIx64, lo, hi);
 
   return "h" + std::string (hex, sizeof (hex) - 1);
 }
-- 
2.32.0.rc0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Test results for gccrs on Debian unstable aarch64

2021-06-03 Thread Mark Wielaard
Hi,

On Thu, Jun 03, 2021 at 09:05:22PM +0200, Mark Wielaard wrote:
> Currently I have only enabled the arches that I know are fully green
> (x86_64, arm64 and ppc64le). I should add ppc64[be] because that
> should also be fully green.

fedora-ppc64 is enabled now too:
https://builder.wildebeest.org/buildbot/#/builders/61

It currently has no builds because there have been no new commits,
but I verified by hand that it is green.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-06-12 Thread Mark Wielaard
Hi,

On Sat, Jun 12, 2021 at 11:38:01PM +, build...@builder.wildebeest.org wrote:
> The Buildbot has detected a new failure on builder gccrust-debian-arm64 while 
> building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/58/builds/45
> 
> Buildbot URL: https://builder.wildebeest.org/buildbot/
> 
> Worker for this Build: debian-arm64
> 
> Build Reason: 
> Blamelist: John Paul Adrian Glaubitz 
> 
> BUILD FAILED: failed compile (failure)

Sorry, that was my fault, I was experimenting with ccache to speed up
builds, but misconfigured things. It should be setup correctly now.
At least we know now that the buildbot sents out emails when something
goes wrong.

Apologies,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-06-18 Thread Mark Wielaard
On Fri, 2021-06-18 at 11:06 +, build...@builder.wildebeest.org
wrote:
> The Buildbot has detected a new failure on builder gccrust-fedora-
> ppc64 while building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/61/builds/40
> 
> Buildbot URL: https://builder.wildebeest.org/buildbot/
> 
> Worker for this Build: fedora-ppc64
> 
> Build Reason: 
> Blamelist: bors[bot] <26634292+bors[bot]@users.noreply.github.com>
> 
> BUILD FAILED: failed compile (failure)

Apologies again. This is me playing with ccache again.
It seems to work fine on all other arches (arm64, x86_64 and ppc64le)
but on ppc64 it causes signal 13 (SIGPIPE) failures. I haven't figured
out why yet.

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


tuple indexes

2021-06-22 Thread Mark Wielaard
Hi,

I was looking into https://github.com/Rust-GCC/gccrs/issues/511 "rust
has two kinds of integer literal" Which explains that integer literals
used for a tuple index are not general integer literals.

First I wanted to write some tests, and started with some constructs
that should pass. But some don't. In particular the empty tuple struct
isn't recognized, and the struct name path lookup doesn't work when
initializing the tuple struct.

tuple_index.rs:16:12: error: unrecognised token ‘)’ in type
   16 |   struct E();
  |^
tuple_index.rs:16:12: error: could not parse type in tuple struct field

tuple_index.rs:20:12: error: unknown root segment in path O lookup O
   20 |   let so = O(0);
  |^
tuple_index.rs:24:12: error: unknown root segment in path T lookup T
   24 |   let st = T(0,1);
  |^
tuple_index.rs:28:12: error: unknown root segment in path M lookup M
   28 |   let sm = M(0,1,2,3,4,5,6,7,8,9,10);
  |^

I haven't had time to try to resolve these issues, but wanted to
report them.

Finally, the The Rust Reference says "A tuple index is used to refer
to the fields of tuples, tuple structs, and tuple variants." I don't
understand how this would work for tuple variants. Does anybody have
an example of how to refer to a tuple variant so a tuple index can be
used on it?

Cheers,

Mark

tuple_index.rs
Description: application/rls-services
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: tuple indexes

2021-06-23 Thread Mark Wielaard
Hi Philip,

On Wed, 2021-06-23 at 10:55 +0100, Philip Herron wrote:
> Small update, I think part of this issue is that the support for
> unit-structs is not there yet in the compiler, so if you remove the unit
> tuple struct and move the other struct definitions outside of the block
> the test case works: https://godbolt.org/z/nb84sEaE4
> 
> It might be enough to help with testing your tuple index fixes.

Very nice. That workaround helps me get unblocked, except for testing
empty struct tuples (unit-structs). But I have a patch for that, and
even included a testcase to proof the parser now handles them. See
attached.

Cheers,

Mark
From a1d03b5182f7e2b16b5201459c98b33a12775888 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Wed, 23 Jun 2021 17:59:30 +0200
Subject: [PATCH] Handle empty/unit tuple structs in the parser.

A tuple struct can be empty, in which case it is a unit tuple struct.
Handle this in Parser::parse_struct by creating
a empty tuple_field vector instead of calling parse_tuple_fields.

Add a testcase to show empty tuple structs are now accepted.
---
 gcc/rust/parse/rust-parse-impl.h  |  7 ++-
 .../rust/compile/torture/tuple_struct_unit.rs | 11 +++
 2 files changed, 17 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index b4f264e0261..dfac00e3dbc 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -3980,7 +3980,12 @@ Parser::parse_struct (AST::Visibility vis,
   lexer.skip_token ();
 
   // parse tuple fields
-  std::vector tuple_fields = parse_tuple_fields ();
+  std::vector tuple_fields;
+  // Might be empty tuple for unit tuple struct.
+  if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+	tuple_fields = std::vector ();
+  else
+	tuple_fields = parse_tuple_fields ();
 
   // tuple parameters must have closing parenthesis
   if (!skip_token (RIGHT_PAREN))
diff --git a/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs b/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs
new file mode 100644
index 000..cda19d2af0b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_struct_unit.rs
@@ -0,0 +1,11 @@
+struct E();
+struct T(E,E,());
+
+fn main()
+{
+  let z0 = E();
+  let z1 = E();
+  let t = T(z0,z1,());
+  let z = t.2;
+  z
+}
-- 
2.31.1

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: tuple indexes

2021-06-23 Thread Mark Wielaard
On Wed, Jun 23, 2021 at 12:51:34AM +0200, Mark Wielaard wrote:
> Finally, the The Rust Reference says "A tuple index is used to refer
> to the fields of tuples, tuple structs, and tuple variants." I don't
> understand how this would work for tuple variants. Does anybody have
> an example of how to refer to a tuple variant so a tuple index can be
> used on it?

Tom pointed out on irc that it doesn't seem possible to access enum
variant types except through a matching expression. The Rust Reference
also seems to be inconsistent. As mentioned above it mentions you can
use a tuple index to refer to a field of a enum tuple variant. But it
also says "A tuple indexing expression accesses fields of tuples and
tuple structs." So it probably really isn't possible to use a tuple
index on enum tuple variants.

I did notice the same issue as for unit tuple struct types. The empty
tuple wasn't accepted in the parser. The attached patch, also at
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=tuple_enum_variant_unit
fixes this.

It does include a test case, but most of it is commented out because
actually resolving enum types isn't implemented yet. If you uncomment
the rest of the testcase you get:

tuple_enum_variants.rs:3:31: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  |   ^
tuple_enum_variants.rs:3:31: error: unresolved type
tuple_enum_variants.rs:3:33: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  | ^
tuple_enum_variants.rs:3:33: error: unresolved type
tuple_enum_variants.rs:3:35: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  |   ^
tuple_enum_variants.rs:3:35: error: unresolved type
tuple_enum_variants.rs:3:10: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  |  ^
tuple_enum_variants.rs:3:10: error: unresolved type
tuple_enum_variants.rs:3:17: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  | ^
tuple_enum_variants.rs:3:17: error: unresolved type
tuple_enum_variants.rs:3:24: error: failed to resolve TypePath: E
3 | fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
  |^
tuple_enum_variants.rs:3:24: error: unresolved type
tuple_enum_variants.rs:13:12: error: unknown root segment in path E::T0 lookup E
   13 |   let e0 = E::T0();
  |^
tuple_enum_variants.rs:14:12: error: unknown root segment in path E::T1 lookup E
   14 |   let e1 = E::T1(0);
  |^
tuple_enum_variants.rs:15:12: error: unknown root segment in path E::T2 lookup E
   15 |   let e2 = E::T2(0,1);
  |^

Cheers,

Mark>From ee1d3b6ab4d508caea35efef67ec89f54178781c Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Wed, 23 Jun 2021 21:54:16 +0200
Subject: [PATCH] Handle empty/unit tuple enum variants in the parser.

A tuple enum variant can be empty, in which case it is a unit enum variant.
Handle this in Parser::parse_enum_item by creating
a empty tuple_field vector instead of calling parse_tuple_fields.

Add a testcase to show empty tuple enum variant types are now accepted.
But note some part of the test is commented out because using the enum
type isn't actually possible right now.
---
 gcc/rust/parse/rust-parse-impl.h  |  7 ++-
 .../compile/torture/tuple_enum_variants.rs| 19 +++
 2 files changed, 25 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index dfac00e3dbc..9a28f6cdb66 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -4415,7 +4415,12 @@ Parser::parse_enum_item ()
 	// tuple enum item
 	lexer.skip_token ();
 
-	std::vector tuple_fields = parse_tuple_fields ();
+	std::vector tuple_fields;
+	// Might be empty tuple for unit tuple enum variant.
+	if (lexer.peek_token ()->get_id () == RIGHT_PAREN)
+	  tuple_fields = std::vector ();
+	else
+	  tuple_fields = parse_tuple_fields ();
 
 	if (!skip_token (RIGHT_PAREN))
 	  {
diff --git a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
new file mode 100644
index 000..26e3e5d0a71
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
@@ -0,0 +1,19 @@
+enum E { T0(), T1(i32), T2(i32,u32) }
+
+/* The following doesn't parse yet...
+fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
+{
+  let e = e0;
+  let f = e1;
+  let g = e2;
+  (e,f,g,())
+}
+
+fn main()
+{
+  let e0 = E::T0();
+  let e1 = E::T1(0);
+  let e2 = E::T2(0,1);
+  f(e0, e1, e2).3
+}
+*/
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Reject non-pure decimal tuple indexes.

2021-06-25 Thread Mark Wielaard
Tuple indexes should be pure decimal integer literals. But the parser just sees 
an
integer literal. Fix this by introducing a new type hint CORETYPE_PURE_DECIMAL. 
This
doesn't conflict with any existing type hints since a pure decimal doesn't have 
a
type suffix.

Introduce a new method is_pure_decimal that the parser can use in 
parse_tuple_index_expr.
get_type_hint will return CORETYPE_UNKNOWN for pure decimals.

parse_decimal_int_or_float will check whether there are no execissive leading 
zeros.
parse_in_decimal checks the literal doesn't contain any underscores.

Add two testcases. bad_tuple_index.rs with all variants of integer literals 
which aren't
pure decimals. And tuple_index.rs with various correct tuple indexes.

Resolves: https://github.com/Rust-GCC/gccrs/issues/511
---
 gcc/rust/lex/rust-lex.cc  | 33 ++
 gcc/rust/lex/rust-lex.h   |  2 +-
 gcc/rust/lex/rust-token.cc|  2 +
 gcc/rust/lex/rust-token.h | 14 +++-
 gcc/rust/parse/rust-parse-impl.h  |  6 ++
 gcc/testsuite/rust/compile/bad_tuple_index.rs | 66 +++
 .../rust/compile/torture/tuple_index.rs   | 32 +
 7 files changed, 142 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_tuple_index.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_index.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b320401e3bb..860ac9f95f8 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -942,23 +942,26 @@ Lexer::parse_in_exponent_part ()
}
 
   // parse another decimal number for exponent
-  auto str_length_pair = parse_in_decimal ();
-  str += str_length_pair.first;
-  additional_length_offset += str_length_pair.second;
+  auto str_length = parse_in_decimal ();
+  str += std::get<0>(str_length);
+  additional_length_offset += std::get<1>(str_length);
 }
   return std::make_pair (str, additional_length_offset);
 }
 
 // Parses a decimal integer.
-std::pair
+std::tuple
 Lexer::parse_in_decimal ()
 {
+  /* A pure decimal contains only digits.  */
+  bool pure_decimal = true;
   int additional_length_offset = 0;
   std::string str;
   while (ISDIGIT (current_char) || current_char == '_')
 {
   if (current_char == '_')
{
+ pure_decimal = false;
  // don't add _ to number
  skip_input ();
  current_char = peek_input ();
@@ -974,7 +977,7 @@ Lexer::parse_in_decimal ()
   skip_input ();
   current_char = peek_input ();
 }
-  return std::make_pair (str, additional_length_offset);
+  return std::make_tuple (str, additional_length_offset, pure_decimal);
 }
 
 /* Parses escapes (and string continues) in "byte" strings and characters. Does
@@ -1842,13 +1845,14 @@ Lexer::parse_decimal_int_or_float (Location loc)
   str += current_char;
 
   int length = 1;
+  bool first_zero = current_char == '0';
 
   current_char = peek_input ();
 
   // parse initial decimal integer (or first integer part of float) literal
-  auto initial_decimal_pair = parse_in_decimal ();
-  str += initial_decimal_pair.first;
-  length += initial_decimal_pair.second;
+  auto initial_decimal = parse_in_decimal ();
+  str += std::get<0>(initial_decimal);
+  length += std::get<1>(initial_decimal);
 
   // detect float literal
   if (current_char == '.' && is_float_digit (peek_input (1)))
@@ -1862,9 +1866,9 @@ Lexer::parse_decimal_int_or_float (Location loc)
   length++;
 
   // parse another decimal number for float
-  auto second_decimal_pair = parse_in_decimal ();
-  str += second_decimal_pair.first;
-  length += second_decimal_pair.second;
+  auto second_decimal = parse_in_decimal ();
+  str += std::get<0>(second_decimal);
+  length += std::get<1>(second_decimal);
 
   // parse in exponent part if it exists
   auto exponent_pair = parse_in_exponent_part ();
@@ -1947,6 +1951,13 @@ Lexer::parse_decimal_int_or_float (Location loc)
   // parse in type suffix if it exists
   auto type_suffix_pair = parse_in_type_suffix ();
   PrimitiveCoreType type_hint = type_suffix_pair.first;
+  /* A "real" pure decimal doesn't have a suffix and no zero prefix.  */
+  if (type_hint == CORETYPE_UNKNOWN)
+   {
+ bool pure_decimal = std::get<2>(initial_decimal);
+ if (pure_decimal && (!first_zero || str.size() == 1))
+   type_hint = CORETYPE_PURE_DECIMAL;
+   }
   length += type_suffix_pair.second;
 
   current_column += length;
diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h
index ba37c63416d..902745fa1d5 100644
--- a/gcc/rust/lex/rust-lex.h
+++ b/gcc/rust/lex/rust-lex.h
@@ -71,7 +71,7 @@ private:
   // Builds a token from the input queue.
   TokenPtr build_token ();
 
-  std::pair parse_in_decimal ();
+  std::tuple parse_in_decimal ();
   std::pair parse_in_exponent_part ();
   std::pair parse_in_

Re: [PATCH] Reject non-pure decimal tuple indexes.

2021-06-25 Thread Mark Wielaard
Hi,

Attached is a slightly updated version for some whitespace issues.
There are spaces after the std::get and the is_pure_decimal
function is now fully on one line.

Cheers,

Mark
>From 60cb8cc43b91ff8a00be45be1106f95f161e9c8d Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Fri, 25 Jun 2021 19:37:11 +0200
Subject: [PATCH] Reject non-pure decimal tuple indexes.

Tuple indexes should be pure decimal integer literals. But the parser just sees an
integer literal. Fix this by introducing a new type hint CORETYPE_PURE_DECIMAL. This
doesn't conflict with any existing type hints since a pure decimal doesn't have a
type suffix.

Introduce a new method is_pure_decimal that the parser can use in parse_tuple_index_expr.
get_type_hint will return CORETYPE_UNKNOWN for pure decimals.

parse_decimal_int_or_float will check whether there are no execissive leading zeros.
parse_in_decimal checks the literal doesn't contain any underscores.

Add two testcases. bad_tuple_index.rs with all variants of integer literals which aren't
pure decimals. And tuple_index.rs with various correct tuple indexes.

Resolves: https://github.com/Rust-GCC/gccrs/issues/511
---
 gcc/rust/lex/rust-lex.cc  | 33 ++
 gcc/rust/lex/rust-lex.h   |  2 +-
 gcc/rust/lex/rust-token.cc|  2 +
 gcc/rust/lex/rust-token.h | 11 +++-
 gcc/rust/parse/rust-parse-impl.h  |  6 ++
 gcc/testsuite/rust/compile/bad_tuple_index.rs | 66 +++
 .../rust/compile/torture/tuple_index.rs   | 32 +
 7 files changed, 139 insertions(+), 13 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_tuple_index.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/tuple_index.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b320401e3bb..d1384168731 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -942,23 +942,26 @@ Lexer::parse_in_exponent_part ()
 	}
 
   // parse another decimal number for exponent
-  auto str_length_pair = parse_in_decimal ();
-  str += str_length_pair.first;
-  additional_length_offset += str_length_pair.second;
+  auto str_length = parse_in_decimal ();
+  str += std::get<0> (str_length);
+  additional_length_offset += std::get<1> (str_length);
 }
   return std::make_pair (str, additional_length_offset);
 }
 
 // Parses a decimal integer.
-std::pair
+std::tuple
 Lexer::parse_in_decimal ()
 {
+  /* A pure decimal contains only digits.  */
+  bool pure_decimal = true;
   int additional_length_offset = 0;
   std::string str;
   while (ISDIGIT (current_char) || current_char == '_')
 {
   if (current_char == '_')
 	{
+	  pure_decimal = false;
 	  // don't add _ to number
 	  skip_input ();
 	  current_char = peek_input ();
@@ -974,7 +977,7 @@ Lexer::parse_in_decimal ()
   skip_input ();
   current_char = peek_input ();
 }
-  return std::make_pair (str, additional_length_offset);
+  return std::make_tuple (str, additional_length_offset, pure_decimal);
 }
 
 /* Parses escapes (and string continues) in "byte" strings and characters. Does
@@ -1842,13 +1845,14 @@ Lexer::parse_decimal_int_or_float (Location loc)
   str += current_char;
 
   int length = 1;
+  bool first_zero = current_char == '0';
 
   current_char = peek_input ();
 
   // parse initial decimal integer (or first integer part of float) literal
-  auto initial_decimal_pair = parse_in_decimal ();
-  str += initial_decimal_pair.first;
-  length += initial_decimal_pair.second;
+  auto initial_decimal = parse_in_decimal ();
+  str += std::get<0> (initial_decimal);
+  length += std::get<1> (initial_decimal);
 
   // detect float literal
   if (current_char == '.' && is_float_digit (peek_input (1)))
@@ -1862,9 +1866,9 @@ Lexer::parse_decimal_int_or_float (Location loc)
   length++;
 
   // parse another decimal number for float
-  auto second_decimal_pair = parse_in_decimal ();
-  str += second_decimal_pair.first;
-  length += second_decimal_pair.second;
+  auto second_decimal = parse_in_decimal ();
+  str += std::get<0> (second_decimal);
+  length += std::get<1> (second_decimal);
 
   // parse in exponent part if it exists
   auto exponent_pair = parse_in_exponent_part ();
@@ -1947,6 +1951,13 @@ Lexer::parse_decimal_int_or_float (Location loc)
   // parse in type suffix if it exists
   auto type_suffix_pair = parse_in_type_suffix ();
   PrimitiveCoreType type_hint = type_suffix_pair.first;
+  /* A "real" pure decimal doesn't have a suffix and no zero prefix.  */
+  if (type_hint == CORETYPE_UNKNOWN)
+	{
+	  bool pure_decimal = std::get<2> (initial_decimal);
+	  if (pure_decimal && (!first_zero || str.size () == 1))
+	type_hint = CORETYPE_PURE_DECIMAL;
+	}
  

[PATCH] Fix inner attribute parsing

2021-06-27 Thread Mark Wielaard
parse_inner_attribute tried to skip the right square token twice. This caused 
odd error
messages in case there were multiple inner attributes. This bug masked another 
bug in
parse_attr_input where when the (optional) attr input was an assignment to a 
literal
the parser failed to skip the literal.

The existing top_attr.rs testcase relied on the two bugs cancelling each other 
out.
Add a new testcase inner_attributes.rs for the first bug.

Resolves: https://github.com/Rust-GCC/gccrs/issues/510
---
 gcc/rust/parse/rust-parse-impl.h   | 2 +-
 gcc/testsuite/rust/compile/torture/inner_attributes.rs | 3 +++
 2 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/inner_attributes.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 014beaf9e9c..23e62349e40 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -495,7 +495,6 @@ Parser::parse_inner_attribute ()
 return AST::Attribute::create_empty ();
 
   AST::Attribute actual_attribute = parse_attribute_body ();
-  lexer.skip_token ();
 
   if (!skip_token (RIGHT_SQUARE))
 return AST::Attribute::create_empty ();
@@ -785,6 +784,7 @@ Parser::parse_attr_input ()
// create actual LiteralExpr
AST::LiteralExpr lit_expr (t->get_str (), lit_type, t->get_type_hint (),
   {}, t->get_locus ());
+   lexer.skip_token ();
 
std::unique_ptr attr_input_lit (
  new AST::AttrInputLiteral (std::move (lit_expr)));
diff --git a/gcc/testsuite/rust/compile/torture/inner_attributes.rs 
b/gcc/testsuite/rust/compile/torture/inner_attributes.rs
new file mode 100644
index 000..3410dd6ec87
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/inner_attributes.rs
@@ -0,0 +1,3 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+pub fn main () { }
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Suppress warning in rust-ast-lower-type.h ASTLowerGenericParam.visit.

2021-06-28 Thread Mark Wielaard
Translating the AST LifetimeType to the HIR LifetimeType causes a warning:
warning: ‘ltt’ may be used uninitialized

Add a default clause to the switch statement calling gcc_unreachable.
This will suppress the warning and make sure that if the AST lifetime type
is invalid or a new unknown type we immediately know when lowering the AST.
---
 gcc/rust/hir/rust-ast-lower-type.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/gcc/rust/hir/rust-ast-lower-type.h 
b/gcc/rust/hir/rust-ast-lower-type.h
index 5e19850e8dd..568a806f98d 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -281,6 +281,8 @@ public:
   case AST::Lifetime::LifetimeType::WILDCARD:
ltt = HIR::Lifetime::LifetimeType::WILDCARD;
break;
+  default:
+   gcc_unreachable ();
   }
 
 HIR::Lifetime lt (mapping, ltt, param.get_lifetime ().get_lifetime_name (),
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Suppress warning in rust-ast-lower-type.h ASTLowerGenericParam.visit.

2021-06-28 Thread Mark Wielaard
On Tue, Jun 29, 2021 at 12:06:56AM +0200, Marc wrote:
> Hi,
> 
> > Translating the AST LifetimeType to the HIR LifetimeType causes a warning:
> > warning: ‘ltt’ may be used uninitialized
> 
> Was wondering why this is needed as the switch case covers all enum
> variants, how can ltt be uninitialized ? I have the same fix locally but
> was thinking something else was causing the error...

LifetimeType is a plain enum, which aren't really their own types,
they are really just ints with fancy names. We could make them enum
class, which is a strong type. Then the compiler would know the switch
really covers all enum (class) variants. But then we have to provide
the right scope/type everywhere we use them in the code (which might
be a good idea, but is more typing).

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Suppress warning in rust-ast-lower-type.h ASTLowerGenericParam.visit.

2021-06-28 Thread Mark Wielaard
On Tue, Jun 29, 2021 at 12:47:07AM +0200, Mark Wielaard wrote:
> On Tue, Jun 29, 2021 at 12:06:56AM +0200, Marc wrote:
> > Hi,
> > 
> > > Translating the AST LifetimeType to the HIR LifetimeType causes a warning:
> > > warning: ‘ltt’ may be used uninitialized
> > 
> > Was wondering why this is needed as the switch case covers all enum
> > variants, how can ltt be uninitialized ? I have the same fix locally but
> > was thinking something else was causing the error...
> 
> LifetimeType is a plain enum, which aren't really their own types,
> they are really just ints with fancy names. We could make them enum
> class, which is a strong type. Then the compiler would know the switch
> really covers all enum (class) variants. But then we have to provide
> the right scope/type everywhere we use them in the code (which might
> be a good idea, but is more typing).

I just tried to make LifetimeType an enum class and that doesn't help.
So I was wrong. I don't know why the compiler doesn't see this? It
should know since if not all switch cases were covered, -Wswitch
(enabled by -Wall) gives us a warning... So, I don't fully understand
why gcc needs the default gcc_unreachable case. It is what is used in
the rest of the code though.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Suppress warning in rust-ast-lower-type.h ASTLowerGenericParam.visit.

2021-06-29 Thread Mark Wielaard
Hi Marc,

On Tue, Jun 29, 2021 at 08:28:51AM +0200, Marc wrote:
> Mark Wielaard  writes:
> > I just tried to make LifetimeType an enum class and that doesn't help.
> > So I was wrong. I don't know why the compiler doesn't see this? It
> > should know since if not all switch cases were covered, -Wswitch
> > (enabled by -Wall) gives us a warning... So, I don't fully understand
> > why gcc needs the default gcc_unreachable case. It is what is used in
> > the rest of the code though.
> 
> I thought maybe that's a C++ vs C diff, or something caused by the
> Lifetime being returned by a function call, but I can't reproduce it, so
> that must be something else:
> 
> https://godbolt.org/z/sjbcWEqdj

Try using the result of the function and using -O2

  enum LifetimeType
  {
NAMED,   // corresponds to LIFETIME_OR_LABEL
STATIC,  // corresponds to 'static
WILDCARD // corresponds to '_
  };

 int g(int i);

 LifetimeType toto();
  int t ()  {
  int t;
  switch(toto()){
  case NAMED:
  t=4;
  break;
  case STATIC:
  t=5;
  break;
  case WILDCARD:
  t=8;
  break;
  }
  return g(t);
  }

gcc -O2 -Wall

: In function 'int t()':
:24:15: warning: 't' may be used uninitialized in this function 
[-Wmaybe-uninitialized]
   24 |   return g(t);
  |  ~^~~

> Anyway, Philipp wants to have these enum shared between AST and HIR, so
> this kind of 'if(AST::Foo) t=HIR::Foo' can be removed.

That might be a good idea if the LifetimeType has the same values and
semantics between AST and HIR.

But till that happend I think it is a good idea to suppress warnings like this.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 2/2] Remove unused have_more_segments from TypeCheckExpr::resolve_root_path

2021-06-29 Thread Mark Wielaard
It isn't necessary to know whether there are more segments while
iteration through the expression segements.
---
 gcc/rust/typecheck/rust-hir-type-check-expr.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index e06b10d358a..327a9a06df7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -1121,7 +1121,6 @@ private:
 for (size_t i = 0; i < expr.get_num_segments (); i++)
   {
HIR::PathExprSegment &seg = expr.get_segments ().at (i);
-   bool have_more_segments = i < expr.get_num_segments ();
bool is_root = *offset == 0;
NodeId ast_node_id = seg.get_mappings ().get_nodeid ();
 
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/2] Remove unused default_ty_param from TypeResolveGenericParam::visit

2021-06-29 Thread Mark Wielaard
The default_ty_param was set, but not used. We do need to call 
TypeCheckType::Resolve
on the default param, but don't need the result.
---
 gcc/rust/typecheck/rust-hir-type-check-type.h | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h 
b/gcc/rust/typecheck/rust-hir-type-check-type.h
index b4baccf4299..6081ec549ce 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.h
@@ -255,11 +255,9 @@ public:
 
   void visit (HIR::TypeParam ¶m) override
   {
-TyTy::BaseType *default_ty_param = nullptr;
 if (param.has_type ())
-  {
-   default_ty_param = TypeCheckType::Resolve (param.get_type ().get ());
-  }
+  TypeCheckType::Resolve (param.get_type ().get ());
+
 resolved = new TyTy::ParamType (param.get_type_representation (),
param.get_mappings ().get_hirid (), param);
   }
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


shebang handling

2021-07-04 Thread Mark Wielaard
Hi,

Shebang handling, the first line starting with #! was not done fully
correct and it isn't necessary to keep track of the shebang line in
the AST or HIR Crate classes.

Because an inner attribute also starts with #! the first line isn't
regarded as a shebang line if the #! is followed by (optional)
whitespace and comments and a [. In that case the #! is seen as the
start of an inner attribute.

I added various testcases that hopefully show the funny things you can
get when the first line starts with #!.

 [PATCH 1/2] Handle shebang line, plus any whitespace and comment
 [PATCH 2/2] Remove has_shebang flag from AST and HIR Crate classes

Patches can also be found here:
https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=shebang

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/2] Handle shebang line, plus any whitespace and comment skipping in lexer

2021-07-04 Thread Mark Wielaard
The lexer tried to handle the shebang line but used loc directly,
instead of the current_column. And it assumed a '/' should immediately
follow the "#!". But if the "#!" is followed by whitespace and/or
comments and a '[' character, then the first line isn't see as a
shebang line (even if the kernel or shell would) but as the start of
an inner attribute.

Add various tests for when the first line starting with "#!" is seen
as a shebang line (and should be skipped). And some tests there is a
'[' character following some whitespace and/or comments and the "#!"
is seen as part of an inner attribute.
---
 gcc/rust/lex/rust-lex.cc  | 79 ++-
 .../rust/compile/torture/not_shebang.rs   |  3 +
 .../torture/not_shebang_block_comment.rs  |  1 +
 .../compile/torture/not_shebang_comment.rs|  3 +
 .../torture/not_shebang_multiline_comment.rs  |  7 ++
 .../compile/torture/not_shebang_spaces.rs |  6 ++
 gcc/testsuite/rust/compile/torture/shebang.rs |  3 +
 .../rust/compile/torture/shebang_plus_attr.rs |  3 +
 .../compile/torture/shebang_plus_attr2.rs |  3 +
 9 files changed, 89 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/not_shebang_block_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/not_shebang_multiline_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/not_shebang_spaces.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang_plus_attr.rs
 create mode 100755 gcc/testsuite/rust/compile/torture/shebang_plus_attr2.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index d1384168731..ebd69de0fd1 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -237,28 +237,63 @@ Lexer::build_token ()
   current_char = peek_input ();
   skip_input ();
 
-  // return end of file token if end of file
-  if (current_char == EOF)
-   return Token::make (END_OF_FILE, loc);
-
   // detect shebang
-  if (loc == 1 && current_line == 1 && current_char == '#')
+  // Must be the first thing on the first line, starting with #!
+  // But since an attribute can also start with an #! we don't count it as 
a
+  // shebang line when after any whitespace or comments there is a [. If it
+  // is a shebang line we simple drop the line. Otherwise we don't consume
+  // any characters and fall through to the real tokenizer.
+  if (current_line == 1 && current_column == 1 && current_char == '#'
+ && peek_input () == '!')
{
- current_char = peek_input ();
-
- if (current_char == '!')
+ int n = 1;
+ while (true)
{
- skip_input ();
- current_char = peek_input ();
-
- if (current_char == '/')
+ int next_char = peek_input (n);
+ if (is_whitespace (next_char))
+   n++;
+ else if (next_char == '/' && peek_input (n + 1) == '/')
{
- // definitely shebang
-
- skip_input ();
-
- // ignore rest of line
- while (current_char != '\n')
+ // A single line comment
+ n += 2;
+ next_char = peek_input (n);
+ while (next_char != '\n' && next_char != EOF)
+   {
+ n++;
+ next_char = peek_input (n);
+   }
+ if (next_char == '\n')
+   n++;
+   }
+ else if (next_char == '/' && peek_input (n + 1) == '*')
+   {
+ // Start of a block comment
+ n += 2;
+ int level = 1;
+ while (level > 0)
+   {
+ if (peek_input (n) == EOF)
+   break;
+ else if (peek_input (n) == '/'
+  && peek_input (n + 1) == '*')
+   {
+ n += 2;
+ level += 1;
+   }
+ else if (peek_input (n) == '*'
+  && peek_input (n + 1) == '/')
+   {
+ n += 2;
+ level -= 1;
+   }
+ else
+   n++;
+   }
+   }
+ else if (next_char != '[')
+   {
+ // definitely shebang, ignore the first line
+ while (current_char != '\n' && current_char != EOF)
{
  current_char = peek_input ();
  skip_input ();
@@ -269,11 +304,17 @

[PATCH 2/2] Remove has_shebang flag from AST and HIR Crate classes

2021-07-04 Thread Mark Wielaard
The lexer deals with the shebang and the parser cannot detect whether
there is or isn't a shebang line. The flag isn't relevant or useful in
the AST and HIR Crate classes.
---
 gcc/rust/ast/rust-ast-full-test.cc  |  5 +
 gcc/rust/ast/rust-ast.h | 13 +
 gcc/rust/hir/rust-ast-lower.cc  |  3 +--
 gcc/rust/hir/tree/rust-hir-full-test.cc |  6 +-
 gcc/rust/hir/tree/rust-hir.h| 14 +-
 gcc/rust/parse/rust-parse-impl.h| 12 +---
 6 files changed, 18 insertions(+), 35 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index 3d339ad1aed..12ef255bcbf 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -172,13 +172,10 @@ Crate::as_string () const
   rust_debug ("beginning crate recursive as-string");
 
   std::string str ("Crate: ");
-  // add utf8bom and shebang
+  // add utf8bom
   if (has_utf8bom)
 str += "\n has utf8bom";
 
-  if (has_shebang)
-str += "\n has shebang";
-
   // inner attributes
   str += append_attributes (inner_attrs, INNER);
 
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 0e25de2be5c..ce55e1beb5e 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1551,7 +1551,6 @@ protected:
 struct Crate
 {
   bool has_utf8bom;
-  bool has_shebang;
 
   std::vector inner_attrs;
   // dodgy spacing required here
@@ -1564,17 +1563,16 @@ struct Crate
 public:
   // Constructor
   Crate (std::vector > items,
-std::vector inner_attrs, bool has_utf8bom = false,
-bool has_shebang = false)
-: has_utf8bom (has_utf8bom), has_shebang (has_shebang),
-  inner_attrs (std::move (inner_attrs)), items (std::move (items)),
+std::vector inner_attrs, bool has_utf8bom = false)
+: has_utf8bom (has_utf8bom), inner_attrs (std::move (inner_attrs)),
+  items (std::move (items)),
   node_id (Analysis::Mappings::get ()->get_next_node_id ())
   {}
 
   // Copy constructor with vector clone
   Crate (Crate const &other)
-: has_utf8bom (other.has_utf8bom), has_shebang (other.has_shebang),
-  inner_attrs (other.inner_attrs), node_id (other.node_id)
+: has_utf8bom (other.has_utf8bom), inner_attrs (other.inner_attrs),
+  node_id (other.node_id)
   {
 items.reserve (other.items.size ());
 for (const auto &e : other.items)
@@ -1587,7 +1585,6 @@ public:
   Crate &operator= (Crate const &other)
   {
 inner_attrs = other.inner_attrs;
-has_shebang = other.has_shebang;
 has_utf8bom = other.has_utf8bom;
 node_id = other.node_id;
 
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index c7222e2e998..0f3c86dc7bf 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -41,7 +41,6 @@ ASTLowering::go ()
 {
   std::vector > items;
   bool has_utf8bom = false;
-  bool has_shebang = false;
 
   for (auto it = astCrate.items.begin (); it != astCrate.items.end (); it++)
 {
@@ -57,7 +56,7 @@ ASTLowering::go ()
 UNKNOWN_LOCAL_DEFID);
 
   return HIR::Crate (std::move (items), astCrate.get_inner_attrs (), mapping,
-has_utf8bom, has_shebang);
+has_utf8bom);
 }
 
 // rust-ast-lower-block.h
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc 
b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 261b3af672a..051ba8736ad 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -73,15 +73,11 @@ std::string
 Crate::as_string () const
 {
   std::string str ("HIR::Crate: ");
-  // add utf8bom and shebang
+  // add utf8bom
   if (has_utf8bom)
 {
   str += "\n has utf8bom";
 }
-  if (has_shebang)
-{
-  str += "\n has shebang";
-}
 
   // inner attributes
   str += "\n inner attributes: ";
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 35dc71ae1df..f918f2dc106 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -679,7 +679,6 @@ public:
 struct Crate
 {
   bool has_utf8bom;
-  bool has_shebang;
 
   AST::AttrVec inner_attrs;
   // dodgy spacing required here
@@ -692,17 +691,15 @@ struct Crate
 public:
   // Constructor
   Crate (std::vector > items, AST::AttrVec inner_attrs,
-Analysis::NodeMapping mappings, bool has_utf8bom = false,
-bool has_shebang = false)
-: has_utf8bom (has_utf8bom), has_shebang (has_shebang),
-  inner_attrs (std::move (inner_attrs)), items (std::move (items)),
-  mappings (mappings)
+Analysis::NodeMapping mappings, bool has_utf8bom = false)
+: has_utf8bom (has_utf8bom), inner_attrs (std::move (inner_attrs)),
+  items (std::move (items)), mappings (mappings)
   {}
 
   // Copy constructor with vector clone
   Crate (Crate const &other)
-: has_utf8bom (other.has_utf8bom), has_shebang (other.has_shebang),
-  inner_attrs (other.inner_attrs), mappings (ot

UTF-8 BOM handling

2021-07-05 Thread Mark Wielaard
Hi,

A rust source file can start with a UTF-8 BOM sequence (EF BB
BF). This simply indicates that the file is encoded as UTF-8 (all rust
input is interpreted as asequence of Unicode code points encoded in
UTF-8) so can be skipped before starting real lexing.

It isn't necessary to keep track of the BOM in the AST or HIR Crate
classes. So I removed the has_utf8bom flag.

Also included are a couple of simple tests to show we handle the BOM
correctly now.

 [PATCH 1/2] Handle UTF-8 BOM in lexer
 [PATCH 2/2] Remove has_utf8bom flag from AST and HIR Crate classes

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/2] Handle UTF-8 BOM in lexer

2021-07-05 Thread Mark Wielaard
The very first thing in a rust source file might be the optional UTF-8
BOM.  This is the 3 bytes 0xEF 0xBB 0xBF. They can simply be skipped,
they just mark the file as UTF-8.  Add some testcases to show we now
handle such files.
---
 gcc/rust/lex/rust-lex.cc| 13 +
 gcc/testsuite/rust/compile/torture/bom.rs   |  1 +
 gcc/testsuite/rust/compile/torture/bom_comment.rs   |  2 ++
 gcc/testsuite/rust/compile/torture/bom_shebang.rs   |  2 ++
 .../rust/compile/torture/bom_whitespace.rs  |  2 ++
 5 files changed, 20 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/torture/bom.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_shebang.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/bom_whitespace.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index ebd69de0fd1..617dd69a080 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -237,6 +237,19 @@ Lexer::build_token ()
   current_char = peek_input ();
   skip_input ();
 
+  // detect UTF8 bom
+  //
+  // Must be the first thing on the first line.
+  // There might be an optional BOM (Byte Order Mark), which for UTF-8 is
+  // the three bytes 0xEF, 0xBB and 0xBF. These can simply be skipped.
+  if (current_line == 1 && current_column == 1 && current_char == 0xef
+ && peek_input () == 0xbb && peek_input (1) == 0xbf)
+   {
+ skip_input (1);
+ current_char = peek_input ();
+ skip_input ();
+   }
+
   // detect shebang
   // Must be the first thing on the first line, starting with #!
   // But since an attribute can also start with an #! we don't count it as 
a
diff --git a/gcc/testsuite/rust/compile/torture/bom.rs 
b/gcc/testsuite/rust/compile/torture/bom.rs
new file mode 100644
index 000..5edcab227ee
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom.rs
@@ -0,0 +1 @@
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_comment.rs 
b/gcc/testsuite/rust/compile/torture/bom_comment.rs
new file mode 100644
index 000..020e1707b55
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_comment.rs
@@ -0,0 +1,2 @@
+// UTF8 BOM
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_shebang.rs 
b/gcc/testsuite/rust/compile/torture/bom_shebang.rs
new file mode 100644
index 000..4c552e8d71d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_shebang.rs
@@ -0,0 +1,2 @@
+#!/usr/bin/cat
+pub fn main () { }
diff --git a/gcc/testsuite/rust/compile/torture/bom_whitespace.rs 
b/gcc/testsuite/rust/compile/torture/bom_whitespace.rs
new file mode 100644
index 000..b10d5654473
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bom_whitespace.rs
@@ -0,0 +1,2 @@
+
+pub fn main () { }
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 2/2] Remove has_utf8bom flag from AST and HIR Crate classes

2021-07-05 Thread Mark Wielaard
The lexer deals with the UTF-8 BOM and the parser cannot detect
whether there is or isn't a BOM at the start of a file. The flag isn't
relevant or useful in the AST and HIR Crate classes.
---
 gcc/rust/ast/rust-ast-full-test.cc  |  3 ---
 gcc/rust/ast/rust-ast.h | 11 +++
 gcc/rust/hir/rust-ast-lower.cc  |  4 +---
 gcc/rust/hir/tree/rust-hir-full-test.cc |  5 -
 gcc/rust/hir/tree/rust-hir.h| 12 
 gcc/rust/parse/rust-parse-impl.h|  8 +---
 6 files changed, 9 insertions(+), 34 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index 12ef255bcbf..dd55e1ddbd2 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -172,9 +172,6 @@ Crate::as_string () const
   rust_debug ("beginning crate recursive as-string");
 
   std::string str ("Crate: ");
-  // add utf8bom
-  if (has_utf8bom)
-str += "\n has utf8bom";
 
   // inner attributes
   str += append_attributes (inner_attrs, INNER);
diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index ce55e1beb5e..75b08f8aa66 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1550,8 +1550,6 @@ protected:
 // A crate AST object - holds all the data for a single compilation unit
 struct Crate
 {
-  bool has_utf8bom;
-
   std::vector inner_attrs;
   // dodgy spacing required here
   /* TODO: is it better to have a vector of items here or a module (implicit
@@ -1563,16 +1561,14 @@ struct Crate
 public:
   // Constructor
   Crate (std::vector > items,
-std::vector inner_attrs, bool has_utf8bom = false)
-: has_utf8bom (has_utf8bom), inner_attrs (std::move (inner_attrs)),
-  items (std::move (items)),
+std::vector inner_attrs)
+: inner_attrs (std::move (inner_attrs)), items (std::move (items)),
   node_id (Analysis::Mappings::get ()->get_next_node_id ())
   {}
 
   // Copy constructor with vector clone
   Crate (Crate const &other)
-: has_utf8bom (other.has_utf8bom), inner_attrs (other.inner_attrs),
-  node_id (other.node_id)
+: inner_attrs (other.inner_attrs), node_id (other.node_id)
   {
 items.reserve (other.items.size ());
 for (const auto &e : other.items)
@@ -1585,7 +1581,6 @@ public:
   Crate &operator= (Crate const &other)
   {
 inner_attrs = other.inner_attrs;
-has_utf8bom = other.has_utf8bom;
 node_id = other.node_id;
 
 items.reserve (other.items.size ());
diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc
index 0f3c86dc7bf..01abd84627b 100644
--- a/gcc/rust/hir/rust-ast-lower.cc
+++ b/gcc/rust/hir/rust-ast-lower.cc
@@ -40,7 +40,6 @@ HIR::Crate
 ASTLowering::go ()
 {
   std::vector > items;
-  bool has_utf8bom = false;
 
   for (auto it = astCrate.items.begin (); it != astCrate.items.end (); it++)
 {
@@ -55,8 +54,7 @@ ASTLowering::go ()
 mappings->get_next_hir_id (crate_num),
 UNKNOWN_LOCAL_DEFID);
 
-  return HIR::Crate (std::move (items), astCrate.get_inner_attrs (), mapping,
-has_utf8bom);
+  return HIR::Crate (std::move (items), astCrate.get_inner_attrs (), mapping);
 }
 
 // rust-ast-lower-block.h
diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc 
b/gcc/rust/hir/tree/rust-hir-full-test.cc
index 051ba8736ad..05c75e06403 100644
--- a/gcc/rust/hir/tree/rust-hir-full-test.cc
+++ b/gcc/rust/hir/tree/rust-hir-full-test.cc
@@ -73,11 +73,6 @@ std::string
 Crate::as_string () const
 {
   std::string str ("HIR::Crate: ");
-  // add utf8bom
-  if (has_utf8bom)
-{
-  str += "\n has utf8bom";
-}
 
   // inner attributes
   str += "\n inner attributes: ";
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index f918f2dc106..1819d17b585 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -678,8 +678,6 @@ public:
 // A crate HIR object - holds all the data for a single compilation unit
 struct Crate
 {
-  bool has_utf8bom;
-
   AST::AttrVec inner_attrs;
   // dodgy spacing required here
   /* TODO: is it better to have a vector of items here or a module (implicit
@@ -691,15 +689,14 @@ struct Crate
 public:
   // Constructor
   Crate (std::vector > items, AST::AttrVec inner_attrs,
-Analysis::NodeMapping mappings, bool has_utf8bom = false)
-: has_utf8bom (has_utf8bom), inner_attrs (std::move (inner_attrs)),
-  items (std::move (items)), mappings (mappings)
+Analysis::NodeMapping mappings)
+: inner_attrs (std::move (inner_attrs)), items (std::move (items)),
+  mappings (mappings)
   {}
 
   // Copy constructor with vector clone
   Crate (Crate const &other)
-: has_utf8bom (other.has_utf8bom), inner_attrs (other.inner_attrs),
-  mappings (other.mappings)
+: inner_attrs (other.inner_attrs), mappings (other.mappings)
   {
 items.reserve (other.items.size ());
 for (const auto &e : other.items)
@@ -712,7

[PATCH] Handle doc comment strings in lexer and parser

2021-07-11 Thread Mark Wielaard
Remove (unused) comment related tokens and replace them with
INNER_DOC_COMMENT and OUTER_DOC_COMMENT tokens, which keep the comment
text as a string. These can be constructed with the new
make_inner_doc_comment and make_outer_doc_comment methods.

Make sure to not confuse doc strings with normal comments in the lexer
when detecting shebang lines. Both single line //! and /*! */ blocks
are turned into INNER_DOC_COMMENT tokens. And both single line /// and
/** */ blocks are turned into OUTER_DOC_COMMENT tokens.

Also fixes some issues with cr/lf line endings and keeping the line
map correct when seeing \n in a comment.

In the parser handle INNER_DOC_COMMENT and OUTER_DOC_COMMENTS where
inner (#[]) and outer (#![]) attributes are handled. Add a method
parse_doc_comment which turns the tokens into an "doc" Attribute with
the string as literal expression.

Add get_locus method to Attribute class for better error reporting.

Tests are added for correctly placed and formatted doc strings, with
or without cr/lf line endings. Incorrect formatted (isolated CRs) doc
strings and badly placed inner doc strings. No tests add handling of
the actual doc attributes yet. These could be tested once we add
support for the #![warn(missing_docs)] attribute.
---
 gcc/rust/ast/rust-ast.h   |   2 +
 gcc/rust/lex/rust-lex.cc  | 214 --
 gcc/rust/lex/rust-token.h |  25 +-
 gcc/rust/parse/rust-parse-impl.h  |  60 -
 gcc/rust/parse/rust-parse.h   |   1 +
 gcc/testsuite/rust/compile/bad_inner_doc.rs   |  15 ++
 .../compile/doc_isolated_cr_block_comment.rs  |   3 +
 .../doc_isolated_cr_inner_block_comment.rs|   5 +
 .../doc_isolated_cr_inner_line_comment.rs |   5 +
 .../compile/doc_isolated_cr_line_comment.rs   |   3 +
 .../torture/all_doc_comment_line_blocks.rs|  47 
 .../all_doc_comment_line_blocks_crlf.rs   |  47 
 .../torture/isolated_cr_block_comment.rs  |   2 +
 .../torture/isolated_cr_line_comment.rs   |   2 +
 14 files changed, 401 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_inner_doc.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 75b08f8aa66..3e3e185b9b5 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -455,6 +455,8 @@ public:
   // Returns whether the attribute is considered an "empty" attribute.
   bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
 
+  Location get_locus () const { return locus; }
+
   /* e.g.:
   #![crate_type = "lib"]
   #[test]
diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 617dd69a080..0b8a8eae651 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -265,9 +265,16 @@ Lexer::build_token ()
  int next_char = peek_input (n);
  if (is_whitespace (next_char))
n++;
- else if (next_char == '/' && peek_input (n + 1) == '/')
+ else if ((next_char == '/' && peek_input (n + 1) == '/'
+   && peek_input (n + 2) != '!'
+   && peek_input (n + 2) != '/')
+  || (next_char == '/' && peek_input (n + 1) == '/'
+  && peek_input (n + 2) == '/'
+  && peek_input (n + 3) == '/'))
{
+ // two // or four 
  // A single line comment
+ // (but not an inner or outer doc comment)
  n += 2;
  next_char = peek_input (n);
  while (next_char != '\n' && next_char != EOF)
@@ -278,9 +285,30 @@ Lexer::build_token ()
  if (next_char == '\n')
n++;
}
- else if (next_char == '/' && peek_input (n + 1) == '*')
+ else if (next_char == '/' && peek_input (n + 1) == '*'
+  && peek_input (n + 2) == '*'
+  && peek_input (n + 3) == '/')
{
+ /**/
+ n += 4;
+   }
+ else if (next_char == '/' && peek_input (n + 1) == '*'
+  && peek_input (n + 2) == '*' && peek_input (n + 3) == '*'
+  && peek

[PATCH] Remove HIR MacroItem and other hir macro forward declarations

2021-07-11 Thread Mark Wielaard
Almost all HIR Macro related trees were already removed by
https://github.com/Rust-GCC/gccrs/pull/492

But there was still one MacroItem class left in rust-hir.h and several
(unused) forward declarations in various other hir .h files. Remove
them all.

Resolves: https://github.com/Rust-GCC/gccrs/issues/69
---
 gcc/rust/hir/tree/rust-hir-expr.h|  3 ---
 gcc/rust/hir/tree/rust-hir-item.h|  3 ---
 gcc/rust/hir/tree/rust-hir-pattern.h |  2 --
 gcc/rust/hir/tree/rust-hir-type.h|  3 ---
 gcc/rust/hir/tree/rust-hir.h | 11 ---
 5 files changed, 22 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-expr.h 
b/gcc/rust/hir/tree/rust-hir-expr.h
index 681ccf8ad65..2b1e9380f6c 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -3094,9 +3094,6 @@ protected:
   }
 };
 
-// Forward decl - defined in rust-macro.h
-class MacroInvocation;
-
 // An unsafe block HIR node
 class UnsafeBlockExpr : public ExprWithBlock
 {
diff --git a/gcc/rust/hir/tree/rust-hir-item.h 
b/gcc/rust/hir/tree/rust-hir-item.h
index 10b1f6143f0..e7e110fda92 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -3020,9 +3020,6 @@ protected:
   }*/
 };
 
-// Replaced with forward decls - defined in "rust-macro.h"
-class MacroItem;
-class MacroRulesDefinition;
 } // namespace HIR
 } // namespace Rust
 
diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h 
b/gcc/rust/hir/tree/rust-hir-pattern.h
index 27cba7d6e18..ac7155d562f 100644
--- a/gcc/rust/hir/tree/rust-hir-pattern.h
+++ b/gcc/rust/hir/tree/rust-hir-pattern.h
@@ -1152,8 +1152,6 @@ class PathPattern;
 class PathInExpression;
 class QualifiedPathInExpression;
 
-// Replaced with forward decl - defined in rust-macro.h
-class MacroInvocation;
 } // namespace HIR
 } // namespace Rust
 
diff --git a/gcc/rust/hir/tree/rust-hir-type.h 
b/gcc/rust/hir/tree/rust-hir-type.h
index 42fccb59607..c4771b6db38 100644
--- a/gcc/rust/hir/tree/rust-hir-type.h
+++ b/gcc/rust/hir/tree/rust-hir-type.h
@@ -907,9 +907,6 @@ protected:
   }
 };
 
-// Forward decl - defined in rust-macro.h
-class MacroInvocation;
-
 /* TODO: possible types
  * struct type?
  * "enum" (tagged union) type?
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 1819d17b585..7d53feb0a4e 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -613,17 +613,6 @@ protected:
   }
 };
 
-// A macro item HIR node - potentially abstract base class
-class MacroItem : public Item
-{
-  /*public:
-  std::string as_string() const;*/
-protected:
-  MacroItem (Analysis::NodeMapping mappings, AST::AttrVec outer_attribs)
-: Item (std::move (mappings), std::move (outer_attribs))
-  {}
-};
-
 // Item used in trait declarations - abstract base class
 class TraitItem
 {
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Handle doc comment strings in lexer and parser

2021-07-12 Thread Mark Wielaard
Hi Philip,

On Mon, Jul 12, 2021 at 09:09:09AM +0100, Philip Herron wrote:
> This patch looks good to me. When I tried to apply it to merge it I got
> the following:
> 
> ```
> $ git am  '[PATCH] Handle doc comment strings in lexer and parser.eml'
> Applying: Handle doc comment strings in lexer and parser
> error: corrupt patch at line 531
> Patch failed at 0001 Handle doc comment strings in lexer and parser
> hint: Use 'git am --show-current-patch' to see the failed patch
> When you have resolved this problem, run "git am --continue".
> If you prefer to skip this patch, run "git am --skip" instead.
> To restore the original branch and stop patching, run "git am --abort".
> ```
> 
> Not sure if I have done something wrong, have you any pointers?

Looks like that is one of the IsolatedCR tests (a bare \r not at the
end of a line followed by \n in a doc comment string). I assume some
mailer ate it and/or added a \n somehwere to "correct" it.

Would you be able to pull directly from my git repo?

The following changes since commit 4560f469ee33536cec6af0f8e5816ff97de60de0:

  Merge #551 (2021-07-10 21:02:06 +)

are available in the Git repository at:

  https://code.wildebeest.org/git/user/mjw/gccrs doc-comments

for you to fetch changes up to e1e14958a90397a1ed6ab7236dc5a6f1c2f22505:

  Handle doc comment strings in lexer and parser (2021-07-11 21:09:21 +0200)


Mark Wielaard (1):
  Handle doc comment strings in lexer and parser

 gcc/rust/ast/rust-ast.h|   2 +
 gcc/rust/lex/rust-lex.cc   | 214 +++--
 gcc/rust/lex/rust-token.h  |  25 ++-
 gcc/rust/parse/rust-parse-impl.h   |  60 +-
 gcc/rust/parse/rust-parse.h|   1 +
 gcc/testsuite/rust/compile/bad_inner_doc.rs|  15 ++
 .../rust/compile/doc_isolated_cr_block_comment.rs  |   3 +
 .../compile/doc_isolated_cr_inner_block_comment.rs |   5 +
 .../compile/doc_isolated_cr_inner_line_comment.rs  |   5 +
 .../rust/compile/doc_isolated_cr_line_comment.rs   |   3 +
 .../compile/torture/all_doc_comment_line_blocks.rs |  47 +
 .../torture/all_doc_comment_line_blocks_crlf.rs|  47 +
 .../compile/torture/isolated_cr_block_comment.rs   |   2 +
 .../compile/torture/isolated_cr_line_comment.rs|   2 +
 14 files changed, 401 insertions(+), 30 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_inner_doc.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/doc_isolated_cr_inner_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/doc_isolated_cr_inner_line_comment.rs
 create mode 100644 gcc/testsuite/rust/compile/doc_isolated_cr_line_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/all_doc_comment_line_blocks_crlf.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/isolated_cr_block_comment.rs
 create mode 100644 
gcc/testsuite/rust/compile/torture/isolated_cr_line_comment.rs

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


New contributor tasks

2021-07-12 Thread Mark Wielaard
On Mon, Jul 12, 2021 at 11:06:01AM +0100, Philip Herron wrote:
> Great work once again. I am aiming to spend some time towards the end of
> the week to add more tickets and info for new contributors to get
> involved, which I will post the interesting ones onto the mailing list
> as well. I think it should be interesting to contributors of all levels.
> The main one that sticks out in my mind is the AST, HIR dumps which are
> a bit of a mess at the moment.

The AST dump (--rust-dump-parse) was actually useful for checking the
comment doc strings, but it could certainly be improved. Ideally it
would be structured in a way that can easily be used in tests.

Some (random) notes I made on issues that might be nice to explain
and/or work on.

- Full unicode/utf8 support in the lexer. Currently the lexer only
  explicitly interprets the input as UTF8 for string parseing. It
  should really treat all input as UTF-8. gnulib has some handy
  modules we could use to read/convert from/to utf8 (unistr/u8-to-u32,
  unistr/u32-to-u8) and test various unicode properties
  (unictype/property-white-space, unictype/property-xid-continue,
  unictype/property-xid-start). I don't know if we can import those or
  if gcc already has these kind of UTF-8/unicode support functions for
  other languages?

- Error handling using rich locations in the lexer and parser.  It
  seems some support is already there, but it isn't totally clear to
  me what is already in place and what could/should be added. e.g. how
  to add notes to an Error.

- I noticed some expressions didn't parse because of what looks to me
  operator precedence issues. e.g the following:

  const S: usize = 64;

  pub fn main ()
  {
let a:u8 = 1;
let b:u8 = 2;
let _c = S * a as usize + b as usize;
  }

  $ gcc/gccrs -Bgcc as.rs

  as.rs:7:27: error: type param bounds (in TraitObjectType) are not allowed as 
TypeNoBounds
7 |   let _c = S * a as usize + b as usize;
  |   ^

  How does one fix such operator precedence issues in the parser?

- Related, TypeCastExpr as the above aren't lowered from AST to HIR.
  I believe I know how to do it, but a small description of the visitor
  pattern used and in which files one does such lowering would be helpful.

- And of course, how to lower HIR to GENERIC?  For TypeCastExpr you
  said on irc we need traits first, but the semantics for primitive
  types is actually spelled out in The Reference. Can we already
  handle them for primitive types (like in the above example having an
  u8 as usize)?

- rust-macro-expand tries to handle both macros and attributes, is
  this by design?  Should we handle different passes for different
  (inert or not) attributes that run before or after macro expansion?

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Fwd: New contributor tasks

2021-07-17 Thread Mark Wielaard
Hi Joel,

On Sat, Jul 17, 2021 at 10:25:48PM +0800, The Other wrote:
> > - Full unicode/utf8 support in the lexer. Currently the lexer only
> >   explicitly interprets the input as UTF8 for string parseing. It
> >   should really treat all input as UTF-8. gnulib has some handy
> >   modules we could use to read/convert from/to utf8 (unistr/u8-to-u32,
> >   unistr/u32-to-u8) and test various unicode properties
> >   (unictype/property-white-space, unictype/property-xid-continue,
> >   unictype/property-xid-start). I don't know if we can import those or
> >   if gcc already has these kind of UTF-8/unicode support functions for
> >   other languages?
> 
> At the time of writing the lexer, I was under the impression that Rust only
> supported UTF-8 in strings. The Rust Reference seems to have changed now to
> show that it supports UTF-8 in identifiers as well. I believe that the C++
> frontend, at least, has its own specific hardcoded UTF-8 handling for
> identifiers and strings (rather than using a library).
> 
> There could be issues with lookahead of several bytes (which the lexer uses
> liberally) if using UTF-8 in strings, depending on the exact implementation
> of whatever library you use (or function you write).

The whole source file should be valid UTF-8. You can use it in
comments too. And any invalid UTF-8 encoding means the file isn't a
valid Rust source file. So the simplest is to make the lexer handle
UTF-8 and handle one codepoint (UCS4/32bits) at a time. Lookahead then
also simply works per codepoint. We would still store strings as
UTF-8. gnulib contains various helpers to convert to/from utf-8/ucs4
and to test various unicode properties of codepoints. I'll ask on the
gcc mailinglist whether to use the C++ frontend support or import the
gnulib helpers.

> >> - rust-macro-expand tries to handle both macros and attributes, is
> >>  this by design?  Should we handle different passes for different
> >>  (inert or not) attributes that run before or after macro expansion?
> > As for macro and cfg expansion Joel some stuff already in place but i do
> > think they need to be separated into distinct passes which would be a
> > good first start with the expand folder.
> 
> That is a good question. Technically, rust-macro-expand only handles cfg
> expansion at the moment. You can read and discuss more about that here:
> https://github.com/Rust-GCC/gccrs/issues/563

I have to think about whether it makes sense to handle the cfg
attribute and the !cfg macro rules in hte same pass/expansion. The
!cfg macro seems so simple it could be handled immediately by the
parser since it only relies on the compiler/host attributes and simply
generates a true or false token.

In general it seems attribute expansion cannot be simply done by one
AttributeVisitor pass because the effect can be at different stages of
parsing (and they can even affect what the lexer accepts -
e.g. whether identifiers as unicode strings are accepted). For example
the various lint attributes can warn/error/etc when lowering the final
AST (CamelCaseStructs for example), after type checking or after
lifeness analysis. So maybe we need to design a pass for each
different attribute and not try to combine them (except maybe to
recognize and validate the attribute syntax).

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


rust frontend and UTF-8/unicode processing/properties

2021-07-18 Thread Mark Wielaard
Hi,

For the gcc rust frontend I was thinking of importing a couple of
gnulib modules to help with UTF-8 processing, conversion to/from
unicode codepoints and determining various properties of those
codepoints. But it seems gcc doesn't yet have any gnulib modules
imported, and maybe other frontends already have helpers to this that
the gcc rust frontend could reuse.

Rust only accepts valid UTF-8 encoded source files, which may or may
not start with UTF-8 BOM character. Whitespace is any codepoint with
the Pattern_White_Space property. Identifiers can start with any
codepoint with the XID_start property plus zero or one codepoints with
XID_continue property. It isn't required, but highly desirable to
detect confusable identifiers according to tr39/Confusable_Detection.

Other names might be constraint to Alphabetic and/or Number categories
(Nd, Nl, No), textual types can only contain Unicode Scalar Values
(any Unicode codepoint except high-surrogate and low-surrogates),
strings in source code can contain unicode escapes (24 bit, up to 6
digits codepoints) but are internally stored as UTF-8 (and must not
encode any surrogates).

Do other gcc frontends handle any of the above already in a way that
might be reusable for other frontends?

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Fwd: New contributor tasks

2021-07-18 Thread Mark Wielaard
Hi Joel,

On Sat, Jul 17, 2021 at 10:25:48PM +0800, The Other wrote:
> >> - I noticed some expressions didn't parse because of what looks to me
> >>   operator precedence issues. e.g the following:
> >>
> >>   const S: usize = 64;
> >>
> >>   pub fn main ()
> >>   {
> >> let a:u8 = 1;
> >> let b:u8 = 2;
> >> let _c = S * a as usize + b as usize;
> >>   }
> >>
> >>   $ gcc/gccrs -Bgcc as.rs
> >>
> >>   as.rs:7:27: error: type param bounds (in TraitObjectType) are not
> >>   allowed as TypeNoBounds
> >> 7 |   let _c = S * a as usize + b as usize;
> >>   |   ^
> >>
> >>   How does one fix such operator precedence issues in the parser?
> 
> > Off the top of my head it looks as though the parse_type_cast_expr has a
> > FIXME for the precedence issue for it. The Pratt parser uses the notion
> > of binding powers to handle this and i think it needs to follow in a
> > similar style to the ::parse_expr piece.
> 
> Yes, this is probably a precedence issue. The actual issue is that while
> expressions have precedence, types (such as "usize", which is what is being
> parsed) do not, and greedily parse tokens like "+". Additionally, the
> interactions of types and expressions and precedence between them is
> something that I have no idea how to approach.
> I believe that this specific issue could be fixed by modifying the
> parse_type_no_bounds method - if instead of erroring when finding a plus,
> it simply returned (treating it like an expression would treat a semicolon,
> basically), then this would have the desired functionality. I don't believe
> that parse_type_no_bounds (TypeNoBounds do not have '+' in them) would ever
> be called in an instance where a Type (that allows bounds) is allowable, so
> this change should hopefully not cause any correct programs to parse
> incorrectly.

I think you are correct. The issue is that parse_type_no_bounds tries
to be helpful and greedily looks for a PLUS so it can produce an
error. Simply removing that case makes things parse.

Patch attached and also here:
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=as-type

This cannot be fully tested yet, because as Cast Expressions aren't
lowered from AST to HIR yet. I didn't get very far trying to lower the
CastExpr to HIR. This is what I came up with. But I didn't know how to
handle the type path yet.

diff --git a/gcc/rust/hir/rust-ast-lower-expr.h 
b/gcc/rust/hir/rust-ast-lower-expr.h
index 19ce8c2cf1f..96f6073cd86 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -405,6 +405,24 @@ public:
   expr.get_locus ());
   }
 
+  void visit (AST::TypeCastExpr &expr) override
+  {
+HIR::Expr *expr_to_cast_to
+  = ASTLoweringExpr::translate (expr.get_casted_expr ().get ());
+
+HIR::TypeNoBounds *type_to_cast_to
+  = nullptr; /* ... (expr._get_type_to_cast_to ().get ())); */
+
+auto crate_num = mappings->get_current_crate ();
+Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+  mappings->get_next_hir_id (crate_num),
+  UNKNOWN_LOCAL_DEFID);
+
+translated = new HIR::TypeCastExpr (
+  mapping, std::unique_ptr (expr_to_cast_to),
+  std::unique_ptr (type_to_cast_to), expr.get_locus ());
+  }
+
   /* Compound assignment expression is compiled away. */
   void visit (AST::CompoundAssignmentExpr &expr) override
   {

It does get us a little bit further into the type checker:

as2.rs:7:12: error: failed to type resolve expression
7 |   let _c = a as usize + b as usize;
  |^
as2.rs:7:25: error: failed to type resolve expression
7 |   let _c = a as usize + b as usize;


Cheers,

Mark>From 4c92de44cde1bdd8d0fcb8a19adafd529d6c759c Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Sun, 18 Jul 2021 22:12:20 +0200
Subject: [PATCH] Remove error handling in parse_type_no_bounds for PLUS token

parse_type_no_bounds tries to be helpful and greedily looks for a PLUS
token after having parsed a typepath so it can produce an error. But
that error breaks parsing expressions that contain "as" Cast
Expressions like "a as usize + b as usize". Drop the explicit error on
seeing a PLUS token and just return the type path parsed.
---
 gcc/rust/parse/rust-parse-impl.h | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..a0607926950 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -9996,13 +9996,6 @@ Parser::parse_type_no_bounds ()
    std::

Using unsafe blocks in let expressions

2021-07-21 Thread Mark Wielaard
Hi,

I wanted to use an unsafe block in a let expression, which wasn't
accepted. The attached patch implements this.

I did want to add a testcase, but I couldn't come up with a test that
is correct and passes the type checker. The following works, but is
not correctly typed:

pub fn main ()
{
  let mut num = 2;
  // let r1 = &num as *const i32;
  // let r1: *const i32 = #
  let r1 = #
  let r2 = unsafe { *r1 } + unsafe { *r1 };
  let r3 = num;
  num = 4;
  let r4 = num + unsafe { *r1 } * r3;
  let _eightteen = r2 + r3 + r4;
}

In this case r1 is a reference, not a raw pointer, so the code
shouldn't work, but it does. It does correctly add up to 18.

The two ways to make this code type correct don't work. The first
gives:

let_unsafe.rs:4:12: fatal error: Failed to lower expr: [&num as *const i32]
4 |   let r1 = &num as *const i32;
  |^

The second gives:

let_unsafe.rs:7:21: error: expected reference type got * const i32
7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
  | ^
let_unsafe.rs:7:21: error: failed to type resolve expression
let_unsafe.rs:7:38: error: expected reference type got * const i32
7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
  |  ^
let_unsafe.rs:7:38: error: failed to type resolve expression
let_unsafe.rs:7:18: error: cannot apply this operator to types  
and 
7 |   let r2 = unsafe { *r1 } + unsafe { *r1 };
  |  ^~  

Note that the error marker is wrong on the last line. I think that is
because of the way the pratt parser eats the token and then the code
does a locus - 1. Which ends up at the wrong place. I think instead of
a boolean we should pass the current token to get the correct
location.

Cheers,

Mark>From 3e9c4eff383cd1a23a148f5a7d556345b7972e26 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Wed, 21 Jul 2021 22:41:04 +0200
Subject: [PATCH] unsafe blocks can be used in expressions

To use an unsafe block expression handle it in null_denotation for the
pratt parser. Adjust parse_unsafe_block_expr to take a pratt_parse
bool that defaults to false.
---
 gcc/rust/parse/rust-parse-impl.h | 15 ---
 gcc/rust/parse/rust-parse.h  |  5 +++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..f75dd206963 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -8704,10 +8704,17 @@ Parser::parse_async_block_expr (AST::AttrVec outer_attrs)
 // Parses an unsafe block expression.
 template 
 std::unique_ptr
-Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs)
+Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs,
+		 bool pratt_parse)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (UNSAFE);
+  Location locus;
+  if (!pratt_parse)
+{
+  Location locus = lexer.peek_token ()->get_locus ();
+  skip_token (UNSAFE);
+}
+  else
+locus = lexer.peek_token ()->get_locus () - 1;
 
   // parse block expression (required)
   std::unique_ptr block_expr = parse_block_expr ();
@@ -12823,6 +12830,8 @@ Parser::null_denotation (const_TokenPtr tok,
 case LEFT_SQUARE:
   // array definition expr (not indexing)
   return parse_array_expr (std::move (outer_attrs), true);
+case UNSAFE:
+  return parse_unsafe_block_expr (std::move (outer_attrs), true);
 default:
   if (!restrictions.expr_can_be_null)
 	add_error (Error (tok->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 1cd85eae8c2..1c7bd781b3f 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -504,8 +504,6 @@ private:
   AST::LoopLabel parse_loop_label ();
   std::unique_ptr
   parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
-  std::unique_ptr
-  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
   std::unique_ptr parse_grouped_expr (AST::AttrVec outer_attrs
 			= AST::AttrVec ());
   std::unique_ptr parse_closure_expr (AST::AttrVec outer_attrs
@@ -522,6 +520,9 @@ private:
   std::unique_ptr
   parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
 		   bool pratt_parse = false);
+  std::unique_ptr
+  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+			   bool pratt_parse = false);
   std::unique_ptr parse_array_expr (AST::AttrVec outer_attrs
 		= AST::AttrVec (),
 		bool pratt_parse = false);
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Using unsafe blocks in let expressions

2021-07-21 Thread Mark Wielaard
On Wed, Jul 21, 2021 at 11:09:38PM +0200, Mark Wielaard wrote:
> +  Location locus;
> +  if (!pratt_parse)
> +{
> +  Location locus = lexer.peek_token ()->get_locus ();

Oops, shadowed locus.  Fixed patch attached, and also at
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=let-unsafe


>From a7329b7fc0190920a9cf8bec77e34f2866b8af94 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Wed, 21 Jul 2021 22:41:04 +0200
Subject: [PATCH] unsafe blocks can be used in expressions

To use an unsafe block expression handle it in null_denotation for the
pratt parser. Adjust parse_unsafe_block_expr to take a pratt_parse
bool that defaults to false.
---
 gcc/rust/parse/rust-parse-impl.h | 15 ---
 gcc/rust/parse/rust-parse.h  |  5 +++--
 2 files changed, 15 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eedc76db43e..bdf1e09a029 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -8704,10 +8704,17 @@ Parser::parse_async_block_expr (AST::AttrVec outer_attrs)
 // Parses an unsafe block expression.
 template 
 std::unique_ptr
-Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs)
+Parser::parse_unsafe_block_expr (AST::AttrVec outer_attrs,
+		 bool pratt_parse)
 {
-  Location locus = lexer.peek_token ()->get_locus ();
-  skip_token (UNSAFE);
+  Location locus;
+  if (!pratt_parse)
+{
+  locus = lexer.peek_token ()->get_locus ();
+  skip_token (UNSAFE);
+}
+  else
+locus = lexer.peek_token ()->get_locus () - 1;
 
   // parse block expression (required)
   std::unique_ptr block_expr = parse_block_expr ();
@@ -12823,6 +12830,8 @@ Parser::null_denotation (const_TokenPtr tok,
 case LEFT_SQUARE:
   // array definition expr (not indexing)
   return parse_array_expr (std::move (outer_attrs), true);
+case UNSAFE:
+  return parse_unsafe_block_expr (std::move (outer_attrs), true);
 default:
   if (!restrictions.expr_can_be_null)
 	add_error (Error (tok->get_locus (),
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 1cd85eae8c2..1c7bd781b3f 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -504,8 +504,6 @@ private:
   AST::LoopLabel parse_loop_label ();
   std::unique_ptr
   parse_async_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
-  std::unique_ptr
-  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec ());
   std::unique_ptr parse_grouped_expr (AST::AttrVec outer_attrs
 			= AST::AttrVec ());
   std::unique_ptr parse_closure_expr (AST::AttrVec outer_attrs
@@ -522,6 +520,9 @@ private:
   std::unique_ptr
   parse_continue_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
 		   bool pratt_parse = false);
+  std::unique_ptr
+  parse_unsafe_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
+			   bool pratt_parse = false);
   std::unique_ptr parse_array_expr (AST::AttrVec outer_attrs
 		= AST::AttrVec (),
 		bool pratt_parse = false);
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


union support

2021-07-22 Thread Mark Wielaard
Hi,

I have been playing with union support which was mostly missing. union
is slightly odd because it is a weak keyword, so it can be used as a
"normal" identifier and is only special when defining a union
type. Which means you can have programs like:

union union { union: u32, funion: f32 }
pub fn main ()
{
  let union = union { union: 1 };
  let _u = unsafe { union.union };
  let _f = unsafe { union.funion; };
}

Here are two patches to support the above (partially).
Also on https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=union

The first fixes up the parser and should be good to go.
[PATCH 1/2] Better union support in the parser

The second provides lowering to HIR and type checking support.  This
is mostly cargo culting existing code for structs and tuple struct. It
seems to work, but I cannot say I fully understand what I am doing.
[PATCH 2/2] WIP union hir-lowering and type support

Currently this will eventually crash when trying to generate code in
Gcc_backend::constructor_expression because we try to emit code for a
struct with multiple fields, but the union doesn't have real fields,
just multiple variants.

Hopefully this is somewhat useful. Feedback on how to proceed and/or
how to get a better design (it seems a good idea to treat a union as
much as possible as a struct/tuple variant, but maybe there is a
better way) is very welcome.

Thanks,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/2] Better union support in the parser

2021-07-22 Thread Mark Wielaard
union is a weak keyword which means it isn't reserved and can be used
as a generic identifier. When we see an identifier where a union could
be declared we check whether the identifier is "union", but only when
the next token is also an identifier. In parse_union we shouldn't skip
the first identifier token, because it is already skipped when we call
expect_token.
---
 gcc/rust/parse/rust-parse-impl.h | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index bdf1e09a029..3996ef21672 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1083,7 +1083,8 @@ 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 () == "union"
+ && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  return parse_vis_item (std::move (outer_attrs));
  // or should this go straight to parsing union?
@@ -1274,8 +1275,8 @@ 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:
-  // TODO: ensure std::string and literal comparison works
-  if (t->get_str () == "union")
+  if (t->get_str () == "union"
+ && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  return parse_union (std::move (vis), std::move (outer_attrs));
  // or should item switch go straight to parsing union?
@@ -4524,7 +4525,6 @@ Parser::parse_union (AST::Visibility 
vis,
   const_TokenPtr union_keyword = expect_token (IDENTIFIER);
   rust_assert (union_keyword->get_str () == "union");
   Location locus = union_keyword->get_locus ();
-  lexer.skip_token ();
 
   // parse actual union name
   const_TokenPtr union_name_tok = expect_token (IDENTIFIER);
@@ -6054,8 +6054,8 @@ Parser::parse_stmt ()
   break;
 // 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 () == "union"
+ && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  return parse_vis_item (std::move (outer_attrs));
  // or should this go straight to parsing union?
@@ -11674,8 +11674,8 @@ 
Parser::parse_stmt_or_expr_without_block ()
   }
 // 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 () == "union"
+ && lexer.peek_token (1)->get_id () == IDENTIFIER)
{
  std::unique_ptr item (
parse_vis_item (std::move (outer_attrs)));
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 2/2] WIP union hir-lowering and type support

2021-07-22 Thread Mark Wielaard
Treat a union as a Struct variant like a tuple struct.  Add an
iterator and get_identifier functions to the AST Union class.  Same
for the HIR Union class, plus a get_generics_params method. Add a
get_is_union method tot the ADTType.
---
 gcc/rust/ast/rust-item.h  | 11 
 gcc/rust/hir/rust-ast-lower-item.h| 51 +
 gcc/rust/hir/rust-ast-lower-stmt.h| 53 ++
 gcc/rust/hir/tree/rust-hir-item.h | 16 ++
 gcc/rust/resolve/rust-ast-resolve-item.h  | 22 
 gcc/rust/resolve/rust-ast-resolve-stmt.h  | 32 +++
 gcc/rust/resolve/rust-ast-resolve-toplevel.h  | 14 +
 gcc/rust/typecheck/rust-hir-type-check-stmt.h | 55 ++-
 .../typecheck/rust-hir-type-check-toplevel.h  | 54 +-
 gcc/rust/typecheck/rust-hir-type-check.cc | 12 +++-
 gcc/rust/typecheck/rust-tycheck-dump.h|  6 ++
 gcc/rust/typecheck/rust-tyty.cc   |  4 +-
 gcc/rust/typecheck/rust-tyty.h| 12 ++--
 13 files changed, 331 insertions(+), 11 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 30cab0ed900..1e928e8111a 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -2489,6 +2489,15 @@ public:
   std::vector &get_variants () { return variants; }
   const std::vector &get_variants () const { return variants; }
 
+  void iterate (std::function cb)
+  {
+for (auto &variant : variants)
+  {
+   if (!cb (variant))
+ return;
+  }
+  }
+
   std::vector > &get_generic_params ()
   {
 return generic_params;
@@ -2505,6 +2514,8 @@ public:
 return where_clause;
   }
 
+  Identifier get_identifier () const { return union_name; }
+
 protected:
   /* Use covariance to implement clone function as returning this object
* rather than base */
diff --git a/gcc/rust/hir/rust-ast-lower-item.h 
b/gcc/rust/hir/rust-ast-lower-item.h
index 5ba59183179..b6af00f6b54 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -192,6 +192,57 @@ public:
   struct_decl.get_locus ());
   }
 
+  void visit (AST::Union &union_decl) override
+  {
+std::vector > generic_params;
+if (union_decl.has_generics ())
+  {
+   generic_params
+ = lower_generic_params (union_decl.get_generic_params ());
+  }
+
+std::vector > where_clause_items;
+HIR::WhereClause where_clause (std::move (where_clause_items));
+HIR::Visibility vis = HIR::Visibility::create_public ();
+
+std::vector variants;
+union_decl.iterate ([&] (AST::StructField &variant) mutable -> bool {
+  HIR::Visibility vis = HIR::Visibility::create_public ();
+  HIR::Type *type
+   = ASTLoweringType::translate (variant.get_field_type ().get ());
+
+  auto crate_num = mappings->get_current_crate ();
+  Analysis::NodeMapping mapping (crate_num, variant.get_node_id (),
+mappings->get_next_hir_id (crate_num),
+mappings->get_next_localdef_id (
+  crate_num));
+
+  HIR::StructField translated_variant (mapping, variant.get_field_name (),
+  std::unique_ptr (type),
+  vis, variant.get_locus (),
+  variant.get_outer_attrs ());
+  variants.push_back (std::move (translated_variant));
+  return true;
+});
+
+auto crate_num = mappings->get_current_crate ();
+Analysis::NodeMapping mapping (crate_num, union_decl.get_node_id (),
+  mappings->get_next_hir_id (crate_num),
+  mappings->get_next_localdef_id (crate_num));
+
+translated
+  = new HIR::Union (mapping, union_decl.get_identifier (), vis,
+   std::move (generic_params), std::move (where_clause),
+   std::move (variants), union_decl.get_outer_attrs (),
+   union_decl.get_locus ());
+
+mappings->insert_defid_mapping (mapping.get_defid (), translated);
+mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+  translated);
+mappings->insert_location (crate_num, mapping.get_hirid (),
+  union_decl.get_locus ());
+  }
+
   void visit (AST::StaticItem &var) override
   {
 HIR::Visibility vis = HIR::Visibility::create_public ();
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h 
b/gcc/rust/hir/rust-ast-lower-stmt.h
index 9df6b746bb7..2e97ca63a13 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -215,6 +215,59 @@ public:
   struct_decl.get_locus ());
   }
 
+  void visit (AST::Union &union_decl) override
+  {
+std::vector > generic_params;
+if (union_decl.has_generics ())
+

[PATCH] Support byte and byte string literals

2021-07-25 Thread Mark Wielaard
A byte literal is an u8 created as a ascii char or hex escape
e.g. b'X'.  A byte string literal is a string created from ascii or
hex chars. bytes are represented as u8 and byte strings as str (with
just ascii < 256 chars), but it should really be &'static [u8; n].
---
 gcc/rust/backend/rust-compile-expr.h  |  9 -
 gcc/rust/parse/rust-parse-impl.h  |  8 
 gcc/rust/rust-backend.h   |  3 +++
 gcc/rust/rust-gcc.cc  |  9 +
 gcc/rust/typecheck/rust-hir-type-check-expr.h | 19 +++
 .../rust/compile/torture/byte_char_str.rs |  8 
 6 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/byte_char_str.rs

diff --git a/gcc/rust/backend/rust-compile-expr.h 
b/gcc/rust/backend/rust-compile-expr.h
index dff4712e18e..fa6a53991ac 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -278,7 +278,14 @@ public:
}
return;
 
-   case HIR::Literal::STRING: {
+   case HIR::Literal::BYTE: {
+ char c = literal_value->as_string ().c_str ()[0];
+ translated = ctx->get_backend ()->char_constant_expression (c);
+   }
+   return;
+
+  case HIR::Literal::STRING:
+   case HIR::Literal::BYTE_STRING: {
  auto base = ctx->get_backend ()->string_constant_expression (
literal_value->as_string ());
  translated
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index be261715c6c..73600d22d60 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -12545,10 +12545,18 @@ Parser::null_denotation 
(const_TokenPtr tok,
   return std::unique_ptr (
new AST::LiteralExpr (tok->get_str (), AST::Literal::STRING,
  tok->get_type_hint (), {}, tok->get_locus ()));
+case BYTE_STRING_LITERAL:
+  return std::unique_ptr (
+   new AST::LiteralExpr (tok->get_str (), AST::Literal::BYTE_STRING,
+ tok->get_type_hint (), {}, tok->get_locus ()));
 case CHAR_LITERAL:
   return std::unique_ptr (
new AST::LiteralExpr (tok->get_str (), AST::Literal::CHAR,
  tok->get_type_hint (), {}, tok->get_locus ()));
+case BYTE_CHAR_LITERAL:
+  return std::unique_ptr (
+   new AST::LiteralExpr (tok->get_str (), AST::Literal::BYTE,
+ tok->get_type_hint (), {}, tok->get_locus ()));
 case TRUE_LITERAL:
   return std::unique_ptr (
new AST::LiteralExpr ("true", AST::Literal::BOOL, tok->get_type_hint (),
diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 35271b60f43..1dd4aba12ca 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -331,6 +331,9 @@ public:
   // Return an expression for the string value VAL.
   virtual Bexpression *string_constant_expression (const std::string &val) = 0;
 
+  // Get a char literal
+  virtual Bexpression *char_constant_expression (char c) = 0;
+
   // Get a char literal
   virtual Bexpression *wchar_constant_expression (wchar_t c) = 0;
 
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 74a8b5221f1..23a91ad9bcb 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -333,6 +333,8 @@ public:
 
   Bexpression *wchar_constant_expression (wchar_t c);
 
+  Bexpression *char_constant_expression (char c);
+
   Bexpression *boolean_constant_expression (bool val);
 
   Bexpression *real_part_expression (Bexpression *bcomplex, Location);
@@ -1557,6 +1559,13 @@ Gcc_backend::wchar_constant_expression (wchar_t c)
   return this->make_expression (ret);
 }
 
+Bexpression *
+Gcc_backend::char_constant_expression (char c)
+{
+  tree ret = build_int_cst (this->char_type ()->get_tree (), c);
+  return this->make_expression (ret);
+}
+
 // Make a constant boolean expression.
 
 Bexpression *
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 166535acba0..6e5b2312f50 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -542,6 +542,12 @@ public:
}
break;
 
+   case HIR::Literal::LitType::BYTE: {
+ auto ok = context->lookup_builtin ("u8", &infered);
+ rust_assert (ok);
+   }
+   break;
+
case HIR::Literal::LitType::STRING: {
  TyTy::BaseType *base = nullptr;
  auto ok = context->lookup_builtin ("str", &base);
@@ -553,6 +559,19 @@ public:
}
break;
 
+   case HIR::Literal::LitType::BYTE_STRING: {
+ /* We just treat this as a string, but it really is an arraytype of
+u8. It isn't in UTF-8, but really just a byte array.  */
+ TyTy::BaseType *base = nullptr;
+ auto ok = context->lookup_builtin ("str", &base);
+ rust_assert (ok);
+
+ infered
+ 

[PATCH] Support RangeFrom ([x..]) and RangeFromTo ([x..y]) in the parser

2021-07-25 Thread Mark Wielaard
Parsing the .. (DOT_DOT) operator to get a range had two
issues. Trying to compile:

  let block = [1,2,3,4,5];
  let _rf = &block[1..];
  let _rt = &block[..3];
  let _rft = &block[2..4];

range.rs:4:23: error: found unexpected token ‘]’ in null denotation
4 |   let _rf = &block[1..];
  |   ^
range.rs:4:24: error: expecting ‘]’ but ‘;’ found
4 |   let _rf = &block[1..];
  |^

Since .. can represent either a range from or a range from-to it can
be followed by an expression or not. We do have a hack in our
pratt-parser so that it is allowed to return a nullptr. But even in
that case it will have swallowed the next token. Add another hack to
the pratt-parser so that if the next token is one that cannot start an
expression and the caller allows a nullptr return then don't skip the
token and return immediately.

After this patch we can parse the above range expressions, but we
still don't handle them fully:

range.rs:4:20: fatal error: Failed to lower expr: [1..]
4 |   let _rf = &block[1..];
  |^

Ranges are actually syntactic sugar for std::ops::Range[From|To].
---
 gcc/rust/parse/rust-parse-impl.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index be261715c6c..7b128fff157 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -12348,6 +12348,18 @@ Parser::parse_expr (int 
right_binding_power,
ParseRestrictions restrictions)
 {
   const_TokenPtr current_token = lexer.peek_token ();
+  // Special hack because we are allowed to return nullptr, in that case we
+  // don't want to skip the token, since we don't actually parse it. But if
+  // null isn't allowed it indicates an error, and we want to skip past that.
+  // So return early if it is one of the tokens that ends an expression
+  // (or at least cannot start a new expression).
+  if (restrictions.expr_can_be_null)
+{
+  TokenId id = current_token->get_id ();
+  if (id == SEMICOLON || id == RIGHT_PAREN || id == RIGHT_CURLY
+ || id == RIGHT_SQUARE)
+   return nullptr;
+}
   lexer.skip_token ();
 
   // parse null denotation (unary part of expression)
@@ -14028,6 +14040,9 @@ 
Parser::parse_led_range_exclusive_expr (
 {
   // FIXME: this probably parses expressions accidently or whatever
   // try parsing RHS (as tok has already been consumed in parse_expression)
+  // Can be nullptr, in which case it is a RangeFromExpr, otherwise a
+  // RangeFromToExpr.
+  restrictions.expr_can_be_null = true;
   std::unique_ptr right
 = parse_expr (LBP_DOT_DOT, AST::AttrVec (), restrictions);
 
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-07-28 Thread Mark Wielaard
The pratt parser skips the first token of an expression before
invoking the actual expression parsing function. This makes getting
the correct starting location of a pratt parsed expression hard. The
"correction" of the location by subtracting an integer is often wrong
(since there may be arbitrary whitespace or comments between
tokens). Fix this by passing the token to the expression parsing
functions (instead of just providing a pratt_parse boolean). Use this
token to set the start of the expression.

Before gccrs would generate the following error message:

return.rs:3:22: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  |  ^

Now we get:

return.rs:3:17: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  | ^
---
 gcc/rust/parse/rust-parse-impl.h | 180 +--
 gcc/rust/parse/rust-parse.h  |  58 +-
 2 files changed, 103 insertions(+), 135 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 340fea70201..6241a972ff7 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6580,7 +6580,7 @@ Parser::parse_path_expr_segment ()
 template 
 AST::QualifiedPathInExpression
 Parser::parse_qualified_path_in_expression (
-  bool pratt_parse)
+  const_TokenPtr pratt_parsed_token)
 {
   /* Note: the Rust grammar is defined in such a way that it is impossible to
* determine whether a prospective qualified path is a
@@ -6595,7 +6595,7 @@ 
Parser::parse_qualified_path_in_expression (
 
   // parse the qualified path type (required)
   AST::QualifiedPathType qual_path_type
-= parse_qualified_path_type (pratt_parse);
+= parse_qualified_path_type (pratt_parsed_token);
   if (qual_path_type.is_error ())
 {
   // TODO: should this create a parse error?
@@ -6661,12 +6661,13 @@ 
Parser::parse_qualified_path_in_expression (
 // Parses the type syntactical construction at the start of a qualified path.
 template 
 AST::QualifiedPathType
-Parser::parse_qualified_path_type (bool pratt_parse)
+Parser::parse_qualified_path_type (
+  const_TokenPtr pratt_parsed_token)
 {
-  Location locus = Linemap::unknown_location ();
+  Location locus;
   /* TODO: should this actually be error? is there anywhere where this could be
* valid? */
-  if (!pratt_parse)
+  if (pratt_parsed_token == nullptr)
 {
   locus = lexer.peek_token ()->get_locus ();
   if (!skip_token (LEFT_ANGLE))
@@ -6676,10 +6677,7 @@ Parser::parse_qualified_path_type 
(bool pratt_parse)
}
 }
   else
-{
-  // move back by 1 if pratt parsing due to skipping '<'
-  locus = lexer.peek_token ()->get_locus () - 1;
-}
+locus = pratt_parsed_token->get_locus ();
 
   // parse type (required)
   std::unique_ptr type = parse_type ();
@@ -7305,10 +7303,10 @@ Parser::parse_expr_without_block 
(AST::AttrVec outer_attrs)
 template 
 std::unique_ptr
 Parser::parse_block_expr (AST::AttrVec outer_attrs,
- bool pratt_parse)
+ const_TokenPtr pratt_parsed_token)
 {
-  Location locus = Linemap::unknown_location ();
-  if (!pratt_parse)
+  Location locus;
+  if (pratt_parsed_token == nullptr)
 {
   locus = lexer.peek_token ()->get_locus ();
   if (!skip_token (LEFT_CURLY))
@@ -7318,9 +7316,7 @@ Parser::parse_block_expr 
(AST::AttrVec outer_attrs,
}
 }
   else
-{
-  locus = lexer.peek_token ()->get_locus () - 1;
-}
+locus = pratt_parsed_token->get_locus ();
 
   AST::AttrVec inner_attrs = parse_inner_attributes ();
 
@@ -7611,22 +7607,17 @@ Parser::parse_literal_expr 
(AST::AttrVec outer_attrs)
 // Parses a return expression (including any expression to return).
 template 
 std::unique_ptr
-Parser::parse_return_expr (AST::AttrVec outer_attrs,
-  bool pratt_parse)
+Parser::parse_return_expr (
+  AST::AttrVec outer_attrs, const_TokenPtr pratt_parsed_token)
 {
-  Location locus = Linemap::unknown_location ();
-  if (!pratt_parse)
+  Location locus;
+  if (pratt_parsed_token == nullptr)
 {
   locus = lexer.peek_token ()->get_locus ();
-
   skip_token (RETURN_TOK);
 }
   else
-{
-  // minus 7 chars for 6 in return and a space
-  // or just TODO: pass in location data
-  locus = lexer.peek_token ()->get_locus () - 7;
-}
+locus = pratt_parsed_token->get_locus ();
 
   // parse expression to return, if it exists
   ParseRestrictions restrictions;
@@ -7644,21 +7635,16 @@ Parser::parse_return_expr 
(AST::AttrVec outer_attrs,
 template 
 std::unique_ptr
 Parser::parse_break_expr (AST::AttrVec outer_attrs,
- bool pratt_parse)
+ const_TokenPtr pratt_parsed_token)
 {
-  Location locus = Linemap::unknown

Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-07-29 Thread Mark Wielaard
Hi Joel,

On Thu, 2021-07-29 at 09:25 +0800, The Other via Gcc-rust wrote:
> I think the core idea of this patch (fixing locations) is very
> important and useful.
> 
> But isn’t it overkill to pass the token in instead of just the
> location? You can avoid a fairly expensive shared_ptr copy by doing
> so. 

I hadn't even noticed it was a smart pointer. At least the abstraction
works transparently. My idea was that the code might want to double
check/assert it was the correct token (as it does in the case the
parser function is called directly and it has to consume the first
token itself).

But yes, things might be even simpler by passing the location directly.
I'll try to rewrite the code tonight to pass a location and see how
that looks.

Thanks,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-07-29 Thread Mark Wielaard
Hi,

On Thu, Jul 29, 2021 at 05:18:50PM +0200, Thomas Schwinge wrote:
> On 2021-07-29T12:55:38+0200, Mark Wielaard  wrote:
> > On Thu, 2021-07-29 at 09:25 +0800, The Other via Gcc-rust wrote:
> >> But isn’t it overkill to pass the token in instead of just the
> >> location? You can avoid a fairly expensive shared_ptr copy by doing
> >> so.
> >
> > I hadn't even noticed it was a smart pointer. At least the abstraction
> > works transparently.
> 
> Wouldn't 'const_TokenPtr &pratt_parsed_token' work, passing a C++
> reference?  (Or am I missing some C++ "detail"; I haven't looked
> carefully.)

I think the issue is not the passing of the actual smart pointer, but
the construction in the default case. When we define the method
argument as const_TokenPtr pratt_parsed_token = nullptr we are
actually constructing a shared_ptr wrapper around the nullptr.

Of course in the case of passing a Location we also always have to
construct an object. But the Location class is very simple, so
hopefully it is cheaper to construct.

> > But yes, things might be even simpler by passing the location directly.
> > I'll try to rewrite the code tonight to pass a location and see how
> > that looks.

That variant is attached and can also be found here:
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-loc
The original is also here:
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token

Hopefully one of the two is acceptable. If not please let me know how
to rewrite it in a cheaper more idiomatic way.

Thanks,

Mark>From 2c51713eec25b38ab2274537103a391d89894dba Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Thu, 29 Jul 2021 00:00:55 +0200
Subject: [PATCH] Pass pratt parsed location to expr parser functions to fix
 expr locus
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The pratt parser skips the first token of an expression before
invoking the actual expression parsing function. This makes getting
the correct starting location of a pratt parsed expression hard. The
"correction" of the location by subtracting an integer is often wrong
(since there may be arbitrary whitespace or comments between
tokens). Fix this by passing the location of the skipped token to the
expression parsing functions (instead of just providing a pratt_parse
boolean). Use this location to set the start of the expression.

Before gccrs would generate the following error message:

return.rs:3:22: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  |  ^

Now we get:

return.rs:3:17: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  | ^
---
 gcc/rust/parse/rust-parse-impl.h | 177 +++
 gcc/rust/parse/rust-parse.h  |  63 ++-
 2 files changed, 95 insertions(+), 145 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 340fea70201..4b208f0da23 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6580,7 +6580,7 @@ Parser::parse_path_expr_segment ()
 template 
 AST::QualifiedPathInExpression
 Parser::parse_qualified_path_in_expression (
-  bool pratt_parse)
+  Location pratt_parsed_loc)
 {
   /* Note: the Rust grammar is defined in such a way that it is impossible to
* determine whether a prospective qualified path is a
@@ -6595,7 +6595,7 @@ Parser::parse_qualified_path_in_expression (
 
   // parse the qualified path type (required)
   AST::QualifiedPathType qual_path_type
-= parse_qualified_path_type (pratt_parse);
+= parse_qualified_path_type (pratt_parsed_loc);
   if (qual_path_type.is_error ())
 {
   // TODO: should this create a parse error?
@@ -6661,12 +6661,13 @@ Parser::parse_qualified_path_in_expression (
 // Parses the type syntactical construction at the start of a qualified path.
 template 
 AST::QualifiedPathType
-Parser::parse_qualified_path_type (bool pratt_parse)
+Parser::parse_qualified_path_type (
+  Location pratt_parsed_loc)
 {
-  Location locus = Linemap::unknown_location ();
+  Location locus = pratt_parsed_loc;
   /* TODO: should this actually be error? is there anywhere where this could be
* valid? */
-  if (!pratt_parse)
+  if (locus == Linemap::unknown_location ())
 {
   locus = lexer.peek_token ()->get_locus ();
   if (!skip_token (LEFT_ANGLE))
@@ -6675,11 +6676,6 @@ Parser::parse_qualified_path_type (bool pratt_parse)
 	  return AST::QualifiedPathType::create_error ();
 	}
 }
-  else
-{
-  // move back by 1 if pratt parsing due to skipping '<'
-  locus = lexer.peek_token ()->get_locus () - 1;
-}
 
   // parse type (required)
   std::unique_ptr type = parse_type ();
@@ 

Re: [PATCH 2/2] WIP union hir-lowering and type support

2021-08-01 Thread Mark Wielaard
Hi Philip,

On Fri, Jul 23, 2021 at 12:19:18PM +0100, Philip Herron wrote:
> On 23/07/2021 00:19, Mark Wielaard wrote:
> > Treat a union as a Struct variant like a tuple struct.  Add an
> > iterator and get_identifier functions to the AST Union class.  Same
> > for the HIR Union class, plus a get_generics_params method. Add a
> > get_is_union method tot the ADTType.
> > ---
> [...]
> Nice work Mark, I think this is nearly there. As far as i can tell there
> is potentially 1 change to make in the ADTType and 1 more change to the
> rust-gcc.cc backend stuff to finish it.

Turned out that there was a bit more work to make constructor
expressions (StructExprStruct) work correctly, but it seems the basics
for union support are ok now. Not every pass (type checking) seems to
handle unions yet though. See below.

> The ADTType is going to be used to represent not just structs and unions
> but also enums.
> https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
> has a field called flags which looks like a u32 bitfield to have
> IS_ENUM, IS_UNION etc it might make sense to turn your is_union flag
> into a bitmask now as part of this patch.

I did add a enum field to distinquish between regular structs, tuple
structs and unions. But I am not sure this abstraction is the easiest
to work with. We will see when we add enum support. structs and tuple
structs are fairly similar and unions and enums also, but they don't
easily combine imho. And if you are treating all abstract data types
the same, then why are tuples separate?

> The other missing piece is that we need to have another function in
> rust-gcc.cc to create the GCC's union_type_node since this will
> currently be creating a RECORD_TYPE at the moment.
> 
> https://github.com/Rust-GCC/gccrs/blob/44472c580cedd836081c82e621482e479a69729c/gcc/rust/rust-gcc.cc#L1085
> 
> I am slightly stuck though since I don't understand the difference
> between UNION_TYPE and QUAL_UNION_TYPE:
> https://github.com/Rust-GCC/gccrs/blob/master/gcc/tree.def#L216-L222

According to https://gcc.gnu.org/onlinedocs/gccint/Types.html
QUAL_UNION_TYPE is for Ada variant records. Which may be somewhat
similar to Rust enums, but Rust unions seem to be like UNION_TYPEs.

> When we are able to create the GCC union type we should be able to
> create an if statement over inside:
> https://github.com/Rust-GCC/gccrs/blob/44472c580cedd836081c82e621482e479a69729c/gcc/rust/backend/rust-compile-context.h#L415
> to call union_type or something similar instead of the struct_type.

I renamed fill_in_struct to fill_in_fields and handle structs
(RECORD_TYPE) and unions (UNION_TYPE) separately now.

The other thing I needed was to handle constructors in Gcc backend
constructor_expression differently for structs and unions. Unions only
initialize one field. For that I added a union_index to
StructExprStruct to indicate which whether the contructor is for a
union and which field (index) is being initialized. The
TypeCheckStructExpr visitor sets this (and also checks the constructor
only mentions one field and doesn't have a base expression for
unions).

I added two simple testcases to show the basic support for unions
works now. But there are a couple of things that don't work correctly
for unions yet. In particular when enabling warnings for the new
union.rs testcase you'll get:

$ gcc/gccrs -Bgcc -g union.rs 
union.rs:18:3: warning: field is never read: ‘f1’
   18 |   f1: U,
  |   ^
union.rs:19:3: warning: field is never read: ‘f2’
   19 |   f2: V
  |   ^

But those (union) fields in the struct are read. Similarly unused
union fields aren't detected.

And you cannot use unions as function arguments or return values.
This example (sorry for the funny naming, union isn't a keyword, so
you can call basically anything a union, including a union, a union
field, function argument, etc.) doesn't pass the type checker:

union union { union: u32, funion: f32 }

fn funion (union: &union) -> union
{
  let v = unsafe { union.union };
  union { union: v }
}

pub fn main ()
{
  let union = union { union: 1 };
  let u = unsafe { union.union };
  let f = unsafe { union.funion };
  let r = funion (&union);
  let _r3 = unsafe { r.union } + unsafe { union.union } + u;
  let _f2 = f + unsafe { r.funion };
}

$ gcc/gccrs -Bgcc -g fn_union.rs 
fn_union.rs:5:20: error: expected algebraic data type got: [& 
union{union:Uint:u32:(Ref: 20 TyRef: 3[3,]), funion:Float:f32:(Ref: 23 TyRef: 
12[12,])}]
5 |   let v = unsafe { union.union };
  |^
fn_union.rs:5:20: error: failed to type resolve expression
fn_union.rs:6:3: error: expected an ADT type for constructor
6 |   union { union: v }
  |   ^
fn_union.rs:3:1: error: expected [union{union:Uint:u32:(Ref: 20 TyRef: 3[3,]), 
funion:Float:f32:(Ref: 23 TyRef

Re: [PATCH 2/2] WIP union hir-lowering and type support

2021-08-01 Thread Mark Wielaard
On Sun, Aug 01, 2021 at 01:29:16PM +0200, Mark Wielaard wrote:
> I added two simple testcases to show the basic support for unions
> works now. But there are a couple of things that don't work correctly
> for unions yet. In particular when enabling warnings for the new
> union.rs testcase you'll get:
> 
> $ gcc/gccrs -Bgcc -g union.rs 
> union.rs:18:3: warning: field is never read: ‘f1’
>18 |   f1: U,
>   |   ^
> union.rs:19:3: warning: field is never read: ‘f2’
>19 |   f2: V
>   |   ^
> 
> But those (union) fields in the struct are read. Similarly unused
> union fields aren't detected.

This is why the testcase uses { dg-options "-w" } to suppress all
warnings.

Attached is a small followup patch to resolve two FIXMEs to add the
correct locus for the Union variant fields (the actual fixme was fixed
by Thomas Young in commit 6d7b87f9dd92 "make struct field carry the
location info"). But it was missing TupleField and (obviously)
Union variants since those weren't implemented yet.

Also on
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=tuple-union-field-locus

Cheers,

Mark>From cd67e5d5f138dbdff4ec859e4020e8091cb03aa7 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Mon, 2 Aug 2021 00:33:02 +0200
Subject: [PATCH] Add locus to TupleField and pass it and union variants to HIR
 class

TupleField was missing a Location field and we dropped to locus when
lowering Union fields to HIR.
---
 gcc/rust/ast/rust-item.h   | 16 ++--
 gcc/rust/hir/rust-ast-lower-item.h |  6 ++
 gcc/rust/hir/rust-ast-lower-stmt.h | 11 +++
 gcc/rust/parse/rust-parse-impl.h   |  4 +++-
 4 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 5605b0bb79c..6b0021a8b11 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -2002,9 +2002,10 @@ private:
 
   std::unique_ptr field_type;
 
-  // should this store location info?
   NodeId node_id;
 
+  Location locus;
+
 public:
   // Returns whether tuple field has outer attributes.
   bool has_outer_attributes () const { return !outer_attrs.empty (); }
@@ -2014,17 +2015,17 @@ public:
   bool has_visibility () const { return !visibility.is_error (); }
 
   // Complete constructor
-  TupleField (std::unique_ptr field_type, Visibility vis,
+  TupleField (std::unique_ptr field_type, Visibility vis, Location locus,
 	  std::vector outer_attrs = std::vector ())
 : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
   field_type (std::move (field_type)),
-  node_id (Analysis::Mappings::get ()->get_next_node_id ())
+  node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
   {}
 
   // Copy constructor with clone
   TupleField (TupleField const &other)
 : outer_attrs (other.outer_attrs), visibility (other.visibility),
-  node_id (other.node_id)
+  node_id (other.node_id), locus (other.locus)
   {
 // guard to prevent null dereference (only required if error)
 if (other.field_type != nullptr)
@@ -2039,6 +2040,7 @@ public:
 visibility = other.visibility;
 outer_attrs = other.outer_attrs;
 node_id = other.node_id;
+locus = other.locus;
 
 // guard to prevent null dereference (only required if error)
 if (other.field_type != nullptr)
@@ -2059,12 +2061,14 @@ public:
   // Creates an error state tuple field.
   static TupleField create_error ()
   {
-return TupleField (nullptr, Visibility::create_error ());
+return TupleField (nullptr, Visibility::create_error (), Location ());
   }
 
   std::string as_string () const;
 
-  NodeId get_node_id () const { return node_id; };
+  NodeId get_node_id () const { return node_id; }
+
+  Location get_locus () const { return locus; }
 
   // TODO: this mutable getter seems really dodgy. Think up better way.
   std::vector &get_outer_attrs () { return outer_attrs; }
diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h
index f168c7d3e88..d49d2b22bf0 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -111,12 +111,10 @@ public:
  mappings->get_next_localdef_id (
    crate_num));
 
-  // FIXME
-  // AST::TupleField is missing Location info
-  Location field_locus;
   HIR::TupleField translated_field (mapping,
 	std::unique_ptr (type), vis,
-	field_locus, field.get_outer_attrs ());
+	field.get_locus (),
+	field.get_outer_attrs ());
   fields.push_back (std::move (translated_field));
   return true;
 });
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h
index 2e97ca63a13..c4c00ac0bee 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -187,12 +187,10 @@ public:
  mappings->get_next_localdef_id (
    cr

[PATCH] Remove split-stack from backend

2021-08-03 Thread Mark Wielaard
The backend was derived from the go backend which enables split stack
support by default. This inserts a __morestack call at the start of
each function. This is not needed for the rust backend. Remove the
split stack support code from the rust backend and spec.
---
 gcc/rust/rust-backend.h | 12 ---
 gcc/rust/rust-gcc.cc|  5 -
 gcc/rust/rustspec.cc| 47 -
 3 files changed, 4 insertions(+), 60 deletions(-)

diff --git a/gcc/rust/rust-backend.h b/gcc/rust/rust-backend.h
index 4635796e953..1af76cfcc10 100644
--- a/gcc/rust/rust-backend.h
+++ b/gcc/rust/rust-backend.h
@@ -790,27 +790,23 @@ public:
   // recover and must be visible for correct panic recovery.
   static const unsigned int function_is_inlinable = 1 << 2;
 
-  // Set if the function may not split the stack.  This is set for the
-  // implementation of recover itself, among other things.
-  static const unsigned int function_no_split_stack = 1 << 3;
-
   // Set if the function does not return.  This is set for the
   // implementation of panic.
-  static const unsigned int function_does_not_return = 1 << 4;
+  static const unsigned int function_does_not_return = 1 << 3;
 
   // Set if the function should be put in a unique section if
   // possible.  This is used for field tracking.
-  static const unsigned int function_in_unique_section = 1 << 5;
+  static const unsigned int function_in_unique_section = 1 << 4;
 
   // Set if the function should be available for inlining in the
   // backend, but should not be emitted as a standalone function.  Any
   // call to the function that is not inlined should be treated as a
   // call to a function defined in a different compilation unit.  This
   // is like a C99 function marked inline but not extern.
-  static const unsigned int function_only_inline = 1 << 6;
+  static const unsigned int function_only_inline = 1 << 5;
 
   // const function
-  static const unsigned int function_read_only = 1 << 7;
+  static const unsigned int function_read_only = 1 << 6;
 
   // Declare or define a function of FNTYPE.
   // NAME is the Go name of the function.  ASM_NAME, if not the empty
diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc
index 3e47a7cba7a..5c37cea20da 100644
--- a/gcc/rust/rust-gcc.cc
+++ b/gcc/rust/rust-gcc.cc
@@ -3382,11 +3382,6 @@ Gcc_backend::function (Btype *fntype, const std::string 
&name,
 }
   if ((flags & function_is_inlinable) == 0)
 DECL_UNINLINABLE (decl) = 1;
-  if ((flags & function_no_split_stack) != 0)
-{
-  tree attr = get_identifier ("no_split_stack");
-  DECL_ATTRIBUTES (decl) = tree_cons (attr, NULL_TREE, NULL_TREE);
-}
   if ((flags & function_does_not_return) != 0)
 TREE_THIS_VOLATILE (decl) = 1;
   if ((flags & function_in_unique_section) != 0)
diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc
index 28c2d9a38fe..12ec874d222 100644
--- a/gcc/rust/rustspec.cc
+++ b/gcc/rust/rustspec.cc
@@ -104,9 +104,6 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
   /* The total number of arguments with the new stuff.  */
   int num_args = 1;
 
-  /* Supports split stack */
-  int supports_split_stack = 0;
-
   /* Whether the -o option was used.  */
   bool saw_opt_o = false;
 
@@ -118,11 +115,6 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
   /* Whether the -S option was used.  */
   bool saw_opt_S = false;
 
-#ifdef TARGET_CAN_SPLIT_STACK_64BIT
-  /* Whether the -m64 option is in force. */
-  bool is_m64 = TARGET_CAN_SPLIT_STACK_64BIT;
-#endif
-
   /* The first input file with an extension of .go.  */
   const char *first_go_file = NULL;
 
@@ -159,16 +151,6 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
library = (library == 0) ? 1 : library;
  break;
 
-#ifdef TARGET_CAN_SPLIT_STACK_64BIT
-   case OPT_m32:
- is_m64 = false;
- break;
-
-   case OPT_m64:
- is_m64 = true;
- break;
-#endif
-
case OPT_pg:
case OPT_p:
  saw_profile_flag = true;
@@ -253,23 +235,6 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
   /* Copy the 0th argument, i.e., the name of the program itself.  */
   new_decoded_options[j++] = decoded_options[i++];
 
-#ifdef TARGET_CAN_SPLIT_STACK
-  supports_split_stack = 1;
-#endif
-
-#ifdef TARGET_CAN_SPLIT_STACK_64BIT
-  if (is_m64)
-supports_split_stack = 1;
-#endif
-
-  /* If we are linking, pass -fsplit-stack if it is supported.  */
-  if ((library >= 0) && supports_split_stack)
-{
-  generate_option (OPT_fsplit_stack, NULL, 1, CL_DRIVER,
-  &new_decoded_options[j]);
-  j++;
-}
-
   /* NOTE: We start at 1 now, not 0.  */
   while (i < argc)
 {
@@ -402,18 +367,6 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
 generate_option (OPT_shared_libgcc, NULL, 1, CL_DRIVER,
 &new_decoded_options[j++]);
 
-  /* lib

[PATCH] Always check the result of expect_token while parsing

2021-08-03 Thread Mark Wielaard
When expect_token fails it produces an error and return a
nullptr. Make sure to always check the result of expect_token so we
don't use a nullptr token and crash.

Resolves: https://github.com/Rust-GCC/gccrs/issues/603
---
 gcc/rust/parse/rust-parse-impl.h | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 9eb212b4e72..acc9d06acd7 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -1898,6 +1898,9 @@ Parser::parse_macro_match_fragment ()
 
   // get MacroFragSpec for macro
   const_TokenPtr t = expect_token (IDENTIFIER);
+  if (t == nullptr)
+return nullptr;
+
   AST::MacroFragSpec frag = AST::get_frag_spec_from_str (t->get_str ());
   if (frag == AST::INVALID)
 {
@@ -4325,6 +4328,9 @@ Parser::parse_enum (AST::Visibility 
vis,
 
   // parse enum name
   const_TokenPtr enum_name_tok = expect_token (IDENTIFIER);
+  if (enum_name_tok == nullptr)
+return nullptr;
+
   Identifier enum_name = enum_name_tok->get_str ();
 
   // parse generic params (of enum container, not enum variants) if they exist
@@ -4650,6 +4656,9 @@ Parser::parse_static_item 
(AST::Visibility vis,
 }
 
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   if (!skip_token (COLON))
@@ -4700,6 +4709,9 @@ Parser::parse_trait (AST::Visibility 
vis,
 
   // parse trait name
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   // parse generic parameters (if they exist)
@@ -4805,6 +4817,9 @@ Parser::parse_trait_item ()
 
// parse function or method name
const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+   if (ident_tok == nullptr)
+ return nullptr;
+
Identifier ident = ident_tok->get_str ();
 
// parse generic params
@@ -4937,6 +4952,9 @@ Parser::parse_trait_type 
(AST::AttrVec outer_attrs)
   skip_token (TYPE);
 
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   std::vector> bounds;
@@ -4973,6 +4991,9 @@ Parser::parse_trait_const 
(AST::AttrVec outer_attrs)
 
   // parse constant item name
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   if (!skip_token (COLON))
@@ -5338,6 +5359,9 @@ 
Parser::parse_inherent_impl_function_or_method (
 
   // parse function or method name
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   // parse generic params
@@ -14210,6 +14234,9 @@ Parser::parse_field_access_expr (
   /* get field name identifier (assume that this is a field access expr and not
* await, for instance) */
   const_TokenPtr ident_tok = expect_token (IDENTIFIER);
+  if (ident_tok == nullptr)
+return nullptr;
+
   Identifier ident = ident_tok->get_str ();
 
   Location locus = struct_expr->get_locus_slow ();
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-08-04 Thread Mark Wielaard
Hi,

On Wed, Aug 04, 2021 at 03:15:00PM +, build...@builder.wildebeest.org wrote:
> The Buildbot has detected a new failure on builder gccrust-debian-arm64 while 
> building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/58/builds/270
> 
> Buildbot URL: https://builder.wildebeest.org/buildbot/
> 
> Worker for this Build: debian-arm64
> 
> Build Reason: 
> Blamelist: CohenArthur 
> 
> BUILD FAILED: failed compile (failure)

This commit (and the following 3) were really bad. They didn't build.
Apparently bors doesn't check commit individually, but the buildbot
does build every commit separately.

The tree is buildable again, but I think it would be good to not have
any commits that break the build.

Periodically broken trees make it also hard to bisect issues.

Is it possible to make bors check all commits in a series? Or can we
somehow connect the buildbot workers to the bors checks?

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH 2/2] WIP union hir-lowering and type support

2021-08-04 Thread Mark Wielaard
Hi,

On Sun, Aug 01, 2021 at 01:29:16PM +0200, Mark Wielaard wrote:
> And you cannot use unions as function arguments or return values.
> This example (sorry for the funny naming, union isn't a keyword, so
> you can call basically anything a union, including a union, a union
> field, function argument, etc.) doesn't pass the type checker:
> 
> union union { union: u32, funion: f32 }
> 
> fn funion (union: &union) -> union
> {
>   let v = unsafe { union.union };
>   union { union: v }
> }
> 
> pub fn main ()
> {
>   let union = union { union: 1 };
>   let u = unsafe { union.union };
>   let f = unsafe { union.funion };
>   let r = funion (&union);
>   let _r3 = unsafe { r.union } + unsafe { union.union } + u;
>   let _f2 = f + unsafe { r.funion };
> }
> 
> $ gcc/gccrs -Bgcc -g fn_union.rs 
> fn_union.rs:5:20: error: expected algebraic data type got: [& 
> union{union:Uint:u32:(Ref: 20 TyRef: 3[3,]), funion:Float:f32:(Ref: 23 TyRef: 
> 12[12,])}]
> 5 |   let v = unsafe { union.union };
>   |^
> fn_union.rs:5:20: error: failed to type resolve expression
> fn_union.rs:6:3: error: expected an ADT type for constructor
> 6 |   union { union: v }
>   |   ^
> fn_union.rs:3:1: error: expected [union{union:Uint:u32:(Ref: 20 TyRef: 
> 3[3,]), funion:Float:f32:(Ref: 23 TyRef: 12[12,])}] got []
> 3 | fn funion (union: &union) -> union
>   | ^~

This example might be slightly hard to read because it uses "union"
also as identifier for things that aren't unions (which is allowed
since union is a weak keyword). So here is a simpler hopefully more
clear example to show the issue:

union U
{
  v1: u64,
  v2: i8
}

fn f (u: &U) -> U
{
  let v = unsafe { u.v2 };
  U { v2: v }
}

pub fn main ()
{
  let u = U { v1: 356 };
  let r = f (u);
  let _v100 = unsafe { r.v1 };
}

$ gcc/gccrs -Bgcc -g union_call.rs 
union_call.rs:9:20: error: expected algebraic data type got: [& 
U{v1:Uint:u64:(Ref: 20 TyRef: 4[4,]), v2:Int:i8:(Ref: 23 TyRef: 6[6,])}]
9 |   let v = unsafe { u.v2 };
  |^
union_call.rs:9:20: error: failed to type resolve expression
union_call.rs:9:3: error: Failed to resolve IdentifierExpr type: ( v ([C: 0 
Nid: 42 Hid: 40]))
9 |   let v = unsafe { u.v2 };
  |   ^
union_call.rs:10:11: error: failed to type resolve expression
   10 |   U { v2: v }
  |   ^
union_call.rs:10:11: error: expected [i8] got []

I am a little lost where the typechecking goes wrong.
Could someone give me a hint?

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Modifying self

2021-08-04 Thread Mark Wielaard
Hi,

I am trying to get this program working:

extern "C" { fn abort (); }

pub struct H
{
  l: u32,
}

impl H
{
  fn p (&mut self) -> u32
  {
self.l -= 1;
self.l
  }
}

fn main ()
{
  let mut h = H { l: 11 }; 
  let eleven = h.l; 
  let ten = h.p (); 
  if ten + 1 != eleven { unsafe { abort (); } } 
  let h2 = H { l: ten }; 
  if h.l != h2.l { unsafe { abort (); } } 
}

This doesn't currently compile:

$ gcc/gccrs -Bgcc -g p.rs 
p.rs:12:5: error: invalid left-hand side of assignment
   12 | self.l -= 1;
  | ^

But this isn't too hard to solve:

diff --git a/gcc/rust/resolve/rust-ast-verify-assignee.h 
b/gcc/rust/resolve/rust-ast-verify-assignee.h
index aed01196f81..1e8988d47df 100644
--- a/gcc/rust/resolve/rust-ast-verify-assignee.h
+++ b/gcc/rust/resolve/rust-ast-verify-assignee.h
@@ -75,6 +75,13 @@ public:
   }
   }
 
+  void visit (AST::PathInExpression &path) override
+  {
+/* XXX do we need to check self is mutable? How?  */
+if (path.as_string () == "self")
+  ok = true;
+  }
+
 private:
   VerifyAsignee (NodeId parent) : ResolverBase (parent), ok (false) {}
 
I am not sure whether this is a good implementation of the
VerifyAsignee visitor for a PathInExpression. What exactly is the goal
of this visitor?

But with the above simple fix, it compiles! And it actually seems to
mostly work. The implementation method is called, it gets its own
field, substracts the value and correctly returns it!

But... then it still aborts on the second check.  The method was
supposed to adjust the given self (H), but it is not given a mutable
reference, it gets a copy...

On irc Philip suggested this is probably
https://github.com/Rust-GCC/gccrs/issues/241

But I must admit I don't fully understand what really needs to be done
here or if the fact that this is a &mut self makes it different from a
&self argument.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-08-05 Thread Mark Wielaard
Hi,

On Fri, Jul 30, 2021 at 03:03:13AM +0200, Mark Wielaard wrote:
> That variant is attached and can also be found here:
> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-loc
> The original is also here:
> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token
> 
> Hopefully one of the two is acceptable. If not please let me know how
> to rewrite it in a cheaper more idiomatic way.

Any feedback on these patches? I really like to get the locations
correct for these pratt parsed expressions. If both variants are
problematic please let me know what I can do to improve them.

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] More rustspec.cc cleanups

2021-08-05 Thread Mark Wielaard
rustspec.cc was based on the Go frontend gospec.cc. Remove special
handling of math and pthread libraries and profiling option. Handle
.rs files instead of .go files. Keep support for linking with (static)
librust which is currently commented out. Add generic static-librust
option to common.opt.
---
 gcc/common.opt  |   4 ++
 gcc/rust/config-lang.in |   2 +-
 gcc/rust/rustspec.cc| 146 
 3 files changed, 32 insertions(+), 120 deletions(-)

diff --git a/gcc/common.opt b/gcc/common.opt
index c75dd36843e..820de1f41b0 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -3449,6 +3449,10 @@ static-libgo
 Driver
 ; Documented for Go, but always accepted by driver.
 
+static-librust
+Driver
+; Documented for Rust, but always accepted by driver.
+
 static-libasan
 Driver
 
diff --git a/gcc/rust/config-lang.in b/gcc/rust/config-lang.in
index c50b72153c2..1d61d2afc6b 100644
--- a/gcc/rust/config-lang.in
+++ b/gcc/rust/config-lang.in
@@ -1,4 +1,4 @@
-# config-lang.in -- Top level configure fragment for gcc Go frontend.
+# config-lang.in -- Top level configure fragment for gcc Rust frontend.
 
 # Copyright (C) 2009-2019 Free Software Foundation, Inc.
 
diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc
index 12ec874d222..806514a9d94 100644
--- a/gcc/rust/rustspec.cc
+++ b/gcc/rust/rustspec.cc
@@ -1,4 +1,4 @@
-/* rustspec.c -- Specific flags and argument handling of the gcc Go front end.
+/* rustspec.c -- Specific flags and argument handling of the gcc Rust front 
end.
Copyright (C) 2009-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -28,24 +28,10 @@ along with GCC; see the file COPYING3.  If not see
 
 /* This bit is set if we saw a `-xfoo' language specification.  */
 #define LANGSPEC (1 << 1)
-/* This bit is set if they did `-lm' or `-lmath'.  */
-#define MATHLIB (1 << 2)
-/* This bit is set if they did `-lpthread'.  */
-#define THREADLIB (1 << 3)
 /* This bit is set if they did `-lc'.  */
-#define WITHLIBC (1 << 4)
+#define WITHLIBC (1 << 2)
 /* Skip this option.  */
-#define SKIPOPT (1 << 5)
-
-#ifndef MATH_LIBRARY
-#define MATH_LIBRARY "m"
-#endif
-#ifndef MATH_LIBRARY_PROFILE
-#define MATH_LIBRARY_PROFILE MATH_LIBRARY
-#endif
-
-#define THREAD_LIBRARY "pthread"
-#define THREAD_LIBRARY_PROFILE THREAD_LIBRARY
+#define SKIPOPT (1 << 3)
 
 void
 lang_specific_driver (struct cl_decoded_option **in_decoded_options,
@@ -54,38 +40,23 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
 {
   unsigned int i, j;
 
-  /* If true, the user gave us the `-p' or `-pg' flag.  */
-  bool saw_profile_flag = false;
-
   /* This is a tristate:
- -1 means we should not link in libgo
- 0  means we should link in libgo if it is needed
- 1  means libgo is needed and should be linked in.
- 2  means libgo is needed and should be linked statically.  */
+ -1 means we should not link in librust
+ 0  means we should link in librust if it is needed
+ 1  means librust is needed and should be linked in.
+ 2  means librust is needed and should be linked statically.  */
   int library = 0;
 
   /* The new argument list will be contained in this.  */
   struct cl_decoded_option *new_decoded_options;
 
-  /* "-lm" or "-lmath" if it appears on the command line.  */
-  const struct cl_decoded_option *saw_math = 0;
-
-  /* "-lpthread" if it appears on the command line.  */
-  const struct cl_decoded_option *saw_thread = 0;
-
   /* "-lc" if it appears on the command line.  */
   const struct cl_decoded_option *saw_libc = 0;
 
   /* An array used to flag each argument that needs a bit set for
- LANGSPEC, MATHLIB, or WITHLIBC.  */
+ LANGSPEC or WITHLIBC.  */
   int *args;
 
-  /* Whether we need the thread library.  */
-  int need_thread = 0;
-
-  /* By default, we throw on the math library if we have one.  */
-  int need_math = (MATH_LIBRARY[0] != '\0');
-
   /* True if we saw -static.  */
   int static_link = 0;
 
@@ -115,8 +86,8 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
   /* Whether the -S option was used.  */
   bool saw_opt_S = false;
 
-  /* The first input file with an extension of .go.  */
-  const char *first_go_file = NULL;
+  /* The first input file with an extension of .rs.  */
+  const char *first_rust_file = NULL;
 
   argc = *in_decoded_options_count;
   decoded_options = *in_decoded_options;
@@ -137,34 +108,22 @@ lang_specific_driver (struct cl_decoded_option 
**in_decoded_options,
  break;
 
case OPT_l:
- if (strcmp (arg, MATH_LIBRARY) == 0)
-   {
- args[i] |= MATHLIB;
- need_math = 0;
-   }
- else if (strcmp (arg, THREAD_LIBRARY) == 0)
-   args[i] |= THREADLIB;
- else if (strcmp (arg, "c") == 0)
+ if (strcmp (arg, "c") == 0)
args[i] |= WITHLIBC;
  else
-   /* Unrecognized libraries (e.g. -lfoo) may require libgo.  */
+   /* Unrecognized 

Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-08-06 Thread Mark Wielaard
Hi Philip,

On Fri, Aug 06, 2021 at 03:31:07PM +0100, Philip Herron wrote:
> > Is it possible to make bors check all commits in a series? Or can we
> > somehow connect the buildbot workers to the bors checks?
> 
> I think the build-bot checks for every commit is a really nice feature
> here. I think you should keep the build-bots as are. I really like to
> make sure each of my commits are build-able and pass tests. It keeps me
> honest to avoid regressions as best I can.
> 
> What do you think?

I am just a little afraid it is running too late. But I am pretty
happy we have workers for 4 different architectures and they are green
most of the time. We really should add a 32bit (i686 or armhf) one
just to be sure that works correctly.

Currently i686 gets lots of failures like:

/home/mark/gccrs/gcc/testsuite/rust/compile/torture/methods3.rs:27:5: error: 
type mismatch in binary exp
ression
f64


D.229 = _2 + _4;
/home/mark/gccrs/gcc/testsuite/rust/compile/torture/methods3.rs:27:5: internal 
compiler error: 'verify_g
imple' failed
0x8b41fd4 verify_gimple_in_seq(gimple*)
../../gccrs/gcc/tree-cfg.c:5157
0x884b4c3 gimplify_body(tree_node*, bool)
../../gccrs/gcc/gimplify.c:15401
0x884b692 gimplify_function_tree(tree_node*)
../../gccrs/gcc/gimplify.c:15472
0x86a6448 cgraph_node::analyze()
../../gccrs/gcc/cgraphunit.c:670
0x86a9218 analyze_functions
../../gccrs/gcc/cgraphunit.c:1236
0x86a9e01 symbol_table::finalize_compilation_unit()
../../gccrs/gcc/cgraphunit.c:2514

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] More rustspec.cc cleanups

2021-08-06 Thread Mark Wielaard
Hi Philip,

On Fri, Aug 06, 2021 at 03:58:24PM +0100, Philip Herron wrote:
> Great patch, this file has been neglected. This is now being merged
> https://github.com/Rust-GCC/gccrs/pull/610
> 
> Its not 100% clear but is the compiler driver here automatically adding
> in -lc or is it simply checking if it saw_libc?

It does pass -lc (if not saw_libc).  You can see what is invoked with
which arguments using -v (e.g. gcc/gccrs -B gcc -v foobar.rs).

One of the things we are using is the crt1.o startup code, which
provides the _start symbol and which relies on libc (in particular
__libc_start_main and abort).

The patch wasn't really meant to change how we currently do
assembling, linking and startup. But just to remove those parts that
were unnecessary because they were go specific.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-08-06 Thread Mark Wielaard
Hi Arthur,

On Fri, Aug 06, 2021 at 05:55:09PM +0200, cohenarthur.dev via Gcc-rust wrote:
> I'm really sorry about not having all the commits build. I tried to keep
> them as atomic as possible and clearly didn't check all of them
> separately. This could have been a single commit and would have avoided
> this, but since each change was big I decided to split them up.
> 
> I was not aware that buildbot checks every commit separately. I think
> this is a good feature, and I'll keep it in mind. Won't happen again!

No worries, that is what the bots are for. We are all human, but the
bots aren't :)

It would be more helpful if the buildbot workers ran a bit earlier.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-08-06 Thread Mark Wielaard
On Fri, Aug 06, 2021 at 04:23:27PM +0100, Philip Herron wrote:
> On 05/08/2021 20:37, Mark Wielaard wrote:
> > Hi,
> >
> > On Fri, Jul 30, 2021 at 03:03:13AM +0200, Mark Wielaard wrote:
> >> That variant is attached and can also be found here:
> >> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-loc
> >> The original is also here:
> >> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token
> >>
> >> Hopefully one of the two is acceptable. If not please let me know how
> >> to rewrite it in a cheaper more idiomatic way.
> > Any feedback on these patches? I really like to get the locations
> > correct for these pratt parsed expressions. If both variants are
> > problematic please let me know what I can do to improve them.
> >
> > Thanks,
> >
> > Mark
> >
> Hi Mark,
> 
> Sorry for lack of reply on this. After looking into this and also
> getting Arthur Cohen to review, I think:
> 
>   * Token passing: If we end up using the token for more than the
> location this might be useful but at present I can't think of a
> use-case for the token. If we do need it maybe we could look into
> passing it by reference.
>   * Location passing: I think this is the best solution and is directly
> associated with the issue you have fixed. The function says that you
> can call me but tell me the location as well so its up to the caller
> to handle this. We should add a comment to the function prototypes
> to say what the location is but that's it.
> 
> What do you think?

OK, lets go with the location passing. I added a comment to the
function prototypes in rust-parse.h about the passed in
pratt_parsed_token.

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token

Cheers,

Mark
>From 1c139cbaa71c2928ca747fa26dc776699937280a Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Thu, 29 Jul 2021 00:00:55 +0200
Subject: [PATCH] Pass pratt parsed token to expr parser functions to fix expr
 locus
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The pratt parser skips the first token of an expression before
invoking the actual expression parsing function. This makes getting
the correct starting location of a pratt parsed expression hard. The
"correction" of the location by subtracting an integer is often wrong
(since there may be arbitrary whitespace or comments between
tokens). Fix this by passing the token to the expression parsing
functions (instead of just providing a pratt_parse boolean). Use this
token to set the start of the expression.

Before gccrs would generate the following error message:

return.rs:3:22: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  |  ^

Now we get:

return.rs:3:17: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  | ^
---
 gcc/rust/parse/rust-parse-impl.h | 180 +--
 gcc/rust/parse/rust-parse.h  |  64 ++-
 2 files changed, 109 insertions(+), 135 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index ccfff841784..1e951e4bd48 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6586,7 +6586,7 @@ Parser::parse_path_expr_segment ()
 template 
 AST::QualifiedPathInExpression
 Parser::parse_qualified_path_in_expression (
-  bool pratt_parse)
+  const_TokenPtr pratt_parsed_token)
 {
   /* Note: the Rust grammar is defined in such a way that it is impossible to
* determine whether a prospective qualified path is a
@@ -6601,7 +6601,7 @@ Parser::parse_qualified_path_in_expression (
 
   // parse the qualified path type (required)
   AST::QualifiedPathType qual_path_type
-= parse_qualified_path_type (pratt_parse);
+= parse_qualified_path_type (pratt_parsed_token);
   if (qual_path_type.is_error ())
 {
   // TODO: should this create a parse error?
@@ -6667,12 +6667,13 @@ Parser::parse_qualified_path_in_expression (
 // Parses the type syntactical construction at the start of a qualified path.
 template 
 AST::QualifiedPathType
-Parser::parse_qualified_path_type (bool pratt_parse)
+Parser::parse_qualified_path_type (
+  const_TokenPtr pratt_parsed_token)
 {
-  Location locus = Linemap::unknown_location ();
+  Location locus;
   /* TODO: should this actually be error? is there anywhere where this could be
* valid? */
-  if (!pratt_parse)
+  if (pratt_parsed_token == nullptr)
 {
   locus = lexer.peek_token ()->get_locus ();
   if (!skip_token (LEFT_ANGLE))
@@ -6682,10 +6683,7 @@ Parser::parse_qualified_path_type (bool pratt_parse)
 	}
 }
   else
-{
-  // move ba

[PATCH] lex: accept zero codepoints in strings

2021-08-07 Thread Mark Wielaard
Zero characters (codepoints) are acceptable in strings. The current
Lexer::parse_string skipped such zero codepoints by accidents. The
zero codepoint was also used as error/skip indicator, but that is only
true if the third argument of utf8_escape_pair is true (yes, it is
called pair, but is a triple).

Add a testcase that checks the (sub)strings are separated by zero
chars. Since we cannot slice strings yet this uses extern "C"
functions, printf and memchr.
---

On irc bjorn3_gh pointed out that our lexer ate embedded zero chars
from strings. This fixes that issue and adds a testcase. Also on
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=str-zero

 gcc/rust/lex/rust-lex.cc  |  2 +-
 .../rust/execute/torture/str-zero.rs  | 26 +++
 2 files changed, 27 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/str-zero.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 0b8a8eae651..2cfbc4fb1f4 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1827,7 +1827,7 @@ Lexer::parse_string (Location loc)
  else
length += std::get<1> (utf8_escape_pair);
 
- if (current_char32 != Codepoint (0))
+ if (current_char32 != Codepoint (0) || !std::get<2> 
(utf8_escape_pair))
str += current_char32;
 
  // required as parsing utf8 escape only changes current_char
diff --git a/gcc/testsuite/rust/execute/torture/str-zero.rs 
b/gcc/testsuite/rust/execute/torture/str-zero.rs
new file mode 100644
index 000..e7fba0d1372
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-zero.rs
@@ -0,0 +1,26 @@
+/* { dg-output "bar foo baz foobar\n" } */
+extern "C"
+{
+  fn printf(s: *const i8, ...);
+  fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
+}
+
+pub fn main () -> i32
+{
+  let f = "%s %s %s %s\n\0";
+  let s = "bar\0\
+   foo\
+   \x00\
+   baz\u{}\
+   foobar\0";
+  let cf = f as *const str as *const i8;
+  let cs = s as *const str as *const i8;
+  unsafe
+{
+  let cs2 = memchr (cs, b'f', 5);
+  let cs3 = memchr (cs2, b'b', 5);
+  let cs4 = memchr (cs3, b'f', 5);
+  printf (cf, cs, cs2, cs3, cs4);
+}
+  0
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Test results for gccrs on Debian unstable s390x

2021-08-08 Thread Mark Wielaard
Hi!

On Sun, Aug 08, 2021 at 09:03:44AM +0200, John Paul Adrian Glaubitz wrote:
> On 6/2/21 9:48 PM, John Paul Adrian Glaubitz wrote:
> > Just built gccrs revision 59b417323b25072aff2662f1f54f417f7b7ded61 on 
> > Debian unstable s390x.
> > 
> > The testsuite fails with the following failures. Attaching the log file.
> As expected, the recent patch by Michael Karcher [1] has fixed the testsuite 
> on s390x as well.

Very nice. I added both a i386 and s390x worker to the buildbot so
that both arches will be tested on each new commit:
https://builder.wildebeest.org/buildbot/#/builders?tags=gccrust

We now have builder for arm64, i386, ppc64, ppc64le, s390x and x86_64
which are known zero fail.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-08-08 Thread Mark Wielaard
On Sun, Aug 08, 2021 at 12:51:47PM +0100, Philip Herron wrote:
> I would be interested in seeing 32bit build bots since this patch has
> been merged: https://github.com/Rust-GCC/gccrs/pull/614
> 
> Which thanks to Adrian who has been testing it out.
> 
> Do you have access to 32bit machines? I have some unused space on
> digital ocean where we could put some build-bots if you like?

Just added one: https://builder.wildebeest.org/buildbot/#/builders/62
(Ignore the red builds, the last one is green, they were setup issues)
It isn't super fast (takes ~25 to do a build plus check-rust), but as
long as we do < 48 commits a day we should be fine. I tried adding
ccache on it (which reduces build times a lot on the other builders)
but that caused some odd failures. I think for now we are fine, but we
start adding lots more commits a day adding some extra VMs would be
nice.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] lex: accept zero codepoints in strings

2021-08-08 Thread Mark Wielaard
Hi Philip

On Sun, Aug 08, 2021 at 01:36:21PM +0100, Philip Herron wrote:
> This patch looks good to go but the clang-format check is failing:
> https://github.com/Rust-GCC/gccrs/pull/615
> 
> The error seems to be that it moves the extra check onto a new line.
> https://github.com/Rust-GCC/gccrs/pull/615/checks?check_run_id=3272823975

Unfortunately it doesn't show what the actual formatting isssue is. It
just say "Sign in for full log view". But I get the idea by running it
locally. The line is too long. Updated patch attached and pushed to
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=str-zero

Cheers,

Mark
>From 007e6ecefb0b43d0b9e7bf85f75ec050b5c520e5 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Sat, 7 Aug 2021 17:32:41 +0200
Subject: [PATCH] lex: accept zero codepoints in strings

Zero characters (codepoints) are acceptable in strings. The current
Lexer::parse_string skipped such zero codepoints by accidents. The
zero codepoint was also used as error/skip indicator, but that is only
true if the third argument of utf8_escape_pair is true (yes, it is
called pair, but is a triple).

Add a testcase that checks the (sub)strings are separated by zero
chars. Since we cannot slice strings yet this uses extern "C"
functions, printf and memchr.
---
 gcc/rust/lex/rust-lex.cc  |  3 ++-
 .../rust/execute/torture/str-zero.rs  | 26 +++
 2 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/execute/torture/str-zero.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 0b8a8eae651..49b6b6d32a7 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1827,7 +1827,8 @@ Lexer::parse_string (Location loc)
 	  else
 	length += std::get<1> (utf8_escape_pair);
 
-	  if (current_char32 != Codepoint (0))
+	  if (current_char32 != Codepoint (0)
+	  || !std::get<2> (utf8_escape_pair))
 	str += current_char32;
 
 	  // required as parsing utf8 escape only changes current_char
diff --git a/gcc/testsuite/rust/execute/torture/str-zero.rs b/gcc/testsuite/rust/execute/torture/str-zero.rs
new file mode 100644
index 000..e7fba0d1372
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/str-zero.rs
@@ -0,0 +1,26 @@
+/* { dg-output "bar foo baz foobar\n" } */
+extern "C"
+{
+  fn printf(s: *const i8, ...);
+  fn memchr(s: *const i8, c: u8, n: usize) -> *const i8;
+}
+
+pub fn main () -> i32
+{
+  let f = "%s %s %s %s\n\0";
+  let s = "bar\0\
+   foo\
+   \x00\
+   baz\u{}\
+   foobar\0";
+  let cf = f as *const str as *const i8;
+  let cs = s as *const str as *const i8;
+  unsafe
+{
+  let cs2 = memchr (cs, b'f', 5);
+  let cs3 = memchr (cs2, b'b', 5);
+  let cs4 = memchr (cs3, b'f', 5);
+  printf (cf, cs, cs2, cs3, cs4);
+}
+  0
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Pass pratt parsed token to expr parser functions to fix expr locus

2021-08-09 Thread Mark Wielaard
Hi,

On Sat, Aug 07, 2021 at 03:01:39AM +0200, Mark Wielaard wrote:
> > Sorry for lack of reply on this. After looking into this and also
> > getting Arthur Cohen to review, I think:
> > 
> >   * Token passing: If we end up using the token for more than the
> > location this might be useful but at present I can't think of a
> > use-case for the token. If we do need it maybe we could look into
> > passing it by reference.
> >   * Location passing: I think this is the best solution and is directly
> > associated with the issue you have fixed. The function says that you
> > can call me but tell me the location as well so its up to the caller
> > to handle this. We should add a comment to the function prototypes
> > to say what the location is but that's it.
> > 
> > What do you think?
> 
> OK, lets go with the location passing. I added a comment to the
> function prototypes in rust-parse.h about the passed in
> pratt_parsed_token.
> 
> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-token

Looks like I said I'll do B, then did A anyway... duh. Sorry.  Here is
the patch as I said I would do it, also on this branch, rebased
against upstream:
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=pass-pratt-parse-loc

Cheers,

Mark
>From 5b0bbf4509776b5ce3e5f82b8365f62110f91641 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Thu, 29 Jul 2021 00:00:55 +0200
Subject: [PATCH] Pass pratt parsed location to expr parser functions to fix
 expr locus
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The pratt parser skips the first token of an expression before
invoking the actual expression parsing function. This makes getting
the correct starting location of a pratt parsed expression hard. The
"correction" of the location by subtracting an integer is often wrong
(since there may be arbitrary whitespace or comments between
tokens). Fix this by passing the location of the skipped token to the
expression parsing functions (instead of just providing a pratt_parse
boolean). Use this location to set the start of the expression (and as
indicator to not try to parse the first token of the expression).

Before gccrs would generate the following error message:

return.rs:3:22: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  |  ^

Now we get:

return.rs:3:17: error: cannot ‘break’ outside of a loop
3 | let x = 5 - break return (16 + 2);
  | ^
---
 gcc/rust/parse/rust-parse-impl.h | 177 +++
 gcc/rust/parse/rust-parse.h  |  72 -
 2 files changed, 104 insertions(+), 145 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index ccfff841784..c94c637e45c 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6586,7 +6586,7 @@ Parser::parse_path_expr_segment ()
 template 
 AST::QualifiedPathInExpression
 Parser::parse_qualified_path_in_expression (
-  bool pratt_parse)
+  Location pratt_parsed_loc)
 {
   /* Note: the Rust grammar is defined in such a way that it is impossible to
* determine whether a prospective qualified path is a
@@ -6601,7 +6601,7 @@ Parser::parse_qualified_path_in_expression (
 
   // parse the qualified path type (required)
   AST::QualifiedPathType qual_path_type
-= parse_qualified_path_type (pratt_parse);
+= parse_qualified_path_type (pratt_parsed_loc);
   if (qual_path_type.is_error ())
 {
   // TODO: should this create a parse error?
@@ -6667,12 +6667,13 @@ Parser::parse_qualified_path_in_expression (
 // Parses the type syntactical construction at the start of a qualified path.
 template 
 AST::QualifiedPathType
-Parser::parse_qualified_path_type (bool pratt_parse)
+Parser::parse_qualified_path_type (
+  Location pratt_parsed_loc)
 {
-  Location locus = Linemap::unknown_location ();
+  Location locus = pratt_parsed_loc;
   /* TODO: should this actually be error? is there anywhere where this could be
* valid? */
-  if (!pratt_parse)
+  if (locus == Linemap::unknown_location ())
 {
   locus = lexer.peek_token ()->get_locus ();
   if (!skip_token (LEFT_ANGLE))
@@ -6681,11 +6682,6 @@ Parser::parse_qualified_path_type (bool pratt_parse)
 	  return AST::QualifiedPathType::create_error ();
 	}
 }
-  else
-{
-  // move back by 1 if pratt parsing due to skipping '<'
-  locus = lexer.peek_token ()->get_locus () - 1;
-}
 
   // parse type (required)
   std::unique_ptr type = parse_type ();
@@ -7311,10 +7307,10 @@ Parser::parse_expr_without_block (AST::AttrVec outer_attrs)
 template 
 std::unique_ptr
 Parser::parse_block_expr (AST::AttrVec outer_attrs,
-	  bool pratt_parse)
+	 

[PATCH] parse if expression with unary minus or not expression

2021-08-14 Thread Mark Wielaard
An if conditional expression doesn't need brackets, but that means
that it doesn't accept struct expressions. Those are not easy to
distinquish from the block that follows. What isn't immediately clear
from the grammar is that unary conditions like minus '-' or not '!'
also shouldn't accept struct expressions (when part of an if
conditional expression) because those also cannot be easily
distinquished from the block that follows.

Add a testcase "ifunaryexpr.rs" that shows a couple of contructs that
should be accepted as if conditional expressions and fix the parser to
pass the restriction of not accepting struct expressions after a unary
expression.
---
 gcc/rust/parse/rust-parse-impl.h  |  4 
 .../rust/compile/torture/ifunaryexpr.rs   | 22 +++
 2 files changed, 26 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/torture/ifunaryexpr.rs

diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 731e0b3682f..fa6d409c6dc 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -12547,6 +12547,8 @@ Parser::null_denotation 
(const_TokenPtr tok,
   case MINUS: { // unary minus
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
+   if (!restrictions.can_be_struct_expr)
+ entered_from_unary.can_be_struct_expr = false;
std::unique_ptr expr
  = parse_expr (LBP_UNARY_MINUS, {}, entered_from_unary);
 
@@ -12571,6 +12573,8 @@ Parser::null_denotation 
(const_TokenPtr tok,
   case EXCLAM: { // logical or bitwise not
ParseRestrictions entered_from_unary;
entered_from_unary.entered_from_unary = true;
+   if (!restrictions.can_be_struct_expr)
+ entered_from_unary.can_be_struct_expr = false;
std::unique_ptr expr
  = parse_expr (LBP_UNARY_EXCLAM, {}, entered_from_unary);
 
diff --git a/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs 
b/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs
new file mode 100644
index 000..8f0bb87f558
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs
@@ -0,0 +1,22 @@
+extern "C"
+{
+  pub fn abort ();
+}
+
+struct B { b: bool }
+
+pub fn main ()
+{
+  let n = 1;
+  if 0 > -n { } else { unsafe { abort (); } }
+
+  let b = true;
+  if !b { unsafe { abort (); } }
+  if !!b { } else { unsafe { abort (); } }
+
+  let bb = B { b: false };
+
+  if !bb.b && !b { unsafe { abort (); } }
+
+  if (B { b: true }).b { } else { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Use builtin bool instead of creating new bool types for ComparisonExpr

2021-08-14 Thread Mark Wielaard
The TypeCheckExpr creates a new TyTy::BoolType for a
ComparisonExpr. This new BoolType is unknown to TyTyResolveCompile
which causes a crash when trying to compile the inferred new
BoolType. The new "bools_eq.rs" testcase uses several bools which show
this issue. Resolve this by looking up the builtin bool type.
---
 gcc/rust/typecheck/rust-hir-type-check-expr.h  |  2 +-
 gcc/testsuite/rust/compile/torture/bools_eq.rs | 18 ++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/bools_eq.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index d88cb0b7f1d..9cf64685e00 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -631,7 +631,7 @@ public:
   return;
 
 // we expect this to be
-infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ());
+context->lookup_builtin ("bool", &infered);
 infered->append_reference (lhs->get_ref ());
 infered->append_reference (rhs->get_ref ());
   }
diff --git a/gcc/testsuite/rust/compile/torture/bools_eq.rs 
b/gcc/testsuite/rust/compile/torture/bools_eq.rs
new file mode 100644
index 000..965127b5d54
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bools_eq.rs
@@ -0,0 +1,18 @@
+extern "C"
+{
+  fn abort ();
+}
+
+fn beq (a: bool, b: bool) -> bool
+{
+  let bools_eq = a == b;
+  bools_eq
+}
+
+pub fn main ()
+{
+  let a = true;
+  let b = false;
+  let r = beq (a, b);
+  if r { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Suppress uninitialized candidate_type warning in process_traits_for_candidates

2021-08-15 Thread Mark Wielaard
Without handling the default case in the switch statement gcc 10.2.1 will warn:

rust-hir-path-probe.h:75:40: warning: ‘candidate_type’ may be used uninitialized
  in this function [-Wmaybe-uninitialized]
---
 gcc/rust/typecheck/rust-hir-path-probe.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h 
b/gcc/rust/typecheck/rust-hir-path-probe.h
index 87c96628118..22b10741094 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -260,6 +260,7 @@ private:
break;
 
  case TraitItemReference::TraitItemType::ERROR:
+ default:
gcc_unreachable ();
break;
  }
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Add support for const bool and const float

2021-08-15 Thread Mark Wielaard
Handle BOOL and FLOAT in ConstFoldExpr::visit (HIR::LiteralExpr) to
make it possible to create const bool, f32 and f64 constants. Add a
new testcase "primconsts.rs". Not yet handled are const char and &str
types.
---
 gcc/rust/typecheck/rust-hir-const-fold.h  | 30 
 .../rust/compile/torture/primconsts.rs| 72 +++
 2 files changed, 102 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/torture/primconsts.rs

diff --git a/gcc/rust/typecheck/rust-hir-const-fold.h 
b/gcc/rust/typecheck/rust-hir-const-fold.h
index f6c66163fc1..8efbb183403 100644
--- a/gcc/rust/typecheck/rust-hir-const-fold.h
+++ b/gcc/rust/typecheck/rust-hir-const-fold.h
@@ -315,6 +315,36 @@ public:
}
return;
 
+   case HIR::Literal::BOOL: {
+ bool bval = literal_value->as_string ().compare ("true") == 0;
+ folded = ctx->get_backend ()->boolean_constant_expression (bval);
+   }
+   return;
+
+   case HIR::Literal::FLOAT: {
+ mpfr_t fval;
+ if (mpfr_init_set_str (fval, literal_value->as_string ().c_str (), 10,
+MPFR_RNDN)
+ != 0)
+   {
+ rust_fatal_error (expr.get_locus (),
+   "bad floating-point number in literal");
+ return;
+   }
+
+ TyTy::BaseType *tyty = nullptr;
+ if (!tyctx->lookup_type (expr.get_mappings ().get_hirid (), &tyty))
+   {
+ rust_fatal_error (expr.get_locus (),
+   "did not resolve type for this literal expr");
+ return;
+   }
+
+ Btype *type = ConstFoldType::fold (tyty, ctx->get_backend ());
+ folded = ctx->get_backend ()->float_constant_expression (type, fval);
+   }
+   return;
+
/* handle other literals */
 
   default:
diff --git a/gcc/testsuite/rust/compile/torture/primconsts.rs 
b/gcc/testsuite/rust/compile/torture/primconsts.rs
new file mode 100644
index 000..bcf9456d059
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/primconsts.rs
@@ -0,0 +1,72 @@
+const TRUE: bool = true;
+const FALSE: bool = !TRUE;
+
+const U8ZERO: u8 = 0;
+const U8ONE: u8 = U8ZERO + 1;
+const U16ZERO: u16 = 0;
+const U16ONE: u16 = U16ZERO + 1;
+const U32ZERO: u32 = 0;
+const U32ONE: u32 = U32ZERO + 1;
+const U64ZERO: u64 = 0;
+const U64ONE: u64 = U64ZERO + 1;
+const U128ZERO: u128 = 0;
+const U128ONE: u128 = U128ZERO + 1;
+
+const I8ZERO: i8 = 0;
+const I8ONE: i8 = I8ZERO + 1;
+const I16ZERO: i16 = 0;
+const I16ONE: i16 = I16ZERO + 1;
+const I32ZERO: i32 = 0;
+const I32ONE: i32 = I32ZERO + 1;
+const I64ZERO: i64 = 0;
+const I64ONE: i64 = I64ZERO + 1;
+const I128ZERO: i128 = 0;
+const I128ONE: i128 = I128ZERO + 1;
+
+const F32ZERO: f32 = 0.0;
+const F32ONE: f32 = F32ZERO + 1.0;
+const F64ZERO: f64 = 0.0;
+const F64ONE: f64 = F64ZERO + 1.0;
+
+const USIZEZERO: usize = 0;
+const USIZEONE: usize = USIZEZERO + 1;
+const ISIZEZERO: isize = 0;
+const ISIZEONE: isize = ISIZEZERO + 1;
+
+/* Not yet supported 
+const CHARPI: char = '\u{03C0}';
+const STRHELLO: &str = "Hello World!";
+*/
+
+extern "C" { fn abort (); }
+
+pub fn main ()
+{
+  if TRUE == FALSE { unsafe { abort (); } }
+  if U8ZERO > U8ONE { unsafe { abort (); } }
+  if U16ZERO > U16ONE { unsafe { abort (); } }
+  if U32ZERO > U32ONE { unsafe { abort (); } }
+  if U64ZERO > U64ONE { unsafe { abort (); } }
+  if U128ZERO > U128ONE { unsafe { abort (); } }
+
+  if I8ONE <= I8ZERO { unsafe { abort (); } }
+  if I16ONE <= I16ZERO { unsafe { abort (); } }
+  if I32ONE <= I32ZERO { unsafe { abort (); } }
+  if I64ONE <= I64ZERO { unsafe { abort (); } }
+  if I128ONE <= I128ZERO { unsafe { abort (); } }
+
+  if F32ZERO + F32ONE != F32ONE { unsafe { abort (); } }
+  if F64ZERO + F64ONE != F64ONE { unsafe { abort (); } }
+
+  if USIZEZERO + USIZEONE - USIZEONE + USIZEZERO != USIZEZERO
+{
+  unsafe { abort (); }
+}
+  if ISIZEZERO + ISIZEONE - ISIZEONE + ISIZEZERO != ISIZEZERO
+{
+  unsafe { abort (); }
+}
+
+ // if CHARPI != '\u{03c0}'  { unsafe { abort (); } }
+ // if STRHELLO != "Hello World!" { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Use default type_for_size langhook

2021-08-15 Thread Mark Wielaard
The gcc constant folding code uses the type_for_size langhook. Use the
default implementation instead of crashing when the langhook is
called. Add a new testcase "prims_struct_eq.rs" that creates trees
that triggers the constant folding.

Also remove the write_globals langhook which was removed when early
debug was integrated into gcc.
---
 gcc/rust/rust-lang.cc | 17 
 .../rust/compile/torture/prims_struct_eq.rs   | 91 +++
 2 files changed, 91 insertions(+), 17 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/prims_struct_eq.rs

diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc
index 462e8344514..b4f8cbe7830 100644
--- a/gcc/rust/rust-lang.cc
+++ b/gcc/rust/rust-lang.cc
@@ -224,20 +224,6 @@ grs_langhook_type_for_mode (machine_mode mode, int 
unsignedp)
   return NULL;
 }
 
-/* This appears to be used for creating different types for different bit sizes
- * (e.g. int and long). Also, the Go frontend calls this from type_for_mode to
- * determine the type from a specific bitsize for integer types.
- * FIXME: change this when working on AST-GENERIC conversion to allow the full
- * range of Rust type sizes. */
-static tree
-grs_langhook_type_for_size (unsigned int bits ATTRIBUTE_UNUSED,
-   int unsignedp ATTRIBUTE_UNUSED)
-{
-  gcc_unreachable ();
-  return NULL_TREE;
-  // nothing at the moment, but change later
-}
-
 // Record a builtin function. We just ignore builtin functions.
 static tree
 grs_langhook_builtin_function (tree decl ATTRIBUTE_UNUSED)
@@ -420,7 +406,6 @@ rust_localize_identifier (const char *ident)
 #undef LANG_HOOKS_POST_OPTIONS
 #undef LANG_HOOKS_PARSE_FILE
 #undef LANG_HOOKS_TYPE_FOR_MODE
-#undef LANG_HOOKS_TYPE_FOR_SIZE
 #undef LANG_HOOKS_BUILTIN_FUNCTION
 #undef LANG_HOOKS_GLOBAL_BINDINGS_P
 #undef LANG_HOOKS_PUSHDECL
@@ -442,12 +427,10 @@ rust_localize_identifier (const char *ident)
  */
 #define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file
 #define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode
-#define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size
 #define LANG_HOOKS_BUILTIN_FUNCTION grs_langhook_builtin_function
 #define LANG_HOOKS_GLOBAL_BINDINGS_P grs_langhook_global_bindings_p
 #define LANG_HOOKS_PUSHDECL grs_langhook_pushdecl
 #define LANG_HOOKS_GETDECLS grs_langhook_getdecls
-#define LANG_HOOKS_WRITE_GLOBALS grs_langhook_write_globals
 #define LANG_HOOKS_GIMPLIFY_EXPR grs_langhook_gimplify_expr
 #define LANG_HOOKS_EH_PERSONALITY grs_langhook_eh_personality
 
diff --git a/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs 
b/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs
new file mode 100644
index 000..81ab7424627
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/prims_struct_eq.rs
@@ -0,0 +1,91 @@
+extern "C"
+{
+  fn abort ();
+}
+
+struct Prims
+{
+  b1: bool,
+  b2: bool,
+  b3: bool,
+  b4: bool,
+  c1: char,
+  c2: char,
+  u81: u8,
+  u82: u8,
+  u83: u8,
+  u84: u8,
+  i81: i8,
+  i82: i8,
+  i83: i8,
+  i84: i8,
+  u161: u16,
+  u162: u16,
+  i161: i16,
+  i162: i16,
+  u321: u32,
+  u322: u32,
+  i321: i32,
+  i322: i32,
+  u641: u64,
+  i641: i64,
+  u1281: u128,
+  i1281: i128,
+  usize1: usize,
+  isize1: isize,
+}
+
+fn prims_eq (p1: Prims, p2: Prims) -> bool
+{
+  return p1.b1 == p2.b1
+ && p1.b2 == p2.b2
+ && p1.b3 == p2.b3
+ && p1.b4 == p2.b4
+ && p1.c1 == p2.c1
+ && p1.c2 == p2.c2
+ && p1.u81 == p2.u81
+ && p1.u82 == p2.u82
+ && p1.u83 == p2.u83
+ && p1.u84 == p2.u84
+ && p1.i81 == p2.i81
+ && p1.i82 == p2.i82
+ && p1.i83 == p2.i83
+ && p1.i84 == p2.i84
+ && p1.u161 == p2.u161
+ && p1.u162 == p2.u162
+ && p1.i161 == p2.i161
+ && p1.i162 == p2.i162
+ && p1.u321 == p2.u321
+ && p1.u322 == p2.u322
+ && p1.i321 == p2.i321
+ && p1.i322 == p2.i322
+ && p1.u641 == p2.u641
+ && p1.i641 == p2.i641
+ && p1.u1281 == p2.u1281
+ && p1.i1281 == p2.i1281
+ && p1.usize1 == p2.usize1
+ && p1.isize1 == p2.isize1;
+}
+
+pub fn main ()
+{
+  let p1 = Prims { b1: true, b2: false, b3: false, b4: true,
+   c1: 'a', c2: 'b',
+   u81: 1, u82: 2, u83: 3, u84: 4,
+   i81: -1, i82: -2, i83: -3, i84: -4,
+   u161: 1, u162: 2,
+   i161: -1, i162: -2,
+   u321: 1, u322: 2,
+   i321: -1, i322: -2,
+   u641: 1,
+   i641: -1,
+   u1281: 1,
+   i1281: -1,
+   usize1: 1,
+   isize1: -1 };
+  let p2 = Prims { usize1: 1, .. p1 };
+  let p3 = Prims { u1281: 0, .. p2 };
+  let p4 = Prims { i1281: 0, .. p3 };
+  if !prims_eq (p1, p2) { unsafe { abort (); } }
+  if prims_eq (p3, p4) { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@g

Re: [PATCH] Add support for const bool and const float

2021-08-16 Thread Mark Wielaard
Hi Marc,

On Mon, 2021-08-16 at 07:48 +, d...@kataplop.net wrote:
> Looks like tests are not OK, at least in the github action.

Are you talking about this patch (which I cannot find on github) or
"Use builtin bool instead of creating new bool types for
ComparisonExpr"? On github I can only see that one has a red cross
which says "build-and-check" but doesn't give any more information
except that "Check regressions" failed, but without any logs ("Sign in
for the full log view").

>  Can't test but maybe you can confirm this issue ?
> 
> # of unexpected failures  14

On my setup, Debian arm64 with gcc 10.2, for both patches the newly
added testcase fails without the patch and succeeds with the patch.
I'll try to find some other setup. What is the configuration for the
machine where you see the new unexpected failures (and with which
patch)?

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Allow bool and char to be cast as any integer type

2021-08-16 Thread Mark Wielaard
bools and chars can be cast to any integer type, but not to floats or
each other. Adjust the BoolCastRule and CharCastRule to allow these
casts. Add a postive test "as_bool_char.rs" and negative test
"bad_as_bool_char.rs" to check the correct casts are accepted and the
illegal casts produce errors.

Resolves: https://github.com/Rust-GCC/gccrs/issues/629
---
 gcc/rust/typecheck/rust-tyty-cast.h   | 12 +++
 .../rust/compile/bad_as_bool_char.rs  | 18 ++
 .../rust/compile/torture/as_bool_char.rs  | 36 +++
 3 files changed, 66 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/bad_as_bool_char.rs
 create mode 100644 gcc/testsuite/rust/compile/torture/as_bool_char.rs

diff --git a/gcc/rust/typecheck/rust-tyty-cast.h 
b/gcc/rust/typecheck/rust-tyty-cast.h
index de59b327e76..c457931b17f 100644
--- a/gcc/rust/typecheck/rust-tyty-cast.h
+++ b/gcc/rust/typecheck/rust-tyty-cast.h
@@ -779,6 +779,12 @@ public:
   }
   }
 
+  /* bools can be cast to any integer type (but not floats or chars).  */
+  void visit (IntType &type) override { resolved = type.clone (); }
+  void visit (UintType &type) override { resolved = type.clone (); }
+  void visit (USizeType &type) override { resolved = type.clone (); }
+  void visit (ISizeType &type) override { resolved = type.clone (); }
+
 private:
   BaseType *get_base () override { return base; }
 
@@ -1078,6 +1084,12 @@ public:
 
   void visit (CharType &type) override { resolved = type.clone (); }
 
+  /* chars can be cast to any integer type (but not floats or bools).  */
+  void visit (IntType &type) override { resolved = type.clone (); }
+  void visit (UintType &type) override { resolved = type.clone (); }
+  void visit (USizeType &type) override { resolved = type.clone (); }
+  void visit (ISizeType &type) override { resolved = type.clone (); }
+
 private:
   BaseType *get_base () override { return base; }
 
diff --git a/gcc/testsuite/rust/compile/bad_as_bool_char.rs 
b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
new file mode 100644
index 000..91a28eebe00
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_as_bool_char.rs
@@ -0,0 +1,18 @@
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let fone = t as f32;   // { dg-error "invalid cast" }
+  let fzero = f as f64;  // { dg-error "invalid cast" }
+
+  let nb = 0u8 as bool;  // { dg-error "invalid cast" }
+  let nc = true as char; // { dg-error "invalid cast" }
+
+  let a = 'a';
+  let b = 'b';
+  let fa = a as f32; // { dg-error "invalid cast" }
+  let bb = b as bool;// { dg-error "invalid cast" }
+
+  let t32: u32 = 33;
+  let ab = t32 as char;  // { dg-error "invalid cast" }
+}
diff --git a/gcc/testsuite/rust/compile/torture/as_bool_char.rs 
b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
new file mode 100644
index 000..d687499384a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/as_bool_char.rs
@@ -0,0 +1,36 @@
+extern "C" { fn abort (); }
+
+pub fn main ()
+{
+  let t = true;
+  let f = false;
+  let one = t as u8;
+  let zero = f as u8;
+
+  if one != 1 || zero != 0 { unsafe { abort (); } }
+
+  let isizeone = true as isize;
+  let usizezero = false as usize;
+
+  if isizeone != 1 || usizezero != 0 { unsafe { abort (); } }
+
+  let i32zero = f as i32;
+  let u128one = t as u128;
+
+  if u128one != 1 || i32zero != 0 { unsafe { abort (); } }
+
+  let a = 'a';
+  let b = 'b';
+  let ua = a as u8;
+  let ib = b as i32;
+
+  if (ua + 1) as i32 != ib { unsafe { abort (); } }
+
+  let tt = ua;
+  let aa = tt as char;
+
+  let ttt = tt + 1;
+  let ab = ttt as char;
+
+  if aa != 'a' || ab != 'b' { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Add support for const bool and const float

2021-08-16 Thread Mark Wielaard
Hi,

On Mon, Aug 16, 2021 at 10:52:07AM +0200, Mark Wielaard wrote:
> On Mon, 2021-08-16 at 07:48 +, d...@kataplop.net wrote:
> > Looks like tests are not OK, at least in the github action.
> 
> Are you talking about this patch (which I cannot find on github) or
> "Use builtin bool instead of creating new bool types for
> ComparisonExpr"? On github I can only see that one has a red cross
> which says "build-and-check" but doesn't give any more information
> except that "Check regressions" failed, but without any logs ("Sign in
> for the full log view").
> 
> >  Can't test but maybe you can confirm this issue ?
> > 
> > # of unexpected failures14
> 
> On my setup, Debian arm64 with gcc 10.2, for both patches the newly
> added testcase fails without the patch and succeeds with the patch.
> I'll try to find some other setup. What is the configuration for the
> machine where you see the new unexpected failures (and with which
> patch)?

On irc we tracked down the confusion. This is about the other patch
"Use builtin bool instead of creating new bool types for
ComparisonExpr".  But rebased on top of current master. Which includes
the testcase rust/compile/torture/ifunaryexpr.rs

So the above failures where:

FAIL: rust/compile/torture/ifunaryexpr.rs   -O0  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O0  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O1  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O1  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O3 -g  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O3 -g  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -Os  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -Os  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2 -flto -fno-use-linker-plugin 
-flto-partition=none  (test for excess errors)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects  (internal compiler error)
FAIL: rust/compile/torture/ifunaryexpr.rs   -O2 -flto -fuse-linker-plugin 
-fno-fat-lto-objects  (test for excess errors)

Now having replicated it locally the rust.log shows:

/srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs: In function 
'main':
/srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs:8:5: error: 
mismatching comparison operand types
const i32
bool
if (n != 0) goto ; else goto ;
/srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs:8:5: 
internal compiler error: 'verify
_gimple' failed
0xf38fbd verify_gimple_in_seq(gimple*)
../../gccrs/gcc/tree-cfg.c:5157
0xc72346 gimplify_body(tree_node*, bool)
../../gccrs/gcc/gimplify.c:15401
0xc724cd gimplify_function_tree(tree_node*)
../../gccrs/gcc/gimplify.c:15472
0xab0dc7 cgraph_node::analyze()
../../gccrs/gcc/cgraphunit.c:670
0xab38b7 analyze_functions
../../gccrs/gcc/cgraphunit.c:1236
0xab454d symbol_table::finalize_compilation_unit()
../../gccrs/gcc/cgraphunit.c:2514

So, my patch created bad gimple. I'll try to track it down.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Add support for const bool and const float

2021-08-16 Thread Mark Wielaard
Hi,

On Mon, Aug 16, 2021 at 11:03:19PM +0200, Mark Wielaard wrote:
> Now having replicated it locally the rust.log shows:
> 
> /srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs: In 
> function 'main':
> /srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs:8:5: 
> error: mismatching comparison operand types
> const i32
> bool
> if (n != 0) goto ; else goto ;
> /srv/gccrs/gccrs/gcc/testsuite/rust/compile/torture/ifunaryexpr.rs:8:5: 
> internal compiler error: 'verify
> _gimple' failed
> 0xf38fbd verify_gimple_in_seq(gimple*)
> ../../gccrs/gcc/tree-cfg.c:5157
> 0xc72346 gimplify_body(tree_node*, bool)
> ../../gccrs/gcc/gimplify.c:15401
> 0xc724cd gimplify_function_tree(tree_node*)
> ../../gccrs/gcc/gimplify.c:15472
> 0xab0dc7 cgraph_node::analyze()
> ../../gccrs/gcc/cgraphunit.c:670
> 0xab38b7 analyze_functions
> ../../gccrs/gcc/cgraphunit.c:1236
> 0xab454d symbol_table::finalize_compilation_unit()
> ../../gccrs/gcc/cgraphunit.c:2514
> 
> So, my patch created bad gimple. I'll try to track it down.

I figured it out. There was another bug in the ComparisonExpr type
checker the result is a bool type but the argument types only need to
have compatible types, they don't have to be bools.

Fixed patch attached. Also on
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=bools_eq

Cheers,

Mark>From 5b229ddbf41c9e74fcce930c26101c1d34a5c9d1 Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Sat, 14 Aug 2021 23:38:11 +0200
Subject: [PATCH] Use builtin bool instead of creating new bool types for
 ComparisonExpr

The TypeCheckExpr creates a new TyTy::BoolType for a
ComparisonExpr. This new BoolType is unknown to TyTyResolveCompile
which causes a crash when trying to compile the inferred new
BoolType. Resolve this by looking up the builtin bool type.
The new "bools_eq.rs" testcase uses several bools which show
this issue.

Also the lhs and rhs types need to be compatible, but don't
need to be bool type themselves. So don't append the reference
to the inferred type. The existing "ifunaryexpr.rs" testcase
will fail without this fix.
---
 gcc/rust/typecheck/rust-hir-type-check-expr.h  |  6 ++
 gcc/testsuite/rust/compile/torture/bools_eq.rs | 18 ++
 2 files changed, 20 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/torture/bools_eq.rs

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index d88cb0b7f1d..a833822e9b3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -630,10 +630,8 @@ public:
 if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR)
   return;
 
-// we expect this to be
-infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ());
-infered->append_reference (lhs->get_ref ());
-infered->append_reference (rhs->get_ref ());
+bool ok = context->lookup_builtin ("bool", &infered);
+rust_assert (ok);
   }
 
   void visit (HIR::LazyBooleanExpr &expr) override
diff --git a/gcc/testsuite/rust/compile/torture/bools_eq.rs b/gcc/testsuite/rust/compile/torture/bools_eq.rs
new file mode 100644
index 000..965127b5d54
--- /dev/null
+++ b/gcc/testsuite/rust/compile/torture/bools_eq.rs
@@ -0,0 +1,18 @@
+extern "C"
+{
+  fn abort ();
+}
+
+fn beq (a: bool, b: bool) -> bool
+{
+  let bools_eq = a == b;
+  bools_eq
+}
+
+pub fn main ()
+{
+  let a = true;
+  let b = false;
+  let r = beq (a, b);
+  if r { unsafe { abort (); } }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Reject duplicate field names in structs and unions.

2021-08-21 Thread Mark Wielaard
Odd things happen if structs or unions have duplicate field names.
Emit an error when lowering an struct/union item or declaration
statement and a duplicate field name is detected.  A new testcase
'dup_fields.rs' checks an error is actually produced.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=dup_fields

 gcc/rust/hir/rust-ast-lower-item.h   | 27 
 gcc/rust/hir/rust-ast-lower-stmt.h   | 27 
 gcc/testsuite/rust/compile/dup_fields.rs | 23 
 3 files changed, 77 insertions(+)
 create mode 100644 gcc/testsuite/rust/compile/dup_fields.rs

diff --git a/gcc/rust/hir/rust-ast-lower-item.h 
b/gcc/rust/hir/rust-ast-lower-item.h
index bcf83ee63b6..b324d0b5b8b 100644
--- a/gcc/rust/hir/rust-ast-lower-item.h
+++ b/gcc/rust/hir/rust-ast-lower-item.h
@@ -176,6 +176,25 @@ public:
   struct_decl.get_locus ());
   }
 
+  /* Checks whether the name of a field already exists.  Returns true
+ and produces an error if so.  */
+  static bool struct_field_name_exists (std::vector &fields,
+   HIR::StructField &new_field)
+  {
+for (auto &field : fields)
+  {
+   if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
+ {
+   RichLocation r (new_field.get_locus ());
+   r.add_range (field.get_locus ());
+   rust_error_at (r, "duplicate field name %qs",
+  field.get_field_name ().c_str ());
+   return true;
+ }
+  }
+return false;
+  }
+
   void visit (AST::StructStruct &struct_decl) override
   {
 std::vector > generic_params;
@@ -206,6 +225,10 @@ public:
 std::unique_ptr (type), vis,
 field.get_locus (),
 field.get_outer_attrs ());
+
+  if (struct_field_name_exists (fields, translated_field))
+   return false;
+
   fields.push_back (std::move (translated_field));
   return true;
 });
@@ -258,6 +281,10 @@ public:
   std::unique_ptr (type),
   vis, variant.get_locus (),
   variant.get_outer_attrs ());
+
+  if (struct_field_name_exists (variants, translated_variant))
+   return false;
+
   variants.push_back (std::move (translated_variant));
   return true;
 });
diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h 
b/gcc/rust/hir/rust-ast-lower-stmt.h
index c4c00ac0bee..1e72c8a2023 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -161,6 +161,25 @@ public:
   struct_decl.get_locus ());
   }
 
+  /* Checks whether the name of a field already exists.  Returns true
+ and produces an error if so.  */
+  static bool struct_field_name_exists (std::vector &fields,
+   HIR::StructField &new_field)
+  {
+for (auto &field : fields)
+  {
+   if (field.get_field_name ().compare (new_field.get_field_name ()) == 0)
+ {
+   RichLocation r (new_field.get_locus ());
+   r.add_range (field.get_locus ());
+   rust_error_at (r, "duplicate field name %qs",
+  field.get_field_name ().c_str ());
+   return true;
+ }
+  }
+return false;
+  }
+
   void visit (AST::StructStruct &struct_decl) override
   {
 std::vector > generic_params;
@@ -191,6 +210,10 @@ public:
 std::unique_ptr (type), vis,
 field.get_locus (),
 field.get_outer_attrs ());
+
+  if (struct_field_name_exists (fields, translated_field))
+   return false;
+
   fields.push_back (std::move (translated_field));
   return true;
 });
@@ -242,6 +265,10 @@ public:
   std::unique_ptr (type),
   vis, variant.get_locus (),
   variant.get_outer_attrs ());
+
+  if (struct_field_name_exists (variants, translated_variant))
+   return false;
+
   variants.push_back (std::move (translated_variant));
   return true;
 });
diff --git a/gcc/testsuite/rust/compile/dup_fields.rs 
b/gcc/testsuite/rust/compile/dup_fields.rs
new file mode 100644
index 000..ab39955eca0
--- /dev/null
+++ b/gcc/testsuite/rust/compile/dup_fields.rs
@@ -0,0 +1,23 @@
+struct S { a: i32, b: i32, c: u8, a: i128 }
+// { dg-error "duplicate field" "" { target *-*-* } .-1 }
+
+union U
+  {
+a: i32,
+b: i32,
+c: u8,
+b: char // { dg-error "duplicate field" "" { target *-*-* } }
+  }
+
+fn main ()
+{
+  struct SS { alpha: i32, beta: i32, gamma: u8, gamma: i128 }
+  // { dg-error "duplicate field" "" { target 

Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-08-22 Thread Mark Wielaard
Hi,

On Sun, Aug 22, 2021 at 03:55:47PM +, build...@builder.wildebeest.org wrote:
> The Buildbot has detected a new failure on builder gccrust-debian-arm64 while 
> building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/58/builds/355

This seems to have been a transient build failure caused by:

commit d5dd96322b588ffcf5bdd2fe0e3a14eb217d75b2
Author: Philip Herron 
Date:   Sun Aug 22 13:42:14 2021 +0100

Add Trait Resolver simple type-path lookup

Post type checking we need to be able to lookup trait references, but do
not need to resolve the trait with error messages. We simple want to look
it up if it exists.

../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:233:1: error: 
‘PathProbeImplTrait’ has not been declared
 PathProbeImplTrait::process_trait_impl_items_for_candidates ()
 ^~
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc: In function ‘void 
Rust::Resolver::process_trait_impl_items_for_candidates()’:
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:235:3: error: 
‘mappings’ was not declared in this scope
   mappings->iterate_impl_items (
   ^~~~
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:235:3: note: suggested 
alternative: ‘warning’
   mappings->iterate_impl_items (
   ^~~~
   warning
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc: In lambda function:
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:244:12: error: 
‘trait_reference’ was not declared in this scope
   if (!trait_reference->is_equal (*resolved))
^~~
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:244:12: note: 
suggested alternative: ‘TraitReference’
   if (!trait_reference->is_equal (*resolved))
^~~
TraitReference
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:247:7: error: 
‘process_impl_item_candidate’ was not declared in this scope
   process_impl_item_candidate (id, item, impl);
   ^~~
../../gccrs/gcc/rust/typecheck/rust-hir-trait-resolve.cc:247:7: note: suggested 
alternative: ‘process_trait_impl_items_for_candidates’
   process_impl_item_candidate (id, item, impl);
   ^~~
   process_trait_impl_items_for_candidates
make[2]: *** [../../gccrs/gcc/rust/Make-lang.in:301: 
rust/rust-hir-trait-resolve.o] Error 1

But resolved by the next commit:

commit a6c8bd136dd4e89752eaec6415ba651f3cd73b9e
Author: Philip Herron 
Date:   Sun Aug 22 13:44:46 2021 +0100

Add impl-trait path probe helper

This adds a probe to lookup candidates for a segment for any impl block
for this receiver and trait. This simplifies some query based compilation
code. When the item is resolved to a trait item but might be overriden by
a reciever impl block instead.

Not all buildbot workers have finished building all the latest commits though.

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Get rid of get_locus_slow

2021-08-25 Thread Mark Wielaard
In various places there was the following hack:

  /* HACK: slow way of getting location from base expression through
 virtual methods. */
  virtual Location get_locus_slow () const { return Location (); }

The problem with get_locus_slow () is that if a subclass didn't
override it then there was no real location. get_locus_slow was
missing for Module, ExternCrate, UseDeclaration, Function, TypeAlias,
StructStruct, TupleStruct, Enum, Union, ConstantItem, StaticItem,
Trait, ImplBlock, ExternBlock, EmptyStmt, ExprStmtWithoutBlock and
ExprStmtWithBlock. All do have a get_locus () function.

Simply replace the get_locus_slow virtual method with a real virtual
Location get_locus () const = 0 method so we know if something
really doesn't have a location. This was only the case for
MacroRulesDefinition.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=no-get-locus-slow

 gcc/rust/ast/rust-ast.h   |  27 +-
 gcc/rust/ast/rust-expr.h  |  39 +--
 gcc/rust/ast/rust-item.h  |  10 -
 gcc/rust/ast/rust-macro.h |   3 +-
 gcc/rust/ast/rust-path.h  |   4 -
 gcc/rust/ast/rust-pattern.h   |  10 -
 gcc/rust/ast/rust-stmt.h  |   6 -
 gcc/rust/ast/rust-type.h  |  15 -
 gcc/rust/backend/rust-compile-expr.h  |   4 +-
 gcc/rust/backend/rust-compile.cc  |   4 +-
 gcc/rust/expand/rust-macro-expand.cc  | 299 +-
 gcc/rust/hir/rust-ast-lower-expr.h|   5 +-
 gcc/rust/hir/rust-ast-lower-item.h|   2 +-
 .../hir/rust-ast-lower-struct-field-expr.h|   3 +-
 gcc/rust/hir/rust-ast-lower-type.h|   8 +-
 gcc/rust/hir/rust-ast-lower.cc|   4 +-
 gcc/rust/hir/tree/rust-hir-expr.h |  31 +-
 gcc/rust/hir/tree/rust-hir-item.h |   2 -
 gcc/rust/hir/tree/rust-hir-path.h |   2 -
 gcc/rust/hir/tree/rust-hir-stmt.h |   2 -
 gcc/rust/hir/tree/rust-hir-type.h |   2 -
 gcc/rust/hir/tree/rust-hir.h  |  17 +-
 gcc/rust/lint/rust-lint-marklive.cc   |   4 +-
 gcc/rust/parse/rust-parse-impl.h  |  88 +++---
 gcc/rust/resolve/rust-ast-resolve-item.h  |  12 +-
 gcc/rust/resolve/rust-ast-resolve-type.h  |   8 +-
 gcc/rust/resolve/rust-ast-verify-assignee.h   |   2 +-
 gcc/rust/typecheck/rust-hir-const-fold.h  |   4 +-
 gcc/rust/typecheck/rust-hir-type-check-expr.h |  19 +-
 gcc/rust/typecheck/rust-hir-type-check-type.h |   2 +-
 gcc/rust/typecheck/rust-hir-type-check.cc |  11 +-
 gcc/rust/typecheck/rust-tyty.cc   |  14 +-
 gcc/rust/util/rust-hir-map.cc |   4 +-
 33 files changed, 256 insertions(+), 411 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index e376488de8c..2b34b201970 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -816,9 +816,7 @@ public:
 
   virtual void accept_vis (ASTVisitor &vis) = 0;
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const { return Location (); }
+  virtual Location get_locus () const = 0;
 
   virtual void mark_for_strip () = 0;
   virtual bool is_marked_for_strip () const = 0;
@@ -885,9 +883,7 @@ public:
 
   virtual ~Expr () {}
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const { return Location (); }
+  virtual Location get_locus () const = 0;
 
   // HACK: strictly not needed, but faster than full downcast clone
   virtual bool is_expr_without_block () const = 0;
@@ -967,7 +963,6 @@ public:
   std::string as_string () const override { return ident; }
 
   Location get_locus () const { return locus; }
-  Location get_locus_slow () const final override { return get_locus (); }
 
   Identifier get_ident () const { return ident; }
 
@@ -1026,9 +1021,7 @@ public:
   virtual void mark_for_strip () {}
   virtual bool is_marked_for_strip () const { return false; }
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const = 0;
+  virtual Location get_locus () const = 0;
 
   virtual NodeId get_node_id () const { return node_id; }
 
@@ -1071,7 +1064,7 @@ public:
   virtual void mark_for_strip () {}
   virtual bool is_marked_for_strip () const { return false; }
 
-  virtual Location get_locus_slow () const = 0;
+  virtual Location get_locus () const = 0;
 
   NodeId get_node_id () const { return node_id; }
 
@@ -1128,7 +1121,7 @@ public:
 
   NodeId get_node_id () const { return node_id; }
 
-  virtual Location get_locus_slow () const = 0;
+  virtual Location get_locus () const = 0;
 
 protected:
   // Clone function implementation as pure virtual method
@@ -1187,8 +1180,6 @@ public:
 
   Location get_locus () const { return locu

Re: [PATCH] Get rid of get_locus_slow

2021-08-26 Thread Mark Wielaard
On Thu, Aug 26, 2021 at 10:31:06AM +0800, The Other wrote:

> The original point of the distinction between get_locus_slow() and
> get_locus() was to avoid the overhead of virtual function calls
> whenever possible, but still have a way to access locations from
> abstract base classes like Expr.

If only we had Traits :)

> As such, I’d at least make the overridden calls ‘final override’ in
> the hope that the compiler can optimise out the virtual call.

Yes, makes sense. I'll sent an updated patch.

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCHv2] Get rid of get_locus_slow

2021-08-26 Thread Mark Wielaard
In various places there was the following hack:

  /* HACK: slow way of getting location from base expression through
 virtual methods. */
  virtual Location get_locus_slow () const { return Location (); }

The problem with get_locus_slow () is that if a subclass didn't
override it then there was no real location. get_locus_slow was
missing for Module, ExternCrate, UseDeclaration, Function, TypeAlias,
StructStruct, TupleStruct, Enum, Union, ConstantItem, StaticItem,
Trait, ImplBlock, ExternBlock, EmptyStmt, ExprStmtWithoutBlock and
ExprStmtWithBlock. All do have a get_locus () function.

Simply replace the get_locus_slow virtual method with a real virtual
Location get_locus () const = 0 method so we know if something
really doesn't have a location. This was only the case for
MacroRulesDefinition.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=no-get-locus-slow

Changes in v2:

  - all replaced get_locus_slow -> get_locus methods are now marked
with final override

 gcc/rust/ast/rust-ast.h   |  35 +-
 gcc/rust/ast/rust-expr.h  | 109 +++
 gcc/rust/ast/rust-item.h  |  42 +--
 gcc/rust/ast/rust-macro.h |   5 +-
 gcc/rust/ast/rust-path.h  |  12 +-
 gcc/rust/ast/rust-pattern.h   |  26 +-
 gcc/rust/ast/rust-stmt.h  |  12 +-
 gcc/rust/ast/rust-type.h  |  43 +--
 gcc/rust/backend/rust-compile-expr.h  |   4 +-
 gcc/rust/backend/rust-compile.cc  |   4 +-
 gcc/rust/expand/rust-macro-expand.cc  | 299 +-
 gcc/rust/hir/rust-ast-lower-expr.h|   5 +-
 gcc/rust/hir/rust-ast-lower-item.h|   2 +-
 .../hir/rust-ast-lower-struct-field-expr.h|   3 +-
 gcc/rust/hir/rust-ast-lower-type.h|   8 +-
 gcc/rust/hir/rust-ast-lower.cc|   4 +-
 gcc/rust/hir/tree/rust-hir-expr.h |  89 ++
 gcc/rust/hir/tree/rust-hir-item.h |  30 +-
 gcc/rust/hir/tree/rust-hir-path.h |   6 +-
 gcc/rust/hir/tree/rust-hir-stmt.h |   8 +-
 gcc/rust/hir/tree/rust-hir-type.h |   4 +-
 gcc/rust/hir/tree/rust-hir.h  |  23 +-
 gcc/rust/lint/rust-lint-marklive.cc   |   4 +-
 gcc/rust/parse/rust-parse-impl.h  |  88 +++---
 gcc/rust/resolve/rust-ast-resolve-item.h  |  12 +-
 gcc/rust/resolve/rust-ast-resolve-type.h  |   8 +-
 gcc/rust/resolve/rust-ast-verify-assignee.h   |   2 +-
 gcc/rust/typecheck/rust-hir-const-fold.h  |   4 +-
 gcc/rust/typecheck/rust-hir-type-check-expr.h |  19 +-
 gcc/rust/typecheck/rust-hir-type-check-type.h |   2 +-
 gcc/rust/typecheck/rust-hir-type-check.cc |  11 +-
 gcc/rust/typecheck/rust-tyty.cc   |  14 +-
 gcc/rust/util/rust-hir-map.cc |   4 +-
 33 files changed, 393 insertions(+), 548 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index e376488de8c..2bfaeb1d364 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -816,9 +816,7 @@ public:
 
   virtual void accept_vis (ASTVisitor &vis) = 0;
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const { return Location (); }
+  virtual Location get_locus () const = 0;
 
   virtual void mark_for_strip () = 0;
   virtual bool is_marked_for_strip () const = 0;
@@ -885,9 +883,7 @@ public:
 
   virtual ~Expr () {}
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const { return Location (); }
+  virtual Location get_locus () const = 0;
 
   // HACK: strictly not needed, but faster than full downcast clone
   virtual bool is_expr_without_block () const = 0;
@@ -966,8 +962,7 @@ public:
 
   std::string as_string () const override { return ident; }
 
-  Location get_locus () const { return locus; }
-  Location get_locus_slow () const final override { return get_locus (); }
+  Location get_locus () const override final { return locus; }
 
   Identifier get_ident () const { return ident; }
 
@@ -1026,9 +1021,7 @@ public:
   virtual void mark_for_strip () {}
   virtual bool is_marked_for_strip () const { return false; }
 
-  /* HACK: slow way of getting location from base expression through virtual
-   * methods. */
-  virtual Location get_locus_slow () const = 0;
+  virtual Location get_locus () const = 0;
 
   virtual NodeId get_node_id () const { return node_id; }
 
@@ -1071,7 +1064,7 @@ public:
   virtual void mark_for_strip () {}
   virtual bool is_marked_for_strip () const { return false; }
 
-  virtual Location get_locus_slow () const = 0;
+  virtual Location get_locus () const = 0;
 
   NodeId get_node_id () const { return node_id; }
 
@@ -1128,7 +1121,7 @@ public:
 
   NodeId get_node_id () const { return node_id; }
 
-  virtual Location get_locus_slow () const = 0;

[PATCH 1/3] Use location when lowering TupleField

2021-08-28 Thread Mark Wielaard
---
 gcc/rust/hir/rust-ast-lower-stmt.h | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h 
b/gcc/rust/hir/rust-ast-lower-stmt.h
index 1e72c8a2023..fdd5041d602 100644
--- a/gcc/rust/hir/rust-ast-lower-stmt.h
+++ b/gcc/rust/hir/rust-ast-lower-stmt.h
@@ -133,12 +133,10 @@ public:
 mappings->get_next_localdef_id (
   crate_num));
 
-  // FIXME
-  // AST::TupleField is missing Location info
-  Location field_locus;
   HIR::TupleField translated_field (mapping,
std::unique_ptr (type), vis,
-   field_locus, field.get_outer_attrs ());
+   field.get_locus (),
+   field.get_outer_attrs ());
   fields.push_back (std::move (translated_field));
   return true;
 });
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 2/3] Replace HIRItem::get_impl_locus with HirItem::get_locus

2021-08-28 Thread Mark Wielaard
HIRItem::get_impl_locus wasn't used and all subclasses already
implement get_locus.
---
 gcc/rust/hir/tree/rust-hir-item.h | 6 --
 gcc/rust/hir/tree/rust-hir.h  | 2 +-
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/gcc/rust/hir/tree/rust-hir-item.h 
b/gcc/rust/hir/tree/rust-hir-item.h
index 99fc91de117..7a2c2676825 100644
--- a/gcc/rust/hir/tree/rust-hir-item.h
+++ b/gcc/rust/hir/tree/rust-hir-item.h
@@ -1126,8 +1126,6 @@ public:
 
   Location get_locus () const override final { return locus; }
 
-  Location get_impl_locus () const final { return get_locus (); }
-
   void accept_vis (HIRVisitor &vis) override;
 
   Analysis::NodeMapping get_impl_mappings () const override
@@ -1268,8 +1266,6 @@ public:
 
   Location get_locus () const override final { return locus; }
 
-  Location get_impl_locus () const final { return get_locus (); }
-
   void accept_vis (HIRVisitor &vis) override;
 
   std::vector > &get_generic_params ()
@@ -2017,8 +2013,6 @@ public:
 
   Location get_locus () const override final { return locus; }
 
-  Location get_impl_locus () const final { return get_locus (); }
-
   void accept_vis (HIRVisitor &vis) override;
 
   Type *get_type () { return type.get (); }
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index b994d063452..8ba6308fdea 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -663,7 +663,7 @@ public:
 
   virtual Analysis::NodeMapping get_impl_mappings () const = 0;
 
-  virtual Location get_impl_locus () const = 0;
+  virtual Location get_locus () const = 0;
 };
 
 // A crate HIR object - holds all the data for a single compilation unit
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


A few more location patches

2021-08-28 Thread Mark Wielaard
Hi,

Here are a couple of little patches to improve or simplify locations a
bit:

 [PATCH 1/3] Use location when lowering TupleField
 [PATCH 2/3] Replace HIRItem::get_impl_locus with HirItem::get_locus
 [PATCH 3/3] Remove GetLocusFromImplItem visitor

Also on https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=locus

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 3/3] Remove GetLocusFromImplItem visitor

2021-08-28 Thread Mark Wielaard
Simply use get_locus () on the ImplItem.
Both the generics7.rs and generics8.rs testcase still pass.
---
 .../rust-hir-inherent-impl-overlap.h  | 45 +--
 1 file changed, 2 insertions(+), 43 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h 
b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 134d3141d38..9a2c7fe3c07 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -64,39 +64,6 @@ private:
   std::string &result;
 };
 
-class GetLocusFromImplItem : public TypeCheckBase
-{
-  using Rust::Resolver::TypeCheckBase::visit;
-
-public:
-  static bool Resolve (HIR::ImplItem *query, Location &locus)
-  {
-GetLocusFromImplItem resolver (locus);
-query->accept_vis (resolver);
-return resolver.ok;
-  }
-
-  void visit (HIR::ConstantItem &constant) override
-  {
-ok = true;
-locus = constant.get_locus ();
-  }
-
-  void visit (HIR::Function &function) override
-  {
-ok = true;
-locus = function.get_locus ();
-  }
-
-private:
-  GetLocusFromImplItem (Location &locus)
-: TypeCheckBase (), ok (false), locus (locus)
-  {}
-
-  bool ok;
-  Location &locus;
-};
-
 class OverlappingImplItemPass : public TypeCheckBase
 {
   using Rust::Resolver::TypeCheckBase::visit;
@@ -185,16 +152,8 @@ public:
   void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup,
   const std::string &name)
   {
-Location qlocus; // query
-bool ok = GetLocusFromImplItem::Resolve (query, qlocus);
-rust_assert (ok);
-
-Location dlocus; // dup
-ok = GetLocusFromImplItem::Resolve (dup, dlocus);
-rust_assert (ok);
-
-RichLocation r (qlocus);
-r.add_range (dlocus);
+RichLocation r (query->get_locus ());
+r.add_range (dup->get_locus ());
 rust_error_at (r, "duplicate definitions with name %s", name.c_str ());
   }
 
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Cleanup some StructExpr related classes

2021-08-31 Thread Mark Wielaard
Hi,

There are various Structure Expressions that don't actually "exist"
because they are syntactically equivalent to other constructs. So we
never really construct or use these classes. But they are still listed
in various visitors, which is somewhat confusing. Removing the AST and
HIR variants of these classes really cleans up the code IMHO.

The following 3 patches can also be found on
https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=structexpr

[PATCH 1/3] StructExprTuple doesn't really exist
[PATCH 2/3] StructExprUnit doesn't really exist
[PATCH 3/3] Remove Enumaration Expression, EnumExpr, classes

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/3] StructExprTuple doesn't really exist

2021-08-31 Thread Mark Wielaard
A StructExprTuple is parsed as a CallExpr. Both (can) start with a
PathInExpression followed by zero or more Expressions between
brackets.

Only, after type checking, when actually generating gcc generic trees
is a distinction made between a function call or tuple constructor.

Remove the AST and HIR StructExprTuple classes which are never used.
---
 gcc/rust/ast/rust-ast-full-decls.h|  1 -
 gcc/rust/ast/rust-ast-full-test.cc| 44 ---
 gcc/rust/ast/rust-ast-visitor.h   |  1 -
 gcc/rust/ast/rust-expr.h  | 69 -
 gcc/rust/backend/rust-compile-base.h  |  1 -
 gcc/rust/expand/rust-macro-expand.cc  | 30 
 gcc/rust/hir/rust-ast-lower-base.h|  1 -
 gcc/rust/hir/tree/rust-hir-expr.h | 74 ---
 gcc/rust/hir/tree/rust-hir-full-decls.h   |  1 -
 gcc/rust/hir/tree/rust-hir-full-test.cc   | 59 ---
 gcc/rust/hir/tree/rust-hir-visitor.h  |  1 -
 gcc/rust/lint/rust-lint-marklive-base.h   |  1 -
 gcc/rust/resolve/rust-ast-resolve-base.h  |  1 -
 gcc/rust/typecheck/rust-hir-const-fold-base.h |  1 -
 gcc/rust/typecheck/rust-hir-type-check-base.h |  1 -
 gcc/rust/typecheck/rust-hir-type-check-util.h |  1 -
 16 files changed, 287 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 7644dfe240c..205da881ed4 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -109,7 +109,6 @@ class StructExprFieldIdentifierValue;
 class StructExprFieldIndexValue;
 class StructExprStructFields;
 class StructExprStructBase;
-class StructExprTuple;
 class StructExprUnit;
 class EnumVariantExpr;
 class EnumExprField;
diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index c18d4c4fd74..1a447ae0198 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -3239,44 +3239,6 @@ StructExpr::as_string () const
   return str;
 }
 
-std::string
-StructExprTuple::as_string () const
-{
-  std::string str = StructExpr::as_string ();
-
-  if (exprs.empty ())
-{
-  str += "()";
-}
-  else
-{
-  auto i = exprs.begin ();
-  auto e = exprs.end ();
-
-  // debug - null pointer check
-  if (*i == nullptr)
-   return "ERROR_MARK_STRING - nullptr struct expr tuple field";
-
-  str += '(';
-  for (; i != e; i++)
-   {
- str += (*i)->as_string ();
- if (e != i + 1)
-   str += ", ";
-   }
-  str += ')';
-}
-
-  indent_spaces (enter);
-  indent_spaces (enter);
-  // inner attributes
-  str += append_attributes (inner_attrs, INNER);
-  indent_spaces (out);
-  indent_spaces (out);
-
-  return str;
-}
-
 std::string
 StructExprStruct::as_string () const
 {
@@ -5222,12 +5184,6 @@ StructExprStructBase::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
-void
-StructExprTuple::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 StructExprUnit::accept_vis (ASTVisitor &vis)
 {
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index e0de54d7a98..30e156facbb 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -93,7 +93,6 @@ public:
   virtual void visit (StructExprFieldIndexValue &field) = 0;
   virtual void visit (StructExprStructFields &expr) = 0;
   virtual void visit (StructExprStructBase &expr) = 0;
-  virtual void visit (StructExprTuple &expr) = 0;
   virtual void visit (StructExprUnit &expr) = 0;
   // virtual void visit(EnumExprField& field) = 0;
   virtual void visit (EnumExprFieldIdentifier &field) = 0;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 88e45fef330..effdb230319 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1852,75 +1852,6 @@ protected:
   }
 };
 
-// AST node of a tuple struct creator
-class StructExprTuple : public StructExpr
-{
-  std::vector inner_attrs;
-  std::vector > exprs;
-
-  Location locus;
-
-public:
-  std::string as_string () const override;
-
-  const std::vector &get_inner_attrs () const { return inner_attrs; 
}
-  std::vector &get_inner_attrs () { return inner_attrs; }
-
-  StructExprTuple (PathInExpression struct_path,
-  std::vector > tuple_exprs,
-  std::vector inner_attribs,
-  std::vector outer_attribs, Location locus)
-: StructExpr (std::move (struct_path), std::move (outer_attribs)),
-  inner_attrs (std::move (inner_attribs)), exprs (std::move (tuple_exprs)),
-  locus (locus)
-  {}
-
-  // copy constructor with vector clone
-  StructExprTuple (StructExprTuple const &other)
-: StructExpr (other), inner_attrs (other.inner_attrs), locus (other.locus)
-  {
-exprs.reserve (other.exprs.size ());
-for (const auto &e : other.exprs)
-  exprs.push_back (e->clone_expr ());
-  }
-
-  // overloaded assignment operator with vector

[PATCH 2/3] StructExprUnit doesn't really exist

2021-08-31 Thread Mark Wielaard
A StructExprUnit is parsed as an IdentifierExpr. An IdentifierExpr,
which is what we call a single segment PathInExpression.

After type checking, when generating gcc generic trees, if the
IdentifierExpr is a type reference (which must be a unit struct), then
a unit expression is generated.

Remove the AST and HIR StructExprUnit classes which are never used.
---
 gcc/rust/ast/rust-ast-full-decls.h|  1 -
 gcc/rust/ast/rust-ast-full-test.cc|  6 
 gcc/rust/ast/rust-ast-visitor.h   |  1 -
 gcc/rust/ast/rust-expr.h  | 30 
 gcc/rust/backend/rust-compile-base.h  |  1 -
 gcc/rust/expand/rust-macro-expand.cc  | 17 -
 gcc/rust/hir/rust-ast-lower-base.h|  1 -
 gcc/rust/hir/tree/rust-hir-expr.h | 35 ---
 gcc/rust/hir/tree/rust-hir-full-decls.h   |  1 -
 gcc/rust/hir/tree/rust-hir-full-test.cc   |  6 
 gcc/rust/hir/tree/rust-hir-visitor.h  |  1 -
 gcc/rust/lint/rust-lint-marklive-base.h   |  1 -
 gcc/rust/resolve/rust-ast-resolve-base.h  |  1 -
 gcc/rust/typecheck/rust-hir-const-fold-base.h |  1 -
 gcc/rust/typecheck/rust-hir-type-check-base.h |  1 -
 gcc/rust/typecheck/rust-hir-type-check-util.h |  1 -
 16 files changed, 105 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 205da881ed4..09f879c312f 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -109,7 +109,6 @@ class StructExprFieldIdentifierValue;
 class StructExprFieldIndexValue;
 class StructExprStructFields;
 class StructExprStructBase;
-class StructExprUnit;
 class EnumVariantExpr;
 class EnumExprField;
 class EnumExprFieldIdentifier;
diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index 1a447ae0198..8ffc1b20e70 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -5184,12 +5184,6 @@ StructExprStructBase::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
-void
-StructExprUnit::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 EnumExprFieldIdentifier::accept_vis (ASTVisitor &vis)
 {
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index 30e156facbb..ffd1d2d3161 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -93,7 +93,6 @@ public:
   virtual void visit (StructExprFieldIndexValue &field) = 0;
   virtual void visit (StructExprStructFields &expr) = 0;
   virtual void visit (StructExprStructBase &expr) = 0;
-  virtual void visit (StructExprUnit &expr) = 0;
   // virtual void visit(EnumExprField& field) = 0;
   virtual void visit (EnumExprFieldIdentifier &field) = 0;
   virtual void visit (EnumExprFieldIdentifierValue &field) = 0;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index effdb230319..a6882c75e82 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1852,36 +1852,6 @@ protected:
   }
 };
 
-// AST node of a "unit" struct creator (no fields and no braces)
-class StructExprUnit : public StructExpr
-{
-  Location locus;
-
-public:
-  std::string as_string () const override
-  {
-return get_struct_name ().as_string ();
-  }
-
-  StructExprUnit (PathInExpression struct_path,
- std::vector outer_attribs, Location locus)
-: StructExpr (std::move (struct_path), std::move (outer_attribs)),
-  locus (locus)
-  {}
-
-  Location get_locus () const override final { return locus; }
-
-  void accept_vis (ASTVisitor &vis) override;
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  StructExprUnit *clone_expr_without_block_impl () const override
-  {
-return new StructExprUnit (*this);
-  }
-};
-
 // aka EnumerationVariantExpr
 // Base AST node representing creation of an enum variant instance - abstract
 class EnumVariantExpr : public ExprWithoutBlock
diff --git a/gcc/rust/backend/rust-compile-base.h 
b/gcc/rust/backend/rust-compile-base.h
index d7cc009133b..2ce7369ecde 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -72,7 +72,6 @@ public:
   virtual void visit (HIR::StructExprFieldIndexValue &field) {}
   virtual void visit (HIR::StructExprStructFields &expr) {}
   virtual void visit (HIR::StructExprStructBase &expr) {}
-  virtual void visit (HIR::StructExprUnit &expr) {}
   // virtual void visit(EnumExprField& field) {}
   virtual void visit (HIR::EnumExprFieldIdentifier &field) {}
   virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {}
diff --git a/gcc/rust/expand/rust-macro-expand.cc 
b/gcc/rust/expand/rust-macro-expand.cc
index 060d41ad04c..65b2ea06039 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -939,23 +939,6 @@ public:
 "cannot strip expression in this position - outer "
  

[PATCH 3/3] Remove Enumaration Expression, EnumExpr, classes

2021-08-31 Thread Mark Wielaard
An Enumaration Expression is just like a Struct Expression. Old
versions of the Rust Reference described them separately. But since
they are syntactically exactly like a Struct Expression they are never
actually parsed. A Struct Expression can also be used to initialize
enums (and unions).

Remove the AST and HIR classes EnumExprField, EnumExprFieldIdentifier,
EnumExprFieldWithVal, EnumExprFieldIdentifierValue,
EnumExprFieldIndexValue, EnumExprStruct, EnumExprTuple,
EnumExprFieldless and EnumVariantExpr.
---
 gcc/rust/ast/rust-ast-full-decls.h|   9 -
 gcc/rust/ast/rust-ast-full-test.cc|  78 
 gcc/rust/ast/rust-ast-visitor.h   |   7 -
 gcc/rust/ast/rust-expr.h  | 346 --
 gcc/rust/backend/rust-compile-base.h  |   7 -
 gcc/rust/expand/rust-macro-expand.cc  |  89 -
 gcc/rust/hir/rust-ast-lower-base.h|   7 -
 gcc/rust/hir/tree/rust-hir-expr.h | 326 -
 gcc/rust/hir/tree/rust-hir-full-decls.h   |   9 -
 gcc/rust/hir/tree/rust-hir-full-test.cc   |  36 --
 gcc/rust/hir/tree/rust-hir-visitor.h  |   6 -
 gcc/rust/lint/rust-lint-marklive-base.h   |   7 -
 gcc/rust/resolve/rust-ast-resolve-base.h  |   6 -
 gcc/rust/typecheck/rust-hir-const-fold-base.h |   7 -
 gcc/rust/typecheck/rust-hir-type-check-base.h |   7 -
 gcc/rust/typecheck/rust-hir-type-check-util.h |   7 -
 16 files changed, 954 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-decls.h 
b/gcc/rust/ast/rust-ast-full-decls.h
index 09f879c312f..2be7e777234 100644
--- a/gcc/rust/ast/rust-ast-full-decls.h
+++ b/gcc/rust/ast/rust-ast-full-decls.h
@@ -109,15 +109,6 @@ class StructExprFieldIdentifierValue;
 class StructExprFieldIndexValue;
 class StructExprStructFields;
 class StructExprStructBase;
-class EnumVariantExpr;
-class EnumExprField;
-class EnumExprFieldIdentifier;
-class EnumExprFieldWithVal;
-class EnumExprFieldIdentifierValue;
-class EnumExprFieldIndexValue;
-class EnumExprStruct;
-class EnumExprTuple;
-class EnumExprFieldless;
 class CallExpr;
 class MethodCallExpr;
 class FieldAccessExpr;
diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index 8ffc1b20e70..6241710226d 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -3308,48 +3308,6 @@ StructExprStructFields::as_string () const
   return str;
 }
 
-std::string
-EnumExprStruct::as_string () const
-{
-  std::string str ("EnumExprStruct (or subclass): ");
-
-  str += "\n Path: " + get_enum_variant_path ().as_string ();
-
-  str += "\n Fields: ";
-  if (fields.empty ())
-{
-  str += "none";
-}
-  else
-{
-  for (const auto &field : fields)
-   str += "\n  " + field->as_string ();
-}
-
-  return str;
-}
-
-std::string
-EnumExprFieldWithVal::as_string () const
-{
-  // used to get value string
-  return value->as_string ();
-}
-
-std::string
-EnumExprFieldIdentifierValue::as_string () const
-{
-  // TODO: rewrite to work with non-linearisable exprs
-  return field_name + " : " + EnumExprFieldWithVal::as_string ();
-}
-
-std::string
-EnumExprFieldIndexValue::as_string () const
-{
-  // TODO: rewrite to work with non-linearisable exprs
-  return std::to_string (index) + " : " + EnumExprFieldWithVal::as_string ();
-}
-
 std::string
 EnumItem::as_string () const
 {
@@ -5184,42 +5142,6 @@ StructExprStructBase::accept_vis (ASTVisitor &vis)
   vis.visit (*this);
 }
 
-void
-EnumExprFieldIdentifier::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-EnumExprFieldIdentifierValue::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-EnumExprFieldIndexValue::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-EnumExprStruct::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-EnumExprTuple::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-EnumExprFieldless::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 CallExpr::accept_vis (ASTVisitor &vis)
 {
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index ffd1d2d3161..15bf0864ddb 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -93,13 +93,6 @@ public:
   virtual void visit (StructExprFieldIndexValue &field) = 0;
   virtual void visit (StructExprStructFields &expr) = 0;
   virtual void visit (StructExprStructBase &expr) = 0;
-  // virtual void visit(EnumExprField& field) = 0;
-  virtual void visit (EnumExprFieldIdentifier &field) = 0;
-  virtual void visit (EnumExprFieldIdentifierValue &field) = 0;
-  virtual void visit (EnumExprFieldIndexValue &field) = 0;
-  virtual void visit (EnumExprStruct &expr) = 0;
-  virtual void visit (EnumExprTuple &expr) = 0;
-  virtual void visit (EnumExprFieldless &expr) = 0;
   virtual void visit (CallExpr &expr) = 0;
   virtual void visit (MethodCallExpr &expr) = 0;
   virtual void visit (FieldAccessExpr &expr) = 0;
diff 

Re: Cleanup some StructExpr related classes

2021-09-01 Thread Mark Wielaard
Hi,

On Wed, Sep 01, 2021 at 11:11:46AM +0100, Philip Herron wrote:
> This is fantastic work Mar. This brings us closer to the AST structures of
> rustc and does simplify a lot of the analysis within the compiler.
> https://doc.rust-lang.org/nightly/reference/expressions/struct-expr.html

The reference does change from time to time. The older one did
describe various constructs that the newer does and for some it still
has comments saying some construct doesn't really construct, like the
tuple expression, which is simply a call (constructor) expression.  I
don't know if there is some kind of change log for the Rust reference.

Note that there are some more StructExpr cleanups at:
https://github.com/Rust-GCC/gccrs/pull/405
Which might be nice to finish.

> I agree the HIR cleanup will also help reduce a lot of duplication of code
> and visitors. It might mean we get alot of enum stuff for free potentially.

Potentially yes, but in practice enum item variants are different
enough to require lots of new code. I have patches for the parser,
resolver, and ast-hir-lowering and working on type-checking. One
tricky issue is that references to an enum item are paths with the
enum name first and the enum item second (Enum::Item). Which is
somewhat more complex than the IdentifierExpr. Another is that a
struct has one constructor, an enum has multiple (depending on the
enum item variant). So you need to add variants to the ADTType.

Work in progress at
https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=enums
cleaned up patches (that I hope are correct) at
https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=enums2

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Cleanup some StructExpr related classes

2021-09-05 Thread Mark Wielaard
Hi Philip,

On Thu, Sep 02, 2021 at 02:23:33PM +0100, Philip Herron wrote:
> I've been reviewing your branch a bit and noticed this commit
> https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=enums&id=84d27b926e09ef44dd94be20c97d72bd4b865c40
> which I really like. I wasn't sure what was the best way to interact with
> the AST which contained unique_ptr's to things so I initially added little
> lambda's but these don't really help anything at all other than make it
> more confusing to work with. So feel free to create patches to remove those.

I wasn't sure whether to replicate this for the HIR classes, so at
first I did it with a lambda, but found that not very nice. So instead
I added simple accessors for the fields vector which are the used in
in a simple for loop using get () on the elements. If you also like
that better I can change the AST classes to do the same thing.

> I also noticed quite a few test cases already are these compiling?

Yes, but they are all "negative" tests. I mean, that they check for
errors. After resolving we can check for unused enum item
warnings. After lowering we can detect bad visibility and duplicate
fields in struct variants. And after typechecking (not finished yet)
we can check the denominators of fieldless enums are unique (and
aren't too big).

> you have to add much to the rust-gcc.cc wrapper for the enum type?

I am still stuck at the type check pass. So haven't actually gotten to
that part.

I'll sent the parser, resolve and hit lowering bits, which include the
test cases.

These patches are also on
https://code.wildebeest.org/git/user/mjw/gccrs/log/?h=enums2

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH 1/3] Parse optional visibility for enum item

2021-09-05 Thread Mark Wielaard
Syntactically enum items can have a visibility. The visibility has to
be removed (through a cfg attribute or macro) before they get lowered.
The semantic checking will be done when we implement lowering enum items.

Make the AST EnumItem class a VisItem. This simplifies things a little
for cloning items, handling outer attributes and will help when adding
EnumItem (sub)classes to AST visitors (so they can be handled as
Items). Also add a get_identifier method to Enum and EnumItem.
---
 gcc/rust/ast/rust-ast-full-test.cc |  6 ++--
 gcc/rust/ast/rust-item.h   | 58 +++---
 gcc/rust/parse/rust-parse-impl.h   | 12 ---
 3 files changed, 38 insertions(+), 38 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-full-test.cc 
b/gcc/rust/ast/rust-ast-full-test.cc
index 6241710226d..2477d7400a7 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -3311,10 +3311,8 @@ StructExprStructFields::as_string () const
 std::string
 EnumItem::as_string () const
 {
-  // outer attributes
-  std::string str = append_attributes (outer_attrs, OUTER);
-
-  str += "\n" + variant_name;
+  std::string str = VisItem::as_string ();
+  str += variant_name;
 
   return str;
 }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 0578329f54b..881a888f092 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -2119,12 +2119,10 @@ protected:
 };
 
 /* An item used in an "enum" tagged union - not abstract: base represents a
- * name-only enum */
-class EnumItem
+ * name-only enum. EnumItems (variants) syntactically allow a Visibility
+ * annotation. */
+class EnumItem : public VisItem
 {
-  // bool has_attrs;
-  std::vector outer_attrs;
-
   Identifier variant_name;
 
   Location locus;
@@ -2132,19 +2130,16 @@ class EnumItem
 public:
   virtual ~EnumItem () {}
 
-  // Returns whether enum item has outer attributes.
-  bool has_outer_attrs () const { return !outer_attrs.empty (); }
-
-  EnumItem (Identifier variant_name, std::vector outer_attrs,
-   Location locus)
-: outer_attrs (std::move (outer_attrs)),
+  EnumItem (Identifier variant_name, Visibility vis,
+   std::vector outer_attrs, Location locus)
+: VisItem (std::move (vis), std::move (outer_attrs)),
   variant_name (std::move (variant_name)), locus (locus)
   {}
 
   // Unique pointer custom clone function
   std::unique_ptr clone_enum_item () const
   {
-return std::unique_ptr (clone_enum_item_impl ());
+return std::unique_ptr (clone_item_impl ());
   }
 
   virtual std::string as_string () const;
@@ -2152,20 +2147,16 @@ public:
   // not pure virtual as not abstract
   virtual void accept_vis (ASTVisitor &vis);
 
+  Location get_locus () const { return locus; }
+
+  Identifier get_identifier () const { return variant_name; }
+
   // Based on idea that name is never empty.
   void mark_for_strip () { variant_name = ""; }
   bool is_marked_for_strip () const { return variant_name.empty (); }
 
-  // TODO: this mutable getter seems really dodgy. Think up better way.
-  std::vector &get_outer_attrs () { return outer_attrs; }
-  const std::vector &get_outer_attrs () const { return outer_attrs; 
}
-
 protected:
-  // Clone function implementation as (not pure) virtual method
-  virtual EnumItem *clone_enum_item_impl () const
-  {
-return new EnumItem (*this);
-  }
+  EnumItem *clone_item_impl () const override { return new EnumItem (*this); }
 };
 
 // A tuple item used in an "enum" tagged union
@@ -2178,9 +2169,11 @@ public:
   // Returns whether tuple enum item has tuple fields.
   bool has_tuple_fields () const { return !tuple_fields.empty (); }
 
-  EnumItemTuple (Identifier variant_name, std::vector tuple_fields,
+  EnumItemTuple (Identifier variant_name, Visibility vis,
+std::vector tuple_fields,
 std::vector outer_attrs, Location locus)
-: EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+: EnumItem (std::move (variant_name), std::move (vis),
+   std::move (outer_attrs), locus),
   tuple_fields (std::move (tuple_fields))
   {}
 
@@ -2197,7 +2190,7 @@ public:
 
 protected:
   // Clone function implementation as (not pure) virtual method
-  EnumItemTuple *clone_enum_item_impl () const override
+  EnumItemTuple *clone_item_impl () const override
   {
 return new EnumItemTuple (*this);
   }
@@ -2213,10 +2206,11 @@ public:
   // Returns whether struct enum item has struct fields.
   bool has_struct_fields () const { return !struct_fields.empty (); }
 
-  EnumItemStruct (Identifier variant_name,
+  EnumItemStruct (Identifier variant_name, Visibility vis,
  std::vector struct_fields,
  std::vector outer_attrs, Location locus)
-: EnumItem (std::move (variant_name), std::move (outer_attrs), locus),
+: EnumItem (std::move (variant_name), std::move (vis),
+   std::move (outer_attrs), locus),
   struct_fields (std::mov

[PATCH 2/3] Resolve Enums and EnumItems

2021-09-05 Thread Mark Wielaard
Generate paths for Enum and EnumItem AST NodeIds and resolve the types
of tuple and struct enum items.

EnumItems always have the Enum as prefix. To make this work for
ResolveStms (declaration statements are not given a canonical path) we
add an enum_prefix to be used when resolving EnumItems.

For ResolveType the tuple and struct fields get resolved using the
Enum type scope.

Add tests for toplevel or stmt enums with duplicate variant names. And
adjust the tuple_enum_variants.rs testcase to expect unused name
warnings.
---
 gcc/rust/resolve/rust-ast-resolve-item.h  |  36 ++
 gcc/rust/resolve/rust-ast-resolve-stmt.h  | 105 +-
 gcc/rust/resolve/rust-ast-resolve-toplevel.h  |  69 
 gcc/testsuite/rust/compile/bad_stmt_enums.rs  |  22 
 .../rust/compile/bad_toplevel_enums.rs|  19 
 .../compile/torture/tuple_enum_variants.rs|   7 +-
 6 files changed, 254 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_stmt_enums.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_toplevel_enums.rs

diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h 
b/gcc/rust/resolve/rust-ast-resolve-item.h
index d3c053b609f..2a2f956a385 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -260,6 +260,42 @@ public:
 resolver->get_type_scope ().pop ();
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+NodeId scope_node_id = enum_decl.get_node_id ();
+resolver->get_type_scope ().push (scope_node_id);
+
+if (enum_decl.has_generics ())
+  {
+   for (auto &generic : enum_decl.get_generic_params ())
+ {
+   ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+ }
+  }
+
+/* The actual fields are inside the variants.  */
+for (auto &variant : enum_decl.get_variants ())
+  ResolveItem::go (variant.get ());
+
+resolver->get_type_scope ().pop ();
+  }
+
+  /* EnumItem doesn't need to be handled, no fields.  */
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+for (auto &field : item.get_tuple_fields ())
+  ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+for (auto &field : item.get_struct_fields ())
+  ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  /* EnumItemDiscriminant doesn't need to be handled, no fields.  */
+
   void visit (AST::StructStruct &struct_decl) override
   {
 NodeId scope_node_id = struct_decl.get_node_id ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h 
b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index b6044327b27..43bf0a421d6 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -33,9 +33,11 @@ class ResolveStmt : public ResolverBase
   using Rust::Resolver::ResolverBase::visit;
 
 public:
-  static void go (AST::Stmt *stmt, NodeId parent)
+  static void go (AST::Stmt *stmt, NodeId parent,
+ const CanonicalPath &enum_prefix
+ = CanonicalPath::create_empty ())
   {
-ResolveStmt resolver (parent);
+ResolveStmt resolver (parent, enum_prefix);
 stmt->accept_vis (resolver);
   };
 
@@ -98,6 +100,97 @@ public:
 resolver->get_type_scope ().pop ();
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+auto enum_path = CanonicalPath::new_seg (enum_decl.get_node_id (),
+enum_decl.get_identifier ());
+resolver->get_type_scope ().insert (
+  enum_path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
+  [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+   RichLocation r (enum_decl.get_locus ());
+   r.add_range (locus);
+   rust_error_at (r, "redefined multiple times");
+  });
+
+NodeId scope_node_id = enum_decl.get_node_id ();
+resolver->get_type_scope ().push (scope_node_id);
+
+if (enum_decl.has_generics ())
+  {
+   for (auto &generic : enum_decl.get_generic_params ())
+ {
+   ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+ }
+  }
+
+for (auto &variant : enum_decl.get_variants ())
+  ResolveStmt::go (variant.get (), parent, enum_path);
+
+resolver->get_type_scope ().pop ();
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+auto path = enum_prefix.append (
+  CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+resolver->get_type_scope ().insert (
+  path, item.get_node_id (), item.get_locus (), false,
+  [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+   RichLocation r (item.get_locus ());
+   r.add_range (locus);
+   rust_error_at (r, "redefined multiple times");
+  });
+
+// Done, no fields.
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+auto path = enum_prefix.append (
+ 

[PATCH 3/3] Add EnumItem HIR lowering

2021-09-05 Thread Mark Wielaard
Make HIT EnumItem class an Item, not VisItem like in the AST. At the
HIR level EnumItems shouldn't have visibility anymore.

Move struct_field_name_exists to rust-ast-lower.cc with the
declaration in rust-ast-lower.h to make it reusable in the different
visitors.

Add a new ASTLoweringEnumItem that can be used from ASTLoweringItem
and ASTLoweringStmt. It checks the EnumItems don't have visibility and
that EnumItemStruct fields are not duplicated.

Add a new testcase 'bad_pub_enumitems.rs' to check the no-visibility and
no-duplicates properties hold.
---
 gcc/rust/hir/rust-ast-lower-enumitem.h| 192 ++
 gcc/rust/hir/rust-ast-lower-item.h|  59 --
 gcc/rust/hir/rust-ast-lower-stmt.h|  58 --
 gcc/rust/hir/rust-ast-lower.cc|  20 ++
 gcc/rust/hir/rust-ast-lower.h |   5 +
 gcc/rust/hir/tree/rust-hir-full-test.cc   |  19 +-
 gcc/rust/hir/tree/rust-hir-item.h |  58 +++---
 .../rust/compile/bad_pub_enumitems.rs |  47 +
 8 files changed, 376 insertions(+), 82 deletions(-)
 create mode 100644 gcc/rust/hir/rust-ast-lower-enumitem.h
 create mode 100644 gcc/testsuite/rust/compile/bad_pub_enumitems.rs

diff --git a/gcc/rust/hir/rust-ast-lower-enumitem.h 
b/gcc/rust/hir/rust-ast-lower-enumitem.h
new file mode 100644
index 000..333cb7ba3fb
--- /dev/null
+++ b/gcc/rust/hir/rust-ast-lower-enumitem.h
@@ -0,0 +1,192 @@
+// Copyright (C) 2020 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
+// .
+
+#ifndef RUST_AST_LOWER_ENUMITEM
+#define RUST_AST_LOWER_ENUMITEM
+
+#include "rust-diagnostics.h"
+
+#include "rust-ast-lower-base.h"
+#include "rust-ast-lower-type.h"
+#include "rust-ast-lower-expr.h"
+#include "rust-hir-full-decls.h"
+
+namespace Rust {
+namespace HIR {
+
+class ASTLoweringEnumItem : public ASTLoweringBase
+{
+  using Rust::HIR::ASTLoweringBase::visit;
+
+public:
+  static HIR::EnumItem *translate (AST::EnumItem *item)
+  {
+ASTLoweringEnumItem resolver;
+item->accept_vis (resolver);
+return resolver.translated;
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+auto crate_num = mappings->get_current_crate ();
+Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+  mappings->get_next_hir_id (crate_num),
+  mappings->get_next_localdef_id (crate_num));
+
+if (item.has_visibility ())
+  rust_error_at (item.get_locus (),
+"visibility qualifier %qs not allowed on enum item",
+item.get_vis ().as_string ().c_str ());
+
+translated = new HIR::EnumItem (mapping, item.get_identifier (),
+   item.get_outer_attrs (), item.get_locus ());
+
+mappings->insert_defid_mapping (mapping.get_defid (), translated);
+mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (),
+  translated);
+mappings->insert_location (crate_num, mapping.get_hirid (),
+  item.get_locus ());
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+auto crate_num = mappings->get_current_crate ();
+Analysis::NodeMapping mapping (crate_num, item.get_node_id (),
+  mappings->get_next_hir_id (crate_num),
+  mappings->get_next_localdef_id (crate_num));
+
+if (item.has_visibility ())
+  rust_error_at (item.get_locus (),
+"visibility qualifier %qs not allowed on enum item",
+item.get_vis ().as_string ().c_str ());
+
+std::vector fields;
+for (auto &field : item.get_tuple_fields ())
+  {
+   HIR::Visibility vis = HIR::Visibility::create_public ();
+   HIR::Type *type
+ = ASTLoweringType::translate (field.get_field_type ().get ());
+
+   auto crate_num = mappings->get_current_crate ();
+   Analysis::NodeMapping field_mapping (
+ crate_num, field.get_node_id (),
+ mappings->get_next_hir_id (crate_num),
+ mappings->get_next_localdef_id (crate_num));
+
+   HIR::TupleField translated_field (field_mapping,
+ std::unique_ptr (type),
+ vis, field.get_locus (),
+  

[PATCH] Remove warnings from v0_mangle functions in rust-mangle.cc

2021-09-20 Thread Mark Wielaard
There were two warnings in rust-mangle.cc

rust-mangle.cc: In function ‘std::string Rust::Compile::v0_mangle_item
(const Rust::TyTy::BaseType*, const Rust::Resolver::CanonicalPath&, const 
string&)’:
rust-mangle.cc:198:1: warning: no return statement in function returning 
non-void

rust-mangle.cc: At global scope:
rust-mangle.cc:201:1: warning: ‘std::string Rust::Compile::v0_mangle_impl_item
(const Rust::TyTy::BaseType*, const Rust::TyTy::BaseType*, const string&, const 
string&)’
 declared ‘static’ but never defined [-Wunused-function]

The first results in undefined behaviour, the second points out that the
function isn't ever called/used.

Fix the first by adding a gcc_unreachable () to turn the calling of the
function into an abort ().  Fix the second by adding the call in
Mangler::mangle_impl_item. And add an implementation simply calling
gcc-unreachable (). This turns the warnings and undefined behaviour into
explicit runtime aborts when these functions are actually called.
---
 gcc/rust/backend/rust-mangle.cc | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=rust-mangle-unreachable

diff --git a/gcc/rust/backend/rust-mangle.cc b/gcc/rust/backend/rust-mangle.cc
index 840acb992e0..0e6643c64ae 100644
--- a/gcc/rust/backend/rust-mangle.cc
+++ b/gcc/rust/backend/rust-mangle.cc
@@ -195,11 +195,15 @@ v0_mangle_item (const TyTy::BaseType *ty, const 
Resolver::CanonicalPath &path,
const std::string &crate_name)
 {
   auto ty_prefix = v0_type_prefix (ty);
+  gcc_unreachable ();
 }
 
 static std::string
 v0_mangle_impl_item (const TyTy::BaseType *self, const TyTy::BaseType *ty,
-const std::string &name, const std::string &crate_name);
+const std::string &name, const std::string &crate_name)
+{
+  gcc_unreachable ();
+}
 
 std::string
 Mangler::mangle_item (const TyTy::BaseType *ty,
@@ -227,7 +231,7 @@ Mangler::mangle_impl_item (const TyTy::BaseType *self, 
const TyTy::BaseType *ty,
 case Mangler::MangleVersion::LEGACY:
   return legacy_mangle_impl_item (self, ty, name, crate_name);
 case Mangler::MangleVersion::V0:
-  gcc_unreachable ();
+  return v0_mangle_impl_item (self, ty, name, crate_name);
 default:
   gcc_unreachable ();
 }
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Remove warnings from v0_mangle functions in rust-mangle.cc

2021-09-21 Thread Mark Wielaard
Hi Arthur,

On Tue, 2021-09-21 at 13:58 +0200, cohenarthur.dev via Gcc-rust wrote:
> I forgot to do a clean build before creating the pull request and the
> file was already compiled... Sorry about that!
> 
> I'll keep on working on v0 mangling in order to get all the parts
> linked correctly, but it was in a bit of a dire state :)

Thanks for working on this. And no worries, I am just allergic to
warnings (I just must look at them to make sure I understand what is
going on and it wasn't me making a mistake).

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Fix byte char and byte string lexing code

2021-09-21 Thread Mark Wielaard
There were two warnings in lexer parse_byte_char and parse_byte_string
code for arches with signed chars:

rust-lex.cc: In member function
 ‘Rust::TokenPtr Rust::Lexer::parse_byte_char(Location)’:
rust-lex.cc:1564:21: warning: comparison is always false due to limited
 range of data type [-Wtype-limits]
 1564 |   if (byte_char > 127)
  |   ~~^
rust-lex.cc: In member function
 ‘Rust::TokenPtr Rust::Lexer::parse_byte_string(Location)’:
rust-lex.cc:1639:27: warning: comparison is always false due to limited
 range of data type [-Wtype-limits]
 1639 |   if (output_char > 127)
  |   ^

The fix would be to cast to an unsigned char before the comparison.
But that is actually wrong, and would produce the following errors
parsing a byte char or byte string:

bytecharstring.rs:3:14: error: ‘byte char’ ‘�’ out of range
3 |   let _bc = b'\x80';
  |  ^
bytecharstring.rs:4:14: error: character ‘�’ in byte string out of range
4 |   let _bs = b"foo\x80bar";
  |  ^

Both byte chars and byte strings may contain up to \xFF (255)
characters. It is utf-8 chars or strings that can only

Remove the faulty check and add a new testcase bytecharstring.rs
that checks byte chars and strings do accept > 127 hex char
escapes, but utf-8 chars and strings reject such hex char escapes.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=bytecharstring

 gcc/rust/lex/rust-lex.cc | 15 ---
 gcc/testsuite/rust/compile/bytecharstring.rs |  8 
 2 files changed, 8 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bytecharstring.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index 49b6b6d32a7..b70877be9ff 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1559,13 +1559,6 @@ Lexer::parse_byte_char (Location loc)
   byte_char = std::get<0> (escape_length_pair);
   length += std::get<1> (escape_length_pair);
 
-  if (byte_char > 127)
-   {
- rust_error_at (get_current_location (),
-"% %<%c%> out of range", byte_char);
- byte_char = 0;
-   }
-
   current_char = peek_input ();
 
   if (current_char != '\'')
@@ -1634,14 +1627,6 @@ Lexer::parse_byte_string (Location loc)
  else
length += std::get<1> (escape_length_pair);
 
- if (output_char > 127)
-   {
- rust_error_at (get_current_location (),
-"character %<%c%> in byte string out of range",
-output_char);
- output_char = 0;
-   }
-
  if (output_char != 0)
str += output_char;
 
diff --git a/gcc/testsuite/rust/compile/bytecharstring.rs 
b/gcc/testsuite/rust/compile/bytecharstring.rs
new file mode 100644
index 000..9242e2c5a0b
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bytecharstring.rs
@@ -0,0 +1,8 @@
+fn main ()
+{
+  let _bc = b'\x80';
+  let _bs = b"foo\x80bar";
+
+  let _c = '\xef';// { dg-error "out of range" }
+  let _s = "Foo\xEFBar";  // { dg-error "out of range" }
+}
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: [PATCH] Fix byte char and byte string lexing code

2021-09-22 Thread Mark Wielaard
Hi Thomas,

On Wed, Sep 22, 2021 at 11:48:56AM +0200, Thomas Schwinge wrote:
> That's .
> [...] 
> That's .

Ah, sorry, I don't really track the github issues and had missed
those. But good to see the analysis matches.

> Both these related to 
> "GCC '--enable-bootstrap' build".

To make --enable-bootstrap possible (wow, that takes a long time...)
you'll also need:
https://gcc.gnu.org/pipermail/gcc-rust/2021-September/000178.html
https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=rust-mangle-unreachable

With this and that patch applied there are no more warnings building
the rust frontend, so a --enable-bootstrap (-Werror) build completes
successfully.

> > https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=bytecharstring
> 
> Thanks, that's now: 
> "Fix byte char and byte string lexing code".

Thanks,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


byte/char string representation (Was: [PATCH] Fix byte char and byte string lexing code)

2021-09-23 Thread Mark Wielaard
On Thu, Sep 23, 2021 at 04:10:59PM +0200, Arthur Cohen wrote:
> > Something I was thinking about outside of the scope of that patch was
> about the utf8 how do they get represented? Is it some kind of wchar_t?
> 
> Do you mean in C++ or in rustc? In rustc, they are represented as Unicode
> Scalar Values which are 4 bytes wide.
> 
> From the docs over here: [https://doc.rust-lang.org/std/primitive.char.html]
> 
> So I'm assuming they could be represented as `int32_t`s which would also
> make sense for the check

Yes, for rust characters a 32bit type (I would pick uint32_t or maybe
char32_t) makes sense, since chars in rust are (almost) equal to
unicode code points (technically only 21 bits are used). But not
really, it is a Unicode scalar value, which excludes high-surrogate
and low-surrogate code points and so the only valid values are 0x0 to
0xD7FF and 0xE000 to 0x10.

We should not use the C type wchar_t, because wchar_t is
implementation defined and can be 16 or 32 bits.

See also https://doc.rust-lang.org/reference/types/textual.html

But utf8 strings are made up of u8 "utf8 chars". You need 1 to 4 utf8
chars to encode a code point. https://en.wikipedia.org/wiki/UTF-8
We can use c++ strings made up of (8 bit) chars for that.

Our lexer should make sure we only accept valid rust characters or
utf-8 sequences.

Note that the above doesn't hold for "byte chars" (b'A') or "byte
strings" (b"abc"). Those are really just u8 or [u8] arrays which hold
bytes (0x0 to 0xff).

We currently get the type for byte strings wrong. We pretend they are
&str, but they really should be &[u8].

I tried to fix that with the following:

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h 
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index fe8973a4d81..b0dd1c3ff2c 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -609,15 +609,42 @@ public:
break;
 
case HIR::Literal::LitType::BYTE_STRING: {
- /* We just treat this as a string, but it really is an arraytype of
-u8. It isn't in UTF-8, but really just a byte array.  */
- TyTy::BaseType *base = nullptr;
- auto ok = context->lookup_builtin ("str", &base);
+ /* This is an arraytype of u8 reference (&[u8;size]). It isn't in
+UTF-8, but really just a byte array. Code to construct the array
+reference copied from ArrayElemsValues and ArrayType. */
+ TyTy::BaseType *u8;
+ auto ok = context->lookup_builtin ("u8", &u8);
  rust_assert (ok);
 
+ auto crate_num = mappings->get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID,
+mappings->get_next_hir_id (crate_num),
+UNKNOWN_LOCAL_DEFID);
+
+ /* Capacity is the size of the string (number of chars).
+It is a constant, but for fold it to get a BExpression.  */
+ std::string capacity_str = std::to_string (expr.as_string ().size ());
+ HIR::LiteralExpr literal_capacity (mapping, capacity_str,
+HIR::Literal::LitType::INT,
+PrimitiveCoreType::CORETYPE_USIZE,
+expr.get_locus ());
+
+ // mark the type for this implicit node
+ context->insert_type (mapping,
+   new TyTy::USizeType (mapping.get_hirid ()));
+
+ Bexpression *capacity
+   = ConstFold::ConstFoldExpr::fold (&literal_capacity);
+
+ TyTy::ArrayType *array
+   = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), capacity,
+  TyTy::TyVar (u8->get_ref ()));
+
+ context->insert_type (expr.get_mappings (), array);
+
  infered
= new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
-  TyTy::TyVar (base->get_ref ()), false);
+  TyTy::TyVar (array->get_ref ()), false);
}
break;
 
But that looks more complicated than is probably necessary and it
doesn't work. When the type checker wants to print this type
ReferenceType.as_string () goes into a loop for some reason.

Can anybody see what is wrong with the above?

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Merge from GCC upstream into GCC/Rust

2021-09-25 Thread Mark Wielaard
Hi Thomas,

On Fri, Sep 24, 2021 at 10:30:15AM +0200, Thomas Schwinge wrote:
> I'm preparing a merge from GCC upstream into GCC/Rust.  This is normally
> pretty unexciting ;-) -- the exception being, as once mentioned in
> :

Thanks for doing this.

> As for checking that the configurations that you're testing are still
> fine, would you like to do (and/or fix) that before or after me pushing
> the merge?

I don't run the builds by hand, the buildbot workers (debian-arm64,
debian-i386, fedora-ppc64, fedora-ppc64le, fedora-s390x,
fedora-x86_64) simply build every new commit they see:
https://builder.wildebeest.org/buildbot/#/builders?tags=gccrust

They are currently all green. If any turns red, they should sent an
email to the list and I'll take a look and try to fix them up.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: byte/char string representation (Was: [PATCH] Fix byte char and byte string lexing code)

2021-09-25 Thread Mark Wielaard
Hi Philip,

On Fri, Sep 24, 2021 at 12:01:42PM +0100, Philip Herron wrote:
> This is really useful information, will this mean that the lexer token will
> need to represent strings differently as well? Or is the std::string in the
> lexer still ok?

I think the respresentation as std::string is fine. As long as we
don't mix std::strings between different types (byte strings may
contain sequences of chars that aren't valid utf-8 sequenecs).

> The change you made above has the problem that reference types like, arrays
> are forms of what rust calls covariant types since they might contain an
> inference variable, so they require lookup to determine the base type. Its
> likely there is a reference cycle here. Though this change will not be
> correct for type checking purposes. The design of the type system is purely
> about rust type checking and inferring types.

OK, so how do I represent an reference to an array type that doesn't
contain any inference variables? When we see a b"hello" byte string
that is the same as seeing &[b'h', b'e', b'l', b'l', b'o'] which is
the same as seeing &[0x68u8, 0x65u8, 0x6cu8, 0x6cu8, 0x6fu8];

So we know this is &[u8;5] and if we write:

let a = b"hello";

We want to infer that a has type &[u8;5].

> So for example this change will break the case of:
> 
> ```
>   let a:str = "test";
> ```
> 
> Since the TypePath of str can't know the size of the expected array at
> compilation time. And the error message will end up with something like
> "expected str got [i8, 4]";

Right, but that is for "proper strings". It is somewhat unfortunate
that Rust calls byte strings also "strings", but they really
aren't. b"abc" is static array of u8, not a &str (containing utf-8).

I have to think about the slicing of "proper strings", which sound
more complicated than slicing of byte strings, because I don't think
you want to chop up a utf-8 sequence. For now I would simply try to
get the type of byte strings like b"test" correct.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-09-25 Thread Mark Wielaard
On Sat, Sep 25, 2021 at 12:04:01PM +, build...@builder.wildebeest.org wrote:
> The Buildbot has detected a new failure on builder gccrust-debian-arm64 while 
> building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/58/builds/469

O fun. I hadn't expected the buildbot to try and build every commit in
the merge... They all fail in the configure step:

  configure: error: The following requested languages could not be
  built: rust

But this will take some time, there are many, many, many commits. I'll
go and reset the buildbot so it picks up the builds after the merge
again.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Remove raw string and raw byte string references from ast and hir

2021-09-27 Thread Mark Wielaard
Raw strings and raw byte strings are simply different ways to
create string and byte string literals. Only the lexer cares
how those literals are constructed and which escapes are used
to construct them. The parser and hir simply see strings or
byte strings.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=no-raw-byte-string

 gcc/rust/ast/rust-ast.h| 2 --
 gcc/rust/ast/rust-item.h   | 2 +-
 gcc/rust/hir/rust-ast-lower-expr.h | 6 --
 gcc/rust/hir/tree/rust-hir.h   | 2 --
 gcc/rust/parse/rust-parse-impl.h   | 3 ---
 5 files changed, 1 insertion(+), 14 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 96b8da40dd7..b0738a26b6c 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -259,10 +259,8 @@ public:
   {
 CHAR,
 STRING,
-RAW_STRING,
 BYTE,
 BYTE_STRING,
-RAW_BYTE_STRING,
 INT,
 FLOAT,
 BOOL
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 7a34144f0d3..c7c8b8f5692 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -32,7 +32,7 @@ class MacroInvocationSemi;
 // TODO: inline?
 /*struct AbiName {
 std::string abi_name;
-// Technically is meant to be STRING_LITERAL or RAW_STRING_LITERAL
+// Technically is meant to be STRING_LITERAL
 
   public:
 // Returns whether abi name is empty, i.e. doesn't exist.
diff --git a/gcc/rust/hir/rust-ast-lower-expr.h 
b/gcc/rust/hir/rust-ast-lower-expr.h
index ff4c181d0e2..1d0b6cc6977 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.h
+++ b/gcc/rust/hir/rust-ast-lower-expr.h
@@ -332,18 +332,12 @@ public:
   case AST::Literal::LitType::STRING:
type = HIR::Literal::LitType::STRING;
break;
-  case AST::Literal::LitType::RAW_STRING:
-   type = HIR::Literal::LitType::RAW_STRING;
-   break;
   case AST::Literal::LitType::BYTE:
type = HIR::Literal::LitType::BYTE;
break;
   case AST::Literal::LitType::BYTE_STRING:
type = HIR::Literal::LitType::BYTE_STRING;
break;
-  case AST::Literal::LitType::RAW_BYTE_STRING:
-   type = HIR::Literal::LitType::RAW_BYTE_STRING;
-   break;
   case AST::Literal::LitType::INT:
type = HIR::Literal::LitType::INT;
break;
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 8ba6308fdea..5a64662efbc 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -45,10 +45,8 @@ public:
   {
 CHAR,
 STRING,
-RAW_STRING,
 BYTE,
 BYTE_STRING,
-RAW_BYTE_STRING,
 INT,
 FLOAT,
 BOOL
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 8cce9332350..c2d3720b47d 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -7556,8 +7556,6 @@ Parser::parse_literal_expr 
(AST::AttrVec outer_attrs)
   literal_value = t->get_str ();
   lexer.skip_token ();
   break;
-// case RAW_STRING_LITERAL:
-// put here if lexer changes to have these
 case BYTE_CHAR_LITERAL:
   type = AST::Literal::BYTE;
   literal_value = t->get_str ();
@@ -7568,7 +7566,6 @@ Parser::parse_literal_expr 
(AST::AttrVec outer_attrs)
   literal_value = t->get_str ();
   lexer.skip_token ();
   break;
-// case RAW_BYTE_STRING_LITERAL:
 case INT_LITERAL:
   type = AST::Literal::INT;
   literal_value = t->get_str ();
-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[no subject]

2021-09-29 Thread Mark Wielaard
>From e6e1cc117e1f08dfde86f5a3b1988e4b7206a7da Mon Sep 17 00:00:00 2001
From: Mark Wielaard 
Date: Wed, 29 Sep 2021 22:03:34 +0200
Subject: [PATCH] Fix raw byte string parsing of zero and out of range bytes

Allow \0 escape in raw byte string and reject non-ascii byte
values. Change parse_partial_hex_escapes to not skip bad characters to
provide better error messages.

Add rawbytestring.rs testcase to check string, raw string, byte string
and raw byte string parsing.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=parse-raw-byte-string

 gcc/rust/lex/rust-lex.cc|  20 +++-
 gcc/testsuite/rust/compile/rawbytestring.rs | Bin 0 -> 3234 bytes
 2 files changed, 15 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/rawbytestring.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b70877be9ff..bbddea04d0c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1423,8 +1423,7 @@ Lexer::parse_partial_hex_escape ()
   char hexNum[3] = {0, 0, 0};
 
   // first hex char
-  skip_input ();
-  current_char = peek_input ();
+  current_char = peek_input (1);
   int additional_length_offset = 1;
 
   if (!is_x_digit (current_char))
@@ -1432,20 +1431,23 @@ Lexer::parse_partial_hex_escape ()
   rust_error_at (get_current_location (),
 "invalid character %<\\x%c%> in \\x sequence",
 current_char);
+  return std::make_pair (0, 0);
 }
   hexNum[0] = current_char;
 
   // second hex char
   skip_input ();
-  current_char = peek_input ();
+  current_char = peek_input (1);
   additional_length_offset++;
 
   if (!is_x_digit (current_char))
 {
   rust_error_at (get_current_location (),
-"invalid character %<\\x%c%> in \\x sequence",
+"invalid character %<\\x%c%c%> in \\x sequence", hexNum[0],
 current_char);
+  return std::make_pair (0, 1);
 }
+  skip_input ();
   hexNum[1] = current_char;
 
   long hexLong = std::strtol (hexNum, nullptr, 16);
@@ -1627,7 +1629,7 @@ Lexer::parse_byte_string (Location loc)
  else
length += std::get<1> (escape_length_pair);
 
- if (output_char != 0)
+ if (output_char != 0 || !std::get<2> (escape_length_pair))
str += output_char;
 
  continue;
@@ -1722,6 +1724,14 @@ Lexer::parse_raw_byte_string (Location loc)
}
}
 
+  if ((unsigned char) current_char > 127)
+   {
+ rust_error_at (get_current_location (),
+"character %<%c%> in raw byte string out of range",
+current_char);
+ current_char = 0;
+   }
+
   length++;
 
   str += current_char;
diff --git a/gcc/testsuite/rust/compile/rawbytestring.rs 
b/gcc/testsuite/rust/compile/rawbytestring.rs
new file mode 100644
index 
..9c6b762a7fd378206a3bfe21db5b708890f5466f
GIT binary patch
literal 3234
zcmbVOO>fgc5amjL#mG4T6)1rVl`5`1a^M^Zc^f;m2zI;c($Wfvf5=~A-pqd4PU65Z
z<9Tmp-n`vS-O~56Y3cQwv*$CS<&wUX59E5=v|Go4UDeZ9>ni$0wkR&M$OnWLi=tR8
zvhYe0>#n0kp8Z~u3yqU0ZIOclm4066_dMaIdKBLE90VG(Y=lGOCeT&0tuLp+z$p*Er0}$>V{I!^8|YFtTxx
z@X*l4>D0{rUt=35bE5|t9J_s{&GuboZD*@|GH+hjmxkvqUg|FRiNY&&
zP6(%e4anlh3W@7JWKOd9E)p`E*!Jfr70=|kILq??taYC%vd4tW9O052FwtHy(W1l^5)-!Q6rkeY2pcOb5
zC5~Q^#`Cf!S&N9GM~?nelacMDHe;2ejYcV-D%(M~7r|5FJ&7hOIQ$Oo!_o8>9i>^x
zV>X-Uc!7Jfq5+jI?0J=nn!sj`v1wMcU}PH?O>D8bJ*^GcSU|ak{Lxs!g8aAiFN}Pz
A0RR91

literal 0
HcmV?d1

-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Fix raw byte string parsing of zero and out of range bytes

2021-09-29 Thread Mark Wielaard
Allow \0 escape in raw byte string and reject non-ascii byte
values. Change parse_partial_hex_escapes to not skip bad characters to
provide better error messages.

Add rawbytestring.rs testcase to check string, raw string, byte string
and raw byte string parsing.
---

https://code.wildebeest.org/git/user/mjw/gccrs/commit/?h=parse-raw-byte-string

 gcc/rust/lex/rust-lex.cc|  20 +++-
 gcc/testsuite/rust/compile/rawbytestring.rs | Bin 0 -> 3234 bytes
 2 files changed, 15 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/rawbytestring.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index b70877be9ff..bbddea04d0c 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1423,8 +1423,7 @@ Lexer::parse_partial_hex_escape ()
   char hexNum[3] = {0, 0, 0};
 
   // first hex char
-  skip_input ();
-  current_char = peek_input ();
+  current_char = peek_input (1);
   int additional_length_offset = 1;
 
   if (!is_x_digit (current_char))
@@ -1432,20 +1431,23 @@ Lexer::parse_partial_hex_escape ()
   rust_error_at (get_current_location (),
 "invalid character %<\\x%c%> in \\x sequence",
 current_char);
+  return std::make_pair (0, 0);
 }
   hexNum[0] = current_char;
 
   // second hex char
   skip_input ();
-  current_char = peek_input ();
+  current_char = peek_input (1);
   additional_length_offset++;
 
   if (!is_x_digit (current_char))
 {
   rust_error_at (get_current_location (),
-"invalid character %<\\x%c%> in \\x sequence",
+"invalid character %<\\x%c%c%> in \\x sequence", hexNum[0],
 current_char);
+  return std::make_pair (0, 1);
 }
+  skip_input ();
   hexNum[1] = current_char;
 
   long hexLong = std::strtol (hexNum, nullptr, 16);
@@ -1627,7 +1629,7 @@ Lexer::parse_byte_string (Location loc)
  else
length += std::get<1> (escape_length_pair);
 
- if (output_char != 0)
+ if (output_char != 0 || !std::get<2> (escape_length_pair))
str += output_char;
 
  continue;
@@ -1722,6 +1724,14 @@ Lexer::parse_raw_byte_string (Location loc)
}
}
 
+  if ((unsigned char) current_char > 127)
+   {
+ rust_error_at (get_current_location (),
+"character %<%c%> in raw byte string out of range",
+current_char);
+ current_char = 0;
+   }
+
   length++;
 
   str += current_char;
diff --git a/gcc/testsuite/rust/compile/rawbytestring.rs 
b/gcc/testsuite/rust/compile/rawbytestring.rs
new file mode 100644
index 
..9c6b762a7fd378206a3bfe21db5b708890f5466f
GIT binary patch
literal 3234
zcmbVOO>fgc5amjL#mG4T6)1rVl`5`1a^M^Zc^f;m2zI;c($Wfvf5=~A-pqd4PU65Z
z<9Tmp-n`vS-O~56Y3cQwv*$CS<&wUX59E5=v|Go4UDeZ9>ni$0wkR&M$OnWLi=tR8
zvhYe0>#n0kp8Z~u3yqU0ZIOclm4066_dMaIdKBLE90VG(Y=lGOCeT&0tuLp+z$p*Er0}$>V{I!^8|YFtTxx
z@X*l4>D0{rUt=35bE5|t9J_s{&GuboZD*@|GH+hjmxkvqUg|FRiNY&&
zP6(%e4anlh3W@7JWKOd9E)p`E*!Jfr70=|kILq??taYC%vd4tW9O052FwtHy(W1l^5)-!Q6rkeY2pcOb5
zC5~Q^#`Cf!S&N9GM~?nelacMDHe;2ejYcV-D%(M~7r|5FJ&7hOIQ$Oo!_o8>9i>^x
zV>X-Uc!7Jfq5+jI?0J=nn!sj`v1wMcU}PH?O>D8bJ*^GcSU|ak{Lxs!g8aAiFN}Pz
A0RR91

literal 0
HcmV?d1

-- 
2.32.0

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


[PATCH] Fix lexer to not produce bad unicode escape values

2021-10-02 Thread Mark Wielaard
There were a couple of issues in the lexer unicode escape code.
Unicode escape sequences must always start with an opening curly
bracket (and end with a closing one). Underscores are not allowed as
starting character. And the produced values must be unicode scalar
values, which excludes surrogate values (D800 to DFFF) or values
larger than 10.

Also try to recover more gracefully from errors by trying to skip past
any bad characters to the end of the escape sequence.

Test all of the above in a new testcase unicode_escape.rs.
---

https://git.sr.ht/~mjw/gccrs/commit/unicode_escape

 gcc/rust/lex/rust-lex.cc | 88 
 gcc/testsuite/rust/compile/unicode_escape.rs | 60 +
 2 files changed, 132 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/unicode_escape.rs

diff --git a/gcc/rust/lex/rust-lex.cc b/gcc/rust/lex/rust-lex.cc
index bbddea04d0c..2b3c89b48be 100644
--- a/gcc/rust/lex/rust-lex.cc
+++ b/gcc/rust/lex/rust-lex.cc
@@ -1273,6 +1273,8 @@ Lexer::parse_escape (char opening_char)
   rust_error_at (get_current_location (),
 "cannot have a unicode escape \\u in a byte %s",
 opening_char == '\'' ? "character" : "string");
+  // Try to parse it anyway, just to skip it
+  parse_partial_unicode_escape ();
   return std::make_tuple (output_char, additional_length_offset, false);
 case '\r':
 case '\n':
@@ -1461,16 +1463,34 @@ Lexer::parse_partial_unicode_escape ()
 {
   skip_input ();
   current_char = peek_input ();
-  int additional_length_offset = 1;
+  int additional_length_offset = 0;
 
-  bool need_close_brace = false;
-  if (current_char == '{')
+  if (current_char != '{')
 {
-  need_close_brace = true;
+  rust_error_at (get_current_location (),
+"unicode escape should start with %<{%>");
+  /* Skip what should probaby have been between brackets.  */
+  while (is_x_digit (current_char) || current_char == '_')
+   {
+ skip_input ();
+ current_char = peek_input ();
+ additional_length_offset++;
+   }
+  return std::make_pair (Codepoint (0), additional_length_offset);
+}
 
+  skip_input ();
+  current_char = peek_input ();
+  additional_length_offset++;
+
+  if (current_char == '_')
+{
+  rust_error_at (get_current_location (),
+"unicode escape cannot start with %<_%>");
   skip_input ();
   current_char = peek_input ();
   additional_length_offset++;
+  // fallthrough and try to parse the rest anyway
 }
 
   // parse unicode escape - 1-6 hex digits
@@ -1500,21 +1520,45 @@ Lexer::parse_partial_unicode_escape ()
   current_char = peek_input ();
 }
 
-  // ensure closing brace if required
-  if (need_close_brace)
+  if (current_char == '}')
 {
-  if (current_char == '}')
+  skip_input ();
+  current_char = peek_input ();
+  additional_length_offset++;
+}
+  else
+{
+  // actually an error, but allow propagation anyway Assume that
+  // wrong bracketm whitespace or single/double quotes are wrong
+  // termination, otherwise it is a wrong character, then skip to the 
actual
+  // terminator.
+  if (current_char == '{' || is_whitespace (current_char)
+ || current_char == '\'' || current_char == '"')
{
- skip_input ();
- current_char = peek_input ();
- additional_length_offset++;
+ rust_error_at (get_current_location (),
+"expected terminating %<}%> in unicode escape");
+ return std::make_pair (Codepoint (0), additional_length_offset);
}
   else
{
- // actually an error, but allow propagation anyway
  rust_error_at (get_current_location (),
-"expected terminating %<}%> in unicode escape");
- // return false;
+"invalid character %<%c%> in unicode escape",
+current_char);
+ while (current_char != '}' && current_char != '{'
+&& !is_whitespace (current_char) && current_char != '\''
+&& current_char != '"')
+   {
+ skip_input ();
+ current_char = peek_input ();
+ additional_length_offset++;
+   }
+ // Consume the actual closing bracket if found
+ if (current_char == '}')
+   {
+ skip_input ();
+ current_char = peek_input ();
+ additional_length_offset++;
+   }
  return std::make_pair (Codepoint (0), additional_length_offset);
}
 }
@@ -1530,10 +1574,22 @@ Lexer::parse_partial_unicode_escape ()
   return std::make_pair (Codepoint (0), additional_length_offset);
 }
 
-  long hex_num = std::strtol (num_str.c_str (), nullptr, 16);
+  unsigned long hex_num = std::strtoul (num_str.c_str (), nullptr, 16);
 
-  // assert fits a u

Re: byte/char string representation (Was: [PATCH] Fix byte char and byte string lexing code)

2021-10-03 Thread Mark Wielaard
Hi Philip,

On Thu, Sep 30, 2021 at 11:46:30AM +0100, Philip Herron wrote:
> Your patch was 99% of the way there to fix the type
> resolution so I finished it off for you:
> 
> https://github.com/Rust-GCC/gccrs/pull/698/files

And you added the actual backend code needed! So I'll probably say I
was maybe 45% there :) This is really useful. It works for me and will
enable writing a couple of real tests for byte strings (like we have
for str already, that aren't just lexer/parser checks, but which can
actually check the contents of the byte strings.

> The missing piece was that References and Array's are a type of covariant
> type so that an array type can look like this: [_, capacity], so the
> inference variable here is the variant so that we need to make sure it has
> its own implicit mapping id. You just needed to create one more mapping to
> get that implicit id so that the reference type similarly doesn't get into
> a loop of looking up itself. Creating implicit types like this could be
> made easier, so we should likely add some helpers for this scenario.

Thanks, my knowledge of mappings was a bit fuzzy. So even though we
know our own array type is fixed, we still need to attach a unique
mapping to match against other types which might not be fixed (yet).

There is indeed a lot of extra work you need to do and that you can
easily get wrong. Creating an empty mapping is a lot of work and it is
easy to get the details right. An new_empty_mapping helper method
would be great. Maybe it could even be hidden inside the expression or
type constructor.

I do have a question about why we also create these mappings for the
capacity. The capacity is always a fixed usize number. Not just in
this case, but always since it is constant expression in a const
context. So any comparison of the length will always be a simple
constant usize number check. Is using mappings not overkill in that
case?

We use a Bexpression for the capacity, created by
ConstFold::ConstFoldExpr::fold, shouldn't we check it actually folded
correctly? Currently when it cannot we just leave it in an error state
till it is too late.

e.g

pub fn main()
{
  let _a: &[u8; 4 / 0];
  _a = b"test";
}

Results in:

rust1: internal compiler error: in const_size_val_to_string, at 
rust/rust-gcc.cc:210
0x794e67 Gcc_backend::const_size_val_to_string[abi:cxx11](Bexpression*)
/home/mark/src/gccrs/gcc/rust/rust-gcc.cc:210
0x794e67 Gcc_backend::const_size_val_to_string[abi:cxx11](Bexpression*)
/home/mark/src/gccrs/gcc/rust/rust-gcc.cc:208
0x8c51ef Rust::TyTy::ArrayType::capacity_string[abi:cxx11]() const
/home/mark/src/gccrs/gcc/rust/typecheck/rust-tyty.cc:1136
0x8c51ef Rust::TyTy::ArrayType::as_string[abi:cxx11]() const
/home/mark/src/gccrs/gcc/rust/typecheck/rust-tyty.cc:1129
0x8d0c8b Rust::TyTy::BaseCoercionRules::visit(Rust::TyTy::ArrayType&)
/home/mark/src/gccrs/gcc/rust/typecheck/rust-tyty-coercion.h:166
[...]

So it seems we really should check for is_error_expr earlier.  And
maybe just get the integer value and store/compare that instead of the
Bexpression?

P.S. Don't let this stop you from committing the code as is, it does
work. We can rework it afterwards if the above comments make any
sense.

Cheers,

Mark

-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


Re: Buildbot failure in Wildebeest Builder on whole buildset

2021-11-05 Thread Mark Wielaard
Hi,

On Fri, 2021-11-05 at 13:49 +, build...@builder.wildebeest.org
wrote:
> The Buildbot has detected a new failure on builder gccrust-fedora-
> s390x while building gccrust.
> Full details are available at:
> https://builder.wildebeest.org/buildbot/#builders/63/builds/1072
> 
> Buildbot URL: https://builder.wildebeest.org/buildbot/
> 
> Worker for this Build: fedora-s390x

Sorry, the buildbot worker ran out of disk space. Space has been
restored and the next builds look green again.

Cheers,

Mark
-- 
Gcc-rust mailing list
Gcc-rust@gcc.gnu.org
https://gcc.gnu.org/mailman/listinfo/gcc-rust


  1   2   >