Port #[cfi_encoding] to attribute parser

This commit is contained in:
Edvin Bryntesson 2025-12-21 21:45:15 +01:00
parent 38c667265b
commit d719a49b28
No known key found for this signature in database
11 changed files with 83 additions and 63 deletions

View file

@ -0,0 +1,33 @@
use super::prelude::*;
pub(crate) struct CfiEncodingParser;
impl<S: Stage> SingleAttributeParser<S> for CfiEncodingParser {
const PATH: &[Symbol] = &[sym::cfi_encoding];
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
Allow(Target::Struct),
Allow(Target::ForeignTy),
Allow(Target::Enum),
Allow(Target::Union),
]);
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "encoding");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(name_value) = args.name_value() else {
cx.expected_name_value(cx.attr_span, Some(sym::cfi_encoding));
return None;
};
let Some(value_str) = name_value.value_as_str() else {
cx.expected_string_literal(name_value.value_span, None);
return None;
};
if value_str.as_str().trim().is_empty() {
cx.expected_non_empty_string_literal(name_value.value_span);
return None;
}
Some(AttributeKind::CfiEncoding { encoding: value_str })
}
}

View file

@ -33,6 +33,7 @@ pub(crate) mod allow_unstable;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_select;
pub(crate) mod cfi_encoding;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod crate_level;

View file

