https://gcc.gnu.org/g:2da40ca97dc7396715e1a63a1c2b186edc92665f

commit r17-1077-g2da40ca97dc7396715e1a63a1c2b186edc92665f
Author: Pierre-Emmanuel Patry <[email protected]>
Date:   Fri Apr 3 13:21:14 2026 +0200

    gccrs: Add assert macro handler
    
    Assert macro handler was missing, insert a basic handler that desugars to
    a condition and a call to panic.
    
    gcc/rust/ChangeLog:
    
            * expand/rust-macro-builtins-log-debug.cc 
(MacroBuiltin::assert_handler):
            Add basic assert builtin macro handler.
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/assert_missing_panic.rs: New test.
    
    Signed-off-by: Pierre-Emmanuel Patry <[email protected]>

Diff:
---
 gcc/rust/expand/rust-macro-builtins-log-debug.cc   | 72 ++++++++++++++++++++++
 gcc/testsuite/rust/compile/assert_missing_panic.rs | 12 ++++
 2 files changed, 84 insertions(+)

diff --git a/gcc/rust/expand/rust-macro-builtins-log-debug.cc 
b/gcc/rust/expand/rust-macro-builtins-log-debug.cc
index d80e7b66c5c0..cef34eb1e033 100644
--- a/gcc/rust/expand/rust-macro-builtins-log-debug.cc
+++ b/gcc/rust/expand/rust-macro-builtins-log-debug.cc
@@ -19,6 +19,9 @@
 #include "rust-ast-fragment.h"
 #include "rust-macro-builtins.h"
 #include "rust-macro-builtins-helpers.h"
+#include "rust-ast-builder.h"
+#include "optional.h"
+#include "rust-ast-collector.h"
 
 namespace Rust {
 tl::optional<AST::Fragment>
@@ -27,6 +30,75 @@ MacroBuiltin::assert_handler (location_t invoc_locus,
                              AST::InvocKind semicolon)
 {
   rust_debug ("assert!() called");
+  auto tt = invoc.get_delim_tok_tree ();
+  MacroInvocLexer lex (tt.to_token_stream ());
+  Parser<MacroInvocLexer> parser (lex);
+
+  auto last_token_id = macro_end_token (tt, parser);
+  bool has_error = false;
+
+  auto expanded_expr = try_expand_many_expr (parser, last_token_id,
+                                            invoc.get_expander (), has_error);
+  if (expanded_expr.size () < 1)
+    {
+      rust_error_at (invoc_locus,
+                    "macro requires a boolean expression as an argument");
+      return AST::Fragment::create_error ();
+    }
+  auto expr_to_assert = std::move (expanded_expr[0]);
+  expanded_expr.erase (expanded_expr.begin ());
+
+  if (expanded_expr.size () > 1)
+    {
+      rust_sorry_at (
+       invoc_locus,
+       "The second form of assert with a message is not supported yet");
+
+      return AST::Fragment::create_error ();
+    }
+
+  auto pending_invocations = check_for_eager_invocations (expanded_expr);
+  if (!pending_invocations.empty ())
+    return make_eager_builtin_invocation (BuiltinMacro::Assert, invoc_locus,
+                                         invoc.get_delim_tok_tree (),
+                                         std::move (pending_invocations));
+
+  AST::Builder b (invoc_locus);
+
+  std::vector<std::unique_ptr<AST::TokenTree>> panic_tree;
+  const_TokenPtr open = Token::make (TokenId::LEFT_PAREN, invoc_locus);
+  panic_tree.push_back (std::make_unique<AST::Token> (std::move (open)));
+
+  const_TokenPtr close = Token::make (TokenId::RIGHT_PAREN, invoc_locus);
+  panic_tree.push_back (std::make_unique<AST::Token> (std::move (close)));
+
+  auto panic = AST::MacroInvocation::Regular (
+    AST::MacroInvocData (AST::SimplePath (Identifier ("panic")),
+                        AST::DelimTokenTree (AST::DelimType::PARENS,
+                                             std::move (panic_tree),
+                                             invoc_locus)),
+    {} /* outer attributes */, invoc_locus, true /* semicoloned */);
+  auto stmt = b.statementify (std::move (panic));
+  std::vector<std::unique_ptr<AST::Stmt>> stmts;
+  stmts.push_back (std::move (stmt));
+  auto block = b.block (std::move (stmts));
+  auto negated_condition = std::unique_ptr<AST::NegationExpr> (
+    new AST::NegationExpr (std::move (expr_to_assert),
+                          AST::NegationExpr::ExprType::NOT, {}, invoc_locus));
+
+  auto if_expr = std::make_unique<AST::IfExpr> (
+    std::move (negated_condition) /* condition*/, std::move (block),
+    std::vector<AST::Attribute>{}, invoc_locus);
+
+  auto node = AST::SingleASTNode (std::move (if_expr));
+
+  AST::TokenCollector collector;
+  collector.visit (node);
+  std::vector<std::unique_ptr<AST::Token>> tokens;
+  for (auto &&token : collector.collect_tokens ())
+    tokens.push_back (std::make_unique<AST::Token> (token));
+
+  return AST::Fragment ({node}, std::move (tokens));
 
   return AST::Fragment::create_error ();
 }
diff --git a/gcc/testsuite/rust/compile/assert_missing_panic.rs 
b/gcc/testsuite/rust/compile/assert_missing_panic.rs
new file mode 100644
index 000000000000..71f87aece385
--- /dev/null
+++ b/gcc/testsuite/rust/compile/assert_missing_panic.rs
@@ -0,0 +1,12 @@
+#![feature(rustc_attrs)]
+#![feature(no_core)]
+#![no_core]
+
+#[macro_export]
+#[rustc_builtin_macro]
+macro_rules! assert {
+    ($($arg:tt)*) => {};
+}
+
+const _: () = assert!(true);
+// { dg-error "could not resolve macro invocation .panic." "" { target *-*-* } 
.-1 }

Reply via email to