From b963d599a7df2cb8e8b6bc3b1006cb1c5b89c5be Mon Sep 17 00:00:00 2001
From: liushuyu <liushuyu011@gmail.com>
Date: Wed, 4 Dec 2024 11:13:59 -0700
Subject: [PATCH] gccrs: fix a compiler crash when path expression contains
 nothing

gcc/rust/ChangeLog:

	* ast/rust-path.h: allows error nodes to specify the source
	location, so that it could be used in diagnostics later.
	* parse/rust-parse-impl.h: creates the PathInExpression error node
	with source location and prints proper diagnostics if the path
	is empty.

gcc/testsuite/ChangeLog:

	* rust/compile/paamayim-nekudotayim.rs: add a test for testing
	proper error recovery logic when there is no path names.
---
 gcc/rust/ast/rust-path.h                           |  4 ++--
 gcc/rust/parse/rust-parse-impl.h                   | 11 ++++++++---
 gcc/testsuite/rust/compile/paamayim-nekudotayim.rs |  5 +++++
 3 files changed, 15 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/paamayim-nekudotayim.rs

diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 2df1506923d7..1bbac6883e1c 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -727,9 +727,9 @@ class PathInExpression : public Pattern, public ExprWithoutBlock
   }
 
   // Creates an error state path in expression.
-  static PathInExpression create_error ()
+  static PathInExpression create_error (location_t locus = UNDEF_LOCATION)
   {
-    return PathInExpression ({}, {}, UNDEF_LOCATION);
+    return PathInExpression ({}, {}, locus);
   }
 
   // Returns whether path in expression is in an error state.
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index aff81448deae..73c55962023a 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -6713,9 +6713,9 @@ Parser<ManagedTokenSource>::parse_path_in_expression ()
   AST::PathExprSegment initial_segment = parse_path_expr_segment ();
   if (initial_segment.is_error ())
     {
-      // skip after somewhere?
-      // don't necessarily throw error but yeah
-      return AST::PathInExpression::create_error ();
+      // we can not throw an error here because if entered from macro expansion
+      // the macro expander can throw another error which might confuse the user
+      return AST::PathInExpression::create_error (locus);
     }
   segments.push_back (std::move (initial_segment));
 
@@ -11637,6 +11637,11 @@ Parser<ManagedTokenSource>::parse_stmt_or_expr ()
 	AST::PathInExpression path = parse_path_in_expression ();
 	std::unique_ptr<AST::Expr> null_denotation;
 
+	if (path.is_error ())
+	  {
+	    rust_error_at (path.get_locus (), "expected identifier");
+	  }
+
 	if (lexer.peek_token ()->get_id () == EXCLAM)
 	  {
 	    std::unique_ptr<AST::MacroInvocation> invoc
diff --git a/gcc/testsuite/rust/compile/paamayim-nekudotayim.rs b/gcc/testsuite/rust/compile/paamayim-nekudotayim.rs
new file mode 100644
index 000000000000..59f80feb6452
--- /dev/null
+++ b/gcc/testsuite/rust/compile/paamayim-nekudotayim.rs
@@ -0,0 +1,5 @@
+// http://phpsadness.com/sad/1
+fn main() {
+    ::;
+    // { dg-error "expected identifier" "" { target *-*-* } .-1 }
+}