From: Pierre-Emmanuel Patry <[email protected]>

Features are now collected early rather than later during the feature
gating visitor. This requires the introduction of an early cfg strip
in order to collect #![cfg(xxxx), feature(yyyy)] correctly.

gcc/rust/ChangeLog:

        * Make-lang.in: Add rust-early-cfg-strip object file.
        * expand/rust-cfg-strip.h (expand_cfg_attrs): Declare function 
prototype.
        * rust-session-manager.cc (Session::compile_crate): Reorder feature
        collection and add early cfg strip.
        * expand/rust-early-cfg-strip.cc: New file.
        * expand/rust-early-cfg-strip.h: New file.

Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/07c1dd1d8f65103a81d2e73ccf14fc05d0ce1f79

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4425

 gcc/rust/Make-lang.in                   |  1 +
 gcc/rust/expand/rust-cfg-strip.h        |  2 ++
 gcc/rust/expand/rust-early-cfg-strip.cc | 38 +++++++++++++++++++++++
 gcc/rust/expand/rust-early-cfg-strip.h  | 41 +++++++++++++++++++++++++
 gcc/rust/rust-session-manager.cc        | 14 +++++++--
 5 files changed, 93 insertions(+), 3 deletions(-)
 create mode 100644 gcc/rust/expand/rust-early-cfg-strip.cc
 create mode 100644 gcc/rust/expand/rust-early-cfg-strip.h

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index b5d837f46..bd5eb8654 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -94,6 +94,7 @@ GRS_OBJS = \
     rust/rust-compile-resolve-path.o \
     rust/rust-macro-expand.o \
     rust/rust-cfg-strip.o \
+    rust/rust-early-cfg-strip.o \
     rust/rust-expand-visitor.o \
     rust/rust-ast-builder.o \
     rust/rust-derive.o \
diff --git a/gcc/rust/expand/rust-cfg-strip.h b/gcc/rust/expand/rust-cfg-strip.h
index dfe724a77..e372744f6 100644
--- a/gcc/rust/expand/rust-cfg-strip.h
+++ b/gcc/rust/expand/rust-cfg-strip.h
@@ -24,6 +24,8 @@
 
 namespace Rust {
 
+void expand_cfg_attrs (AST::AttrVec &attrs);
+
 // forward declare
 struct ExpansionCfg;
 
diff --git a/gcc/rust/expand/rust-early-cfg-strip.cc 
b/gcc/rust/expand/rust-early-cfg-strip.cc
new file mode 100644
index 000000000..bc0e4b5b0
--- /dev/null
+++ b/gcc/rust/expand/rust-early-cfg-strip.cc
@@ -0,0 +1,38 @@
+// Copyright (C) 2026 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
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-early-cfg-strip.h"
+#include "rust-cfg-strip.h"
+
+namespace Rust {
+
+void
+EarlyCfgStrip::go (AST::Crate &crate)
+{
+  visit (crate);
+}
+
+void
+EarlyCfgStrip::visit (AST::Crate &crate)
+{
+  expand_cfg_attrs (crate.inner_attrs);
+
+  AST::DefaultASTVisitor::visit (crate);
+}
+
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-early-cfg-strip.h 
b/gcc/rust/expand/rust-early-cfg-strip.h
new file mode 100644
index 000000000..b342aee90
--- /dev/null
+++ b/gcc/rust/expand/rust-early-cfg-strip.h
@@ -0,0 +1,41 @@
+// Copyright (C) 2026 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
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_EARLY_CFG_STRIP_H
+#define RUST_EARLY_CFG_STRIP_H
+
+#include "rust-ast-visitor.h"
+
+namespace Rust {
+
+/**
+ * Some parts cannot be stripped during the expansion passes
+ */
+class EarlyCfgStrip : AST::DefaultASTVisitor
+{
+public:
+  using DefaultASTVisitor::visit;
+
+  void go (AST::Crate &crate);
+
+  void visit (AST::Crate &crate) override;
+};
+
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 67adb103c..cf3237ccd 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -52,6 +52,7 @@
 #include "rust-early-name-resolver-2.0.h"
 #include "rust-late-name-resolver-2.0.h"
 #include "rust-resolve-builtins.h"
+#include "rust-early-cfg-strip.h"
 #include "rust-cfg-strip.h"
 #include "rust-expand-visitor.h"
 #include "rust-unicode.h"
@@ -669,7 +670,15 @@ Session::compile_crate (const char *filename)
 
   Analysis::AttributeChecker ().go (parsed_crate);
 
-  if (!has_attribute (parsed_crate, std::string (Values::Attributes::NO_CORE)))
+  EarlyCfgStrip ().go (parsed_crate);
+
+  auto parsed_crate_features
+    = Features::FeatureCollector{}.collect (parsed_crate);
+
+  // Do not inject core if some errors were emitted
+  if (!saw_errors ()
+      && !has_attribute (parsed_crate,
+                        std::string (Values::Attributes::NO_CORE)))
     {
       parsed_crate.inject_extern_crate ("core");
     }
@@ -702,8 +711,7 @@ Session::compile_crate (const char *filename)
   // feature gating
   if (last_step == CompileOptions::CompileStep::FeatureGating)
     return;
-  auto parsed_crate_features
-    = Features::FeatureCollector{}.collect (parsed_crate);
+
   FeatureGate (parsed_crate_features).check (parsed_crate);
 
   if (last_step == CompileOptions::CompileStep::NameResolution)
-- 
2.53.0

Reply via email to