@ -19,6 +19,7 @@ use crate::attributes::allow_unstable::{
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
};
use crate::attributes::body::CoroutineParser;
use crate::attributes::cfi_encoding::CfiEncodingParser;
use crate::attributes::codegen_attrs::{
ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser,
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
@ -187,6 +188,7 @@ attribute_parsers!(
// tidy-alphabetical-end
// tidy-alphabetical-start
Single<CfiEncodingParser>,
Single<CoverageParser>,
Single<CrateNameParser>,
Single<CustomMirParser>,

View file

@ -703,6 +703,9 @@ pub enum AttributeKind {
span: Span,
},
/// Represents `#[cfi_encoding]`
CfiEncoding { encoding: Symbol },
/// Represents `#[rustc_coinductive]`.
Coinductive(Span),

View file

@ -26,6 +26,7 @@ impl AttributeKind {
AsPtr(..) => Yes,
AutomaticallyDerived(..) => Yes,
BodyStability { .. } => No,
CfiEncoding { .. } => Yes,
Coinductive(..) => No,
Cold(..) => No,
Confusables { .. } => Yes,

View file

@ -298,6 +298,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::PinV2(..)
| AttributeKind::WindowsSubsystem(..)
| AttributeKind::ThreadLocal
| AttributeKind::CfiEncoding { .. }
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -336,7 +337,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::cfg_trace
| sym::cfg_attr_trace
// need to be fixed
| sym::cfi_encoding // FIXME(cfi_encoding)
| sym::instruction_set // broken on stable!!!
| sym::patchable_function_entry // FIXME(patchable_function_entry)
| sym::deprecated_safe // FIXME(deprecated_safe)

View file

@ -11,6 +11,8 @@ use rustc_abi::{ExternAbi, Integer};
use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, CASE_INSENSITIVE, ToBaseN};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::find_attr;
use rustc_middle::bug;
use rustc_middle::ty::layout::IntegerExt;
use rustc_middle::ty::{
@ -18,7 +20,6 @@ use rustc_middle::ty::{
IntTy, List, Region, RegionKind, TermKind, Ty, TyCtxt, TypeFoldable, UintTy,
};
use rustc_span::def_id::DefId;
use rustc_span::sym;
use tracing::instrument;
use crate::cfi::typeid::TypeIdOptions;
@ -446,36 +447,20 @@ pub(crate) fn encode_ty<'tcx>(
ty::Adt(adt_def, args) => {
let mut s = String::new();
let def_id = adt_def.did();
if let Some(cfi_encoding) = tcx.get_attr(def_id, sym::cfi_encoding) {
if let Some(encoding) = find_attr!(tcx.get_all_attrs(def_id), AttributeKind::CfiEncoding { encoding } => encoding)
{
let encoding = encoding.as_str().trim();
// Use user-defined CFI encoding for type
if let Some(value_str) = cfi_encoding.value_str() {
let value_str = value_str.as_str().trim();
if !value_str.is_empty() {
s.push_str(value_str);
// Don't compress user-defined builtin types (see
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-builtin and
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
let builtin_types = [
"v", "w", "b", "c", "a", "h", "s", "t", "i", "j", "l", "m", "x", "y",
"n", "o", "f", "d", "e", "g", "z", "Dh",
];
if !builtin_types.contains(&value_str) {
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
}
} else {
#[allow(
rustc::diagnostic_outside_of_impl,
rustc::untranslatable_diagnostic
)]
tcx.dcx()
.struct_span_err(
cfi_encoding.span(),
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
)
.emit();
}
} else {
bug!("encode_ty: invalid `cfi_encoding` for `{:?}`", ty.kind());
s.push_str(&encoding);
// Don't compress user-defined builtin types (see
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-builtin and
// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression).
let builtin_types = [
"v", "w", "b", "c", "a", "h", "s", "t", "i", "j", "l", "m", "x", "y", "n", "o",
"f", "d", "e", "g", "z", "Dh",
];
if !builtin_types.contains(&encoding) {
compress(dict, DictKey::Ty(ty, TyQ::None), &mut s);
}
} else if options.contains(EncodeTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c() {
// For cross-language LLVM CFI support, the encoding must be compatible at the FFI
@ -508,26 +493,11 @@ pub(crate) fn encode_ty<'tcx>(
ty::Foreign(def_id) => {
// <length><name>, where <name> is <unscoped-name>
let mut s = String::new();
if let Some(cfi_encoding) = tcx.get_attr(*def_id, sym::cfi_encoding) {
if let Some(encoding) = find_attr!(tcx.get_all_attrs(*def_id), AttributeKind::CfiEncoding {encoding} => encoding)
{
// Use user-defined CFI encoding for type
if let Some(value_str) = cfi_encoding.value_str() {
if !value_str.to_string().trim().is_empty() {
s.push_str(value_str.to_string().trim());
} else {
#[allow(
rustc::diagnostic_outside_of_impl,
rustc::untranslatable_diagnostic
)]
tcx.dcx()
.struct_span_err(
cfi_encoding.span(),
format!("invalid `cfi_encoding` for `{:?}`", ty.kind()),
)
.emit();
}
} else {
bug!("encode_ty: invalid `cfi_encoding` for `{:?}`", ty.kind());
}
s.push_str(encoding.as_str().trim());
} else {
let name = tcx.item_name(*def_id).to_string();
let _ = write!(s, "{}{}", name.len(), name);

View file

@ -6,15 +6,15 @@
use std::iter;
use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{self as hir, LangItem, find_attr};
use rustc_middle::bug;
use rustc_middle::ty::{
self, AssocContainer, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, TraitRef,
Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UintTy,
};
use rustc_span::DUMMY_SP;
use rustc_span::def_id::DefId;
use rustc_span::{DUMMY_SP, sym};
use rustc_trait_selection::traits;
use tracing::{debug, instrument};
@ -138,7 +138,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
{
// Don't transform repr(transparent) types with an user-defined CFI encoding to
// preserve the user-defined CFI encoding.
if let Some(_) = self.tcx.get_attr(adt_def.did(), sym::cfi_encoding) {
if find_attr!(
self.tcx.get_all_attrs(adt_def.did()),
AttributeKind::CfiEncoding { .. }
) {
return t;
}
let variant = adt_def.non_enum_variant();

View file

@ -137,7 +137,7 @@ pub fn test3() {}
//~^ ERROR malformed
#[must_not_suspend()]
//~^ ERROR malformed
#[cfi_encoding]
#[cfi_encoding = ""]
//~^ ERROR malformed
struct Test;

View file

@ -55,12 +55,6 @@ LL - #[must_not_suspend()]
LL + #[must_not_suspend]
|
error: malformed `cfi_encoding` attribute input
--> $DIR/malformed-attrs.rs:140:1
|
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
error: malformed `allow` attribute input
--> $DIR/malformed-attrs.rs:184:1
|
@ -530,6 +524,15 @@ LL | #[rustc_layout_scalar_valid_range_end]
| expected this to be a list
| help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
error[E0539]: malformed `cfi_encoding` attribute input
--> $DIR/malformed-attrs.rs:140:1
|
LL | #[cfi_encoding = ""]
| ^^^^^^^^^^^^^^^^^--^
| | |
| | string is not allowed to be empty
| help: must be of the form: `#[cfi_encoding = "encoding"]`
error[E0565]: malformed `marker` attribute input
--> $DIR/malformed-attrs.rs:161:1
|

View file

@ -1,8 +1,12 @@
error: malformed `cfi_encoding` attribute input
error[E0539]: malformed `cfi_encoding` attribute input
--> $DIR/invalid-attr-encoding.rs:10:1
|
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
| ^^^^^^^^^^^^^^^
| |
| expected this to be of the form `cfi_encoding = "..."`
| help: must be of the form: `#[cfi_encoding = "encoding"]`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0539`.