Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 28 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NoMangleParser {
pub(crate) struct UsedParser {
first_compiler: Option<Span>,
first_linker: Option<Span>,
first_default: Option<Span>,
}

// A custom `AttributeParser` is used rather than a Simple attribute parser because
Expand All @@ -382,7 +383,7 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
template!(Word, List: &["compiler", "linker"]),
|group: &mut Self, cx, args| {
let used_by = match args {
ArgParser::NoArgs => UsedBy::Linker,
ArgParser::NoArgs => UsedBy::Default,
ArgParser::List(list) => {
let Some(l) = list.single() else {
cx.expected_single_argument(list.span);
Expand Down Expand Up @@ -423,12 +424,29 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
ArgParser::NameValue(_) => return,
};

let attr_span = cx.attr_span;

// `#[used]` is interpreted as `#[used(linker)]` (though depending on target OS the
// circumstances are more complicated). While we're checking `used_by`, also report
// these cross-`UsedBy` duplicates to warn.
let target = match used_by {
UsedBy::Compiler => &mut group.first_compiler,
UsedBy::Linker => &mut group.first_linker,
UsedBy::Linker => {
if let Some(prev) = group.first_default {
cx.warn_unused_duplicate(prev, attr_span);
return;
}
&mut group.first_linker
}
UsedBy::Default => {
if let Some(prev) = group.first_linker {
cx.warn_unused_duplicate(prev, attr_span);
return;
}
&mut group.first_default
}
};

let attr_span = cx.attr_span;
if let Some(prev) = *target {
cx.warn_unused_duplicate(prev, attr_span);
} else {
Expand All @@ -440,11 +458,13 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);

fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
// Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
Some(match (self.first_compiler, self.first_linker) {
(_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span },
(Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
(None, None) => return None,
// If a specific form of `used` is specified, it takes precedence over generic `#[used]`.
// If both `linker` and `compiler` are specified, use `linker`.
Some(match (self.first_compiler, self.first_linker, self.first_default) {
(_, Some(span), _) => AttributeKind::Used { used_by: UsedBy::Linker, span },
(Some(span), _, _) => AttributeKind::Used { used_by: UsedBy::Compiler, span },
(_, _, Some(span)) => AttributeKind::Used { used_by: UsedBy::Default, span },
(None, None, None) => return None,
})
}
}
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_codegen_ssa/src/codegen_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,19 @@ fn process_builtin_attrs(
AttributeKind::Used { used_by, .. } => match used_by {
UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
UsedBy::Default => {
let used_form = if tcx.sess.target.os == "illumos" {
// illumos' `ld` doesn't support a section header that would represent
// `#[used(linker)]`, see
// https://github.com/rust-lang/rust/issues/146169. For that target,
// downgrade as if `#[used(compiler)]` was requested and hope for the
// best.
CodegenFnAttrFlags::USED_COMPILER
} else {
CodegenFnAttrFlags::USED_LINKER
};
codegen_fn_attrs.flags |= used_form;
}
},
AttributeKind::FfiConst(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_hir/src/attrs/data_structures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,13 @@ impl Deprecation {
}

/// There are three valid forms of the attribute:
/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable.
/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
/// `#[used(compiler)]`
/// `#[used(linker)]`
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic, PrintAttribute)]
pub enum UsedBy {
Default,
Compiler,
Linker,
}
Expand Down
Loading