gccrs: Add early cfg strip step before feature collection

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 <pierre-emmanuel.patry@embecosm.com>
This commit is contained in:
Pierre-Emmanuel Patry
2026-02-05 13:58:11 +01:00
committed by Arthur Cohen
parent ea66f8aaee
commit 435416e845
5 changed files with 93 additions and 3 deletions

View File

@@ -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 \

View File

@@ -24,6 +24,8 @@
namespace Rust {
void expand_cfg_attrs (AST::AttrVec &attrs);
// forward declare
struct ExpansionCfg;

View File

@@ -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

View File

@@ -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

View File

@@ -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)