https://gcc.gnu.org/g:751000cd47c280a5799559f6892cf99e8149b2a4
commit r17-3082-g751000cd47c280a5799559f6892cf99e8149b2a4 Author: Owen Avery <[email protected]> Date: Sun Jun 28 22:50:06 2026 -0400 gccrs: Add compatible version option GCCRS targets version 1.49 of rust. However, rust for linux expects rust 1.78 or later (soon 1.85 or later) and we will want to bump our main target version from 1.49 eventually. This patch adds an option for the user to specify a rust version to target for compatibility, so that we can account for backwards incompatible behavior between rust versions. This should allow libcore 1.49 to compile without explicitly enabling post-1.49 features. gcc/rust/ChangeLog: * checks/errors/feature/rust-feature-collector.cc: Include "rust-session-manager.h". (FeatureCollector::collect): Automatically enable EXTENDED_KEY_VALUE_ATTRIBUTES when targeting compatibility with rust versions before 1.50. * expand/rust-macro-expand.cc: Include "rust-session-manager.h". (MacroExpander::expand_invoc): Use Session to determine whether offset_of is supported. * lang.opt (frust-assume-builtin-offset-of): Remove option, superseded by... (frust-compat-version): ...new option. * resolve/rust-early-name-resolver-2.0.cc: Include "rust-session-manager.h". (Early::visit (MacroInvocation)): Use Session to determine whether offset_of is supported. * rust-session-manager.cc (Session::handle_option): Handle frust-compat-version. * rust-session-manager.h (CompileOptions::compat_version): New member variable. (CompileOptions::set_compat_version): New member function. (CompileOptions::get_compat_version): Likewise. (Session::get_compat_version): Likewise. (Session::should_support_offset_of): Likewise. gcc/testsuite/ChangeLog: * rust/compile/early_feature_gate_in_macro.rs: Change test options. * rust/compile/offset_of1.rs: Likewise. * rust/compile/offset_of2.rs: Likewise. * rust/compile/parse_time_feature_gate.rs: Likewise. * rust/execute/torture/offset_of1.rs: Likewise. Signed-off-by: Owen Avery <[email protected]> Diff: --- .../errors/feature/rust-feature-collector.cc | 6 +++++ gcc/rust/expand/rust-macro-expand.cc | 3 ++- gcc/rust/lang.opt | 6 ++--- gcc/rust/resolve/rust-early-name-resolver-2.0.cc | 5 ++-- gcc/rust/rust-session-manager.cc | 3 +++ gcc/rust/rust-session-manager.h | 30 ++++++++++++++++++++++ .../rust/compile/early_feature_gate_in_macro.rs | 1 + gcc/testsuite/rust/compile/offset_of1.rs | 2 +- gcc/testsuite/rust/compile/offset_of2.rs | 2 +- .../rust/compile/parse_time_feature_gate.rs | 1 + gcc/testsuite/rust/execute/torture/offset_of1.rs | 2 +- 11 files changed, 52 insertions(+), 9 deletions(-) diff --git a/gcc/rust/checks/errors/feature/rust-feature-collector.cc b/gcc/rust/checks/errors/feature/rust-feature-collector.cc index 6a3a1479227f..bd5a910d96c6 100644 --- a/gcc/rust/checks/errors/feature/rust-feature-collector.cc +++ b/gcc/rust/checks/errors/feature/rust-feature-collector.cc @@ -18,6 +18,7 @@ #include "rust-feature-collector.h" #include "rust-attribute-values.h" +#include "rust-session-manager.h" namespace Rust { namespace Features { @@ -32,6 +33,11 @@ FeatureCollector::collect (AST::Crate &crate) features.valid_lib_features.clear (); features.crate_id = crate.get_node_id (); + // TODO: this is a hack, remove when possible + if (Session::get_instance ().get_compat_version () < 50) + features.valid_lang_features.insert ( + Feature::Name::EXTENDED_KEY_VALUE_ATTRIBUTES); + visit (crate); return features; diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index c06290cdfda2..2ab9d2541dcb 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -29,6 +29,7 @@ #include "rust-cfg-strip.h" #include "rust-proc-macro.h" #include "rust-token-tree-desugar.h" +#include "rust-session-manager.h" namespace Rust { @@ -311,7 +312,7 @@ MacroExpander::expand_invoc (AST::MacroInvocation &invoc, // We special case the `offset_of!()` macro if the flag is here and manually // resolve to the builtin transcriber we have specified auto assume_builtin_offset_of - = flag_assume_builtin_offset_of + = Session::get_instance ().should_support_offset_of () && (invoc.get_invoc_data ().get_path ().as_string () == "offset_of") && !rules_def; diff --git a/gcc/rust/lang.opt b/gcc/rust/lang.opt index 1d38fec8635a..f996ec0f0a58 100644 --- a/gcc/rust/lang.opt +++ b/gcc/rust/lang.opt @@ -229,9 +229,9 @@ frust-overflow-checks Rust Var(flag_overflow_checks) Init(1) Enable the overflow checks in code generation. -frust-assume-builtin-offset-of -Rust Var(flag_assume_builtin_offset_of) -Define a built-in offset_of macro in the compiler and assume it is present. +frust-compat-version= +Rust Joined RejectNegative Var(flag_rust_compat_version) +Select a version of rust to target for compatibility. Must be of form '1.x' or 'max'. frust-unused-check-2.0 Rust Var(flag_unused_check_2_0) diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc index 0c5422d2c43a..854102ff90b3 100644 --- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc @@ -30,6 +30,7 @@ #include "rust-finalize-imports-2.0.h" #include "rust-attribute-values.h" #include "rust-identifier-path.h" +#include "rust-session-manager.h" namespace Rust { namespace Resolver2_0 { @@ -318,8 +319,8 @@ Early::visit (AST::MacroInvocation &invoc) // We special case the `offset_of!()` macro if the flag is here, otherwise // we accept whatever `offset_of!()` definition we resolved to. - auto resolve_offset_of - = flag_assume_builtin_offset_of && (path.as_string () == "offset_of"); + auto resolve_offset_of = Session::get_instance ().should_support_offset_of () + && (path.as_string () == "offset_of"); if (invoc.get_kind () == AST::MacroInvocation::InvocKind::Builtin) for (auto &pending_invoc : invoc.get_pending_eager_invocations ()) diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 011ca8b99e88..6a56c956d9e3 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -289,6 +289,9 @@ Session::handle_option ( case OPT_frust_edition_: options.set_edition (flag_rust_edition); break; + case OPT_frust_compat_version_: + options.set_compat_version (flag_rust_compat_version); + break; case OPT_frust_compile_until_: options.set_compile_step (flag_rust_compile_until); break; diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 930012a7bd7f..af5a700b84b3 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -242,6 +242,8 @@ struct CompileOptions bool debug_assertions = false; std::string metadata_output_path; + int compat_version = 49; + /** Structure containing additional attributes to be injected within the * compiled crate from the command line instead of the source code. * @@ -344,6 +346,30 @@ struct CompileOptions const Edition &get_edition () const { return edition; } + void set_compat_version (const char *version) + { + if (!strcmp (version, "max")) + { + compat_version = INT_MAX; + return; + } + + long res; + char *end_ptr; + if (version[0] != '1' || version[1] != '.' || version[2] == '\0' + || (res = strtol (version + 2, &end_ptr, 10), *end_ptr) || res < 0 + || res > INT_MAX) + { + rust_error_at (UNKNOWN_LOCATION, + "compat version must be of form 1.x or be \"max\""); + return; + } + + compat_version = res; + } + + int get_compat_version () const { return compat_version; } + void set_crate_type (int raw_type) { target_data.set_crate_type (raw_type); } bool is_proc_macro () const @@ -474,6 +500,10 @@ public: tl::expected<LoadedCrate, LoadingError> load_extern_crate (const std::string &crate_name, location_t locus); + int get_compat_version () const { return options.get_compat_version (); } + + bool should_support_offset_of () const { return get_compat_version () >= 71; } + private: Session () : mappings (Analysis::Mappings::get ()) {} void compile_crate (const char *filename); diff --git a/gcc/testsuite/rust/compile/early_feature_gate_in_macro.rs b/gcc/testsuite/rust/compile/early_feature_gate_in_macro.rs index 9e2a51027aa6..dd68b920e710 100644 --- a/gcc/testsuite/rust/compile/early_feature_gate_in_macro.rs +++ b/gcc/testsuite/rust/compile/early_feature_gate_in_macro.rs @@ -1,3 +1,4 @@ +// { dg-additional-options "-frust-compat-version=1.50" } #![feature(rustc_attrs)] #![feature(lang_items)] #![feature(no_core)] diff --git a/gcc/testsuite/rust/compile/offset_of1.rs b/gcc/testsuite/rust/compile/offset_of1.rs index 2fca6d5eed2d..ff1bd4a21508 100644 --- a/gcc/testsuite/rust/compile/offset_of1.rs +++ b/gcc/testsuite/rust/compile/offset_of1.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-compile-until=lowering -frust-assume-builtin-offset-of" } +// { dg-additional-options "-frust-compile-until=lowering -frust-compat-version=1.71" } #![feature(no_core)] #![no_core] diff --git a/gcc/testsuite/rust/compile/offset_of2.rs b/gcc/testsuite/rust/compile/offset_of2.rs index 2f2fa00a305f..143aab1e0eba 100644 --- a/gcc/testsuite/rust/compile/offset_of2.rs +++ b/gcc/testsuite/rust/compile/offset_of2.rs @@ -1,4 +1,4 @@ -// { dg-additional-options "-frust-compile-until=compilation -frust-assume-builtin-offset-of" } +// { dg-additional-options "-frust-compile-until=compilation -frust-compat-version=1.71" } #![feature(no_core)] #![no_core] diff --git a/gcc/testsuite/rust/compile/parse_time_feature_gate.rs b/gcc/testsuite/rust/compile/parse_time_feature_gate.rs index 907ac0c519b5..1affcd81a5a3 100644 --- a/gcc/testsuite/rust/compile/parse_time_feature_gate.rs +++ b/gcc/testsuite/rust/compile/parse_time_feature_gate.rs @@ -1,3 +1,4 @@ +// { dg-additional-options "-frust-compat-version=1.50" } #![feature(no_core)] #![no_core] #![feature(rustc_attrs)] diff --git a/gcc/testsuite/rust/execute/torture/offset_of1.rs b/gcc/testsuite/rust/execute/torture/offset_of1.rs index d8ab9eba4d35..9d17b2bb2cf8 100644 --- a/gcc/testsuite/rust/execute/torture/offset_of1.rs +++ b/gcc/testsuite/rust/execute/torture/offset_of1.rs @@ -1,5 +1,5 @@ // { dg-do run { target x86_64*-*-* } } -// { dg-additional-options "-frust-assume-builtin-offset-of" } +// { dg-additional-options "-frust-compat-version=1.71" } #![feature(no_core)] #![no_core]
