Port the #[link] attribute to the new parser
This commit is contained in:
parent
aab5e0bf1f
commit
e8d08b5416
14 changed files with 639 additions and 623 deletions
|
|
@ -195,3 +195,55 @@ attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`
|
|||
|
||||
attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
|
||||
.help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
|
||||
|
||||
attr_parsing_as_needed_compatibility =
|
||||
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
|
||||
|
||||
attr_parsing_bundle_needs_static =
|
||||
linking modifier `bundle` is only compatible with `static` linking kind
|
||||
|
||||
attr_parsing_empty_link_name =
|
||||
link name must not be empty
|
||||
.label = empty link name
|
||||
|
||||
attr_parsing_import_name_type_raw =
|
||||
import name type can only be used with link kind `raw-dylib`
|
||||
|
||||
attr_parsing_import_name_type_x86 =
|
||||
import name type is only supported on x86
|
||||
|
||||
attr_parsing_incompatible_wasm_link =
|
||||
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
|
||||
|
||||
attr_parsing_invalid_link_modifier =
|
||||
invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
|
||||
|
||||
attr_parsing_link_arg_unstable =
|
||||
link kind `link-arg` is unstable
|
||||
|
||||
attr_parsing_link_cfg_unstable =
|
||||
link cfg is unstable
|
||||
|
||||
attr_parsing_link_framework_apple =
|
||||
link kind `framework` is only supported on Apple targets
|
||||
|
||||
attr_parsing_link_requires_name =
|
||||
`#[link]` attribute requires a `name = "string"` argument
|
||||
.label = missing `name` argument
|
||||
|
||||
attr_parsing_multiple_modifiers =
|
||||
multiple `{$modifier}` modifiers in a single `modifiers` argument
|
||||
|
||||
attr_parsing_multiple_renamings =
|
||||
multiple renamings were specified for library `{$lib_name}`
|
||||
attr_parsing_raw_dylib_no_nul =
|
||||
link name must not contain NUL characters if link kind is `raw-dylib`
|
||||
|
||||
attr_parsing_raw_dylib_elf_unstable =
|
||||
link kind `raw-dylib` is unstable on ELF platforms
|
||||
|
||||
attr_parsing_raw_dylib_only_windows =
|
||||
link kind `raw-dylib` is only supported on Windows targets
|
||||
|
||||
attr_parsing_whole_archive_needs_static =
|
||||
linking modifier `whole-archive` is only compatible with `static` linking kind
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ pub fn parse_cfg_attr<'c, S: Stage>(
|
|||
parse_cfg_entry(cx, single)
|
||||
}
|
||||
|
||||
fn parse_cfg_entry<S: Stage>(
|
||||
pub(crate) fn parse_cfg_entry<S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
item: &MetaItemOrLitParser<'_>,
|
||||
) -> Option<CfgEntry> {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
use rustc_feature::Features;
|
||||
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
|
||||
use rustc_hir::attrs::Linkage;
|
||||
use rustc_hir::attrs::*;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::kw;
|
||||
use rustc_target::spec::BinaryFormat;
|
||||
|
||||
use super::prelude::*;
|
||||
use super::util::parse_single_integer;
|
||||
use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
|
||||
use crate::attributes::cfg::parse_cfg_entry;
|
||||
use crate::fluent_generated;
|
||||
use crate::session_diagnostics::{
|
||||
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86,
|
||||
IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange,
|
||||
LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
|
||||
WholeArchiveNeedsStatic,
|
||||
};
|
||||
|
||||
pub(crate) struct LinkNameParser;
|
||||
|
||||
|
|
@ -34,6 +46,409 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LinkParser;
|
||||
|
||||
impl<S: Stage> CombineAttributeParser<S> for LinkParser {
|
||||
type Item = LinkEntry;
|
||||
const PATH: &[Symbol] = &[sym::link];
|
||||
const CONVERT: ConvertFn<Self::Item> = AttributeKind::Link;
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &[
|
||||
r#"name = "...""#,
|
||||
r#"name = "...", kind = "dylib|static|...""#,
|
||||
r#"name = "...", wasm_import_module = "...""#,
|
||||
r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#,
|
||||
r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#,
|
||||
], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute");
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
|
||||
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
args: &'c ArgParser<'_>,
|
||||
) -> impl IntoIterator<Item = Self::Item> + 'c {
|
||||
let mut result = None;
|
||||
let Some(items) = args.list() else {
|
||||
cx.expected_list(cx.attr_span);
|
||||
return result;
|
||||
};
|
||||
|
||||
let sess = cx.sess();
|
||||
let features = cx.features();
|
||||
|
||||
let mut name = None;
|
||||
let mut kind = None;
|
||||
let mut modifiers = None;
|
||||
let mut cfg = None;
|
||||
let mut wasm_import_module = None;
|
||||
let mut import_name_type = None;
|
||||
for item in items.mixed() {
|
||||
let Some(item) = item.meta_item() else {
|
||||
cx.unexpected_literal(item.span());
|
||||
continue;
|
||||
};
|
||||
|
||||
let cont = match item.path().word().map(|ident| ident.name) {
|
||||
Some(sym::name) => Self::parse_link_name(item, &mut name, cx),
|
||||
Some(sym::kind) => Self::parse_link_kind(item, &mut kind, cx, sess, features),
|
||||
Some(sym::modifiers) => Self::parse_link_modifiers(item, &mut modifiers, cx),
|
||||
Some(sym::cfg) => Self::parse_link_cfg(item, &mut cfg, cx, sess, features),
|
||||
Some(sym::wasm_import_module) => {
|
||||
Self::parse_link_wasm_import_module(item, &mut wasm_import_module, cx)
|
||||
}
|
||||
Some(sym::import_name_type) => {
|
||||
Self::parse_link_import_name_type(item, &mut import_name_type, cx)
|
||||
}
|
||||
_ => {
|
||||
cx.expected_specific_argument_strings(
|
||||
item.span(),
|
||||
&[
|
||||
sym::name,
|
||||
sym::kind,
|
||||
sym::modifiers,
|
||||
sym::cfg,
|
||||
sym::wasm_import_module,
|
||||
sym::import_name_type,
|
||||
],
|
||||
);
|
||||
true
|
||||
}
|
||||
};
|
||||
if !cont {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Do this outside the above loop so we don't depend on modifiers coming after kinds
|
||||
let mut verbatim = None;
|
||||
if let Some((modifiers, span)) = modifiers {
|
||||
for modifier in modifiers.as_str().split(',') {
|
||||
let (modifier, value): (Symbol, bool) = match modifier.strip_prefix(&['+', '-']) {
|
||||
Some(m) => (Symbol::intern(m), modifier.starts_with('+')),
|
||||
None => {
|
||||
cx.emit_err(InvalidLinkModifier { span });
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
macro report_unstable_modifier($feature: ident) {
|
||||
if !features.$feature() {
|
||||
// FIXME: make this translatable
|
||||
#[expect(rustc::untranslatable_diagnostic)]
|
||||
feature_err(
|
||||
sess,
|
||||
sym::$feature,
|
||||
span,
|
||||
format!("linking modifier `{modifier}` is unstable"),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
let assign_modifier = |dst: &mut Option<bool>| {
|
||||
if dst.is_some() {
|
||||
cx.emit_err(MultipleModifiers { span, modifier });
|
||||
} else {
|
||||
*dst = Some(value);
|
||||
}
|
||||
};
|
||||
match (modifier, &mut kind) {
|
||||
(sym::bundle, Some(NativeLibKind::Static { bundle, .. })) => {
|
||||
assign_modifier(bundle)
|
||||
}
|
||||
(sym::bundle, _) => {
|
||||
cx.emit_err(BundleNeedsStatic { span });
|
||||
}
|
||||
|
||||
(sym::verbatim, _) => assign_modifier(&mut verbatim),
|
||||
|
||||
(
|
||||
sym::whole_dash_archive,
|
||||
Some(NativeLibKind::Static { whole_archive, .. }),
|
||||
) => assign_modifier(whole_archive),
|
||||
(sym::whole_dash_archive, _) => {
|
||||
cx.emit_err(WholeArchiveNeedsStatic { span });
|
||||
}
|
||||
|
||||
(sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
|
||||
| (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
|
||||
report_unstable_modifier!(native_link_modifiers_as_needed);
|
||||
assign_modifier(as_needed)
|
||||
}
|
||||
(sym::as_dash_needed, _) => {
|
||||
cx.emit_err(AsNeededCompatibility { span });
|
||||
}
|
||||
|
||||
_ => {
|
||||
cx.expected_specific_argument_strings(
|
||||
span,
|
||||
&[
|
||||
sym::bundle,
|
||||
sym::verbatim,
|
||||
sym::whole_dash_archive,
|
||||
sym::as_dash_needed,
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((_, span)) = wasm_import_module {
|
||||
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
|
||||
cx.emit_err(IncompatibleWasmLink { span });
|
||||
}
|
||||
}
|
||||
|
||||
if wasm_import_module.is_some() {
|
||||
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
|
||||
}
|
||||
let Some((name, name_span)) = name else {
|
||||
cx.emit_err(LinkRequiresName { span: cx.attr_span });
|
||||
return result;
|
||||
};
|
||||
|
||||
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
|
||||
if let Some((_, span)) = import_name_type {
|
||||
if kind != Some(NativeLibKind::RawDylib) {
|
||||
cx.emit_err(ImportNameTypeRaw { span });
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(NativeLibKind::RawDylib) = kind
|
||||
&& name.as_str().contains('\0')
|
||||
{
|
||||
cx.emit_err(RawDylibNoNul { span: name_span });
|
||||
}
|
||||
|
||||
result = Some(LinkEntry {
|
||||
span: cx.attr_span,
|
||||
kind: kind.unwrap_or(NativeLibKind::Unspecified),
|
||||
name,
|
||||
cfg,
|
||||
verbatim,
|
||||
import_name_type,
|
||||
});
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl LinkParser {
|
||||
fn parse_link_name<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
name: &mut Option<(Symbol, Span)>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> bool {
|
||||
if name.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::name);
|
||||
return true;
|
||||
}
|
||||
let Some(nv) = item.args().name_value() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::name));
|
||||
return false;
|
||||
};
|
||||
let Some(link_name) = nv.value_as_str() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::name));
|
||||
return false;
|
||||
};
|
||||
|
||||
if link_name.is_empty() {
|
||||
cx.emit_err(EmptyLinkName { span: nv.value_span });
|
||||
}
|
||||
*name = Some((link_name, nv.value_span));
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_link_kind<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
kind: &mut Option<NativeLibKind>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
) -> bool {
|
||||
if kind.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::kind);
|
||||
return true;
|
||||
}
|
||||
let Some(nv) = item.args().name_value() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::kind));
|
||||
return true;
|
||||
};
|
||||
let Some(link_kind) = nv.value_as_str() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::kind));
|
||||
return true;
|
||||
};
|
||||
|
||||
let link_kind = match link_kind {
|
||||
kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
sym::dylib => NativeLibKind::Dylib { as_needed: None },
|
||||
sym::framework => {
|
||||
if !sess.target.is_like_darwin {
|
||||
cx.emit_err(LinkFrameworkApple { span: nv.value_span });
|
||||
}
|
||||
NativeLibKind::Framework { as_needed: None }
|
||||
}
|
||||
sym::raw_dash_dylib => {
|
||||
if sess.target.is_like_windows {
|
||||
// raw-dylib is stable and working on Windows
|
||||
} else if sess.target.binary_format == BinaryFormat::Elf && features.raw_dylib_elf()
|
||||
{
|
||||
// raw-dylib is unstable on ELF, but the user opted in
|
||||
} else if sess.target.binary_format == BinaryFormat::Elf && sess.is_nightly_build()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::raw_dylib_elf,
|
||||
nv.value_span,
|
||||
fluent_generated::attr_parsing_raw_dylib_elf_unstable,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
|
||||
}
|
||||
|
||||
NativeLibKind::RawDylib
|
||||
}
|
||||
sym::link_dash_arg => {
|
||||
if !features.link_arg_attribute() {
|
||||
feature_err(
|
||||
sess,
|
||||
sym::link_arg_attribute,
|
||||
nv.value_span,
|
||||
fluent_generated::attr_parsing_link_arg_unstable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
NativeLibKind::LinkArg
|
||||
}
|
||||
_kind => {
|
||||
cx.expected_specific_argument_strings(
|
||||
nv.value_span,
|
||||
&[
|
||||
kw::Static,
|
||||
sym::dylib,
|
||||
sym::framework,
|
||||
sym::raw_dash_dylib,
|
||||
sym::link_dash_arg,
|
||||
],
|
||||
);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
*kind = Some(link_kind);
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_link_modifiers<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
modifiers: &mut Option<(Symbol, Span)>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> bool {
|
||||
if modifiers.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::modifiers);
|
||||
return true;
|
||||
}
|
||||
let Some(nv) = item.args().name_value() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::modifiers));
|
||||
return true;
|
||||
};
|
||||
let Some(link_modifiers) = nv.value_as_str() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::modifiers));
|
||||
return true;
|
||||
};
|
||||
*modifiers = Some((link_modifiers, nv.value_span));
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_link_cfg<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
cfg: &mut Option<CfgEntry>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
sess: &Session,
|
||||
features: &Features,
|
||||
) -> bool {
|
||||
if cfg.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::cfg);
|
||||
return true;
|
||||
}
|
||||
let Some(link_cfg) = item.args().list() else {
|
||||
cx.expected_list(item.span());
|
||||
return true;
|
||||
};
|
||||
let Some(link_cfg) = link_cfg.single() else {
|
||||
cx.expected_single_argument(item.span());
|
||||
return true;
|
||||
};
|
||||
if !features.link_cfg() {
|
||||
feature_err(
|
||||
sess,
|
||||
sym::link_cfg,
|
||||
item.span(),
|
||||
fluent_generated::attr_parsing_link_cfg_unstable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
*cfg = parse_cfg_entry(cx, link_cfg);
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_link_wasm_import_module<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
wasm_import_module: &mut Option<(Symbol, Span)>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> bool {
|
||||
if wasm_import_module.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::wasm_import_module);
|
||||
return true;
|
||||
}
|
||||
let Some(nv) = item.args().name_value() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
|
||||
return true;
|
||||
};
|
||||
let Some(link_wasm_import_module) = nv.value_as_str() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
|
||||
return true;
|
||||
};
|
||||
*wasm_import_module = Some((link_wasm_import_module, item.span()));
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_link_import_name_type<S: Stage>(
|
||||
item: &MetaItemParser<'_>,
|
||||
import_name_type: &mut Option<(PeImportNameType, Span)>,
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
) -> bool {
|
||||
if import_name_type.is_some() {
|
||||
cx.duplicate_key(item.span(), sym::import_name_type);
|
||||
return true;
|
||||
}
|
||||
let Some(nv) = item.args().name_value() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::import_name_type));
|
||||
return true;
|
||||
};
|
||||
let Some(link_import_name_type) = nv.value_as_str() else {
|
||||
cx.expected_name_value(item.span(), Some(sym::import_name_type));
|
||||
return true;
|
||||
};
|
||||
if cx.sess().target.arch != "x86" {
|
||||
cx.emit_err(ImportNameTypeX86 { span: item.span() });
|
||||
return true;
|
||||
}
|
||||
|
||||
let link_import_name_type = match link_import_name_type {
|
||||
sym::decorated => PeImportNameType::Decorated,
|
||||
sym::noprefix => PeImportNameType::NoPrefix,
|
||||
sym::undecorated => PeImportNameType::Undecorated,
|
||||
_ => {
|
||||
cx.expected_specific_argument_strings(
|
||||
item.span(),
|
||||
&[sym::decorated, sym::noprefix, sym::undecorated],
|
||||
);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
*import_name_type = Some((link_import_name_type, item.span()));
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LinkSectionParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use crate::attributes::dummy::DummyParser;
|
|||
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
|
||||
use crate::attributes::link_attrs::{
|
||||
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
|
||||
LinkSectionParser, LinkageParser, StdInternalSymbolParser,
|
||||
LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
|
||||
};
|
||||
use crate::attributes::lint_helpers::{
|
||||
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
|
||||
|
|
@ -162,6 +162,7 @@ attribute_parsers!(
|
|||
Combine<AllowConstFnUnstableParser>,
|
||||
Combine<AllowInternalUnstableParser>,
|
||||
Combine<ForceTargetFeatureParser>,
|
||||
Combine<LinkParser>,
|
||||
Combine<ReprParser>,
|
||||
Combine<TargetFeatureParser>,
|
||||
Combine<UnstableFeatureBoundParser>,
|
||||
|
|
|
|||
|
|
@ -836,3 +836,97 @@ pub(crate) struct InvalidAttrStyle {
|
|||
pub target_span: Option<Span>,
|
||||
pub target: Target,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_empty_link_name, code = E0454)]
|
||||
pub(crate) struct EmptyLinkName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_framework_apple, code = E0455)]
|
||||
pub(crate) struct LinkFrameworkApple {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_incompatible_wasm_link)]
|
||||
pub(crate) struct IncompatibleWasmLink {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_link_requires_name, code = E0459)]
|
||||
pub(crate) struct LinkRequiresName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_raw_dylib_no_nul)]
|
||||
pub(crate) struct RawDylibNoNul {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)]
|
||||
pub(crate) struct RawDylibOnlyWindows {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_invalid_link_modifier)]
|
||||
pub(crate) struct InvalidLinkModifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_multiple_modifiers)]
|
||||
pub(crate) struct MultipleModifiers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub modifier: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_import_name_type_x86)]
|
||||
pub(crate) struct ImportNameTypeX86 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_bundle_needs_static)]
|
||||
pub(crate) struct BundleNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_whole_archive_needs_static)]
|
||||
pub(crate) struct WholeArchiveNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_as_needed_compatibility)]
|
||||
pub(crate) struct AsNeededCompatibility {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(attr_parsing_import_name_type_raw)]
|
||||
pub(crate) struct ImportNameTypeRaw {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,11 +14,13 @@ use itertools::Itertools;
|
|||
use regex::Regex;
|
||||
use rustc_arena::TypedArena;
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||
use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
|
||||
use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
|
||||
use rustc_hir::attrs::NativeLibKind;
|
||||
use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
|
||||
use rustc_macros::LintDiagnostic;
|
||||
use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
|
||||
|
|
@ -38,7 +40,6 @@ use rustc_session::config::{
|
|||
use rustc_session::lint::builtin::LINKER_MESSAGES;
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
/// For all the linkers we support, and information they might
|
||||
/// need out of the shared crate context before we get rid of it.
|
||||
use rustc_session::{Session, filesearch};
|
||||
|
|
@ -3019,7 +3020,9 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
|
|||
|
||||
fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
|
||||
Some(ref cfg) => {
|
||||
eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,10 +25,10 @@ use std::io;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::CRATE_HIR_ID;
|
||||
use rustc_hir::attrs::{CfgEntry, NativeLibKind};
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_macros::{Decodable, Encodable, HashStable};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
|
|
@ -45,7 +45,6 @@ use rustc_session::Session;
|
|||
use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
|
||||
use rustc_session::cstore::{self, CrateSource};
|
||||
use rustc_session::lint::builtin::LINKER_MESSAGES;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
use rustc_span::Symbol;
|
||||
|
||||
pub mod assert_module_sources;
|
||||
|
|
@ -187,7 +186,7 @@ pub struct NativeLib {
|
|||
pub kind: NativeLibKind,
|
||||
pub name: Symbol,
|
||||
pub filename: Option<Symbol>,
|
||||
pub cfg: Option<ast::MetaItemInner>,
|
||||
pub cfg: Option<CfgEntry>,
|
||||
pub verbatim: bool,
|
||||
pub dll_imports: Vec<cstore::DllImport>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -351,6 +351,17 @@ impl NativeLibKind {
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
|
||||
pub struct LinkEntry {
|
||||
pub span: Span,
|
||||
pub kind: NativeLibKind,
|
||||
pub name: Symbol,
|
||||
pub cfg: Option<CfgEntry>,
|
||||
pub verbatim: Option<bool>,
|
||||
pub import_name_type: Option<(PeImportNameType, Span)>,
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
|
|
@ -521,6 +532,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[inline]` and `#[rustc_force_inline]`.
|
||||
Inline(InlineAttr, Span),
|
||||
|
||||
/// Represents `#[link]`.
|
||||
Link(ThinVec<LinkEntry>, Span),
|
||||
|
||||
/// Represents `#[link_name]`.
|
||||
LinkName { name: Symbol, span: Span },
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ impl AttributeKind {
|
|||
Fundamental { .. } => Yes,
|
||||
Ignore { .. } => No,
|
||||
Inline(..) => No,
|
||||
Link(..) => No,
|
||||
LinkName { .. } => Yes, // Needed for rustdoc
|
||||
LinkOrdinal { .. } => No,
|
||||
LinkSection { .. } => Yes, // Needed for rustdoc
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
metadata_as_needed_compatibility =
|
||||
linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
|
||||
|
||||
metadata_async_drop_types_in_dependency =
|
||||
found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
|
||||
.help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
|
||||
|
|
@ -11,9 +8,6 @@ metadata_bad_panic_strategy =
|
|||
metadata_binary_output_to_tty =
|
||||
option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty
|
||||
|
||||
metadata_bundle_needs_static =
|
||||
linking modifier `bundle` is only compatible with `static` linking kind
|
||||
|
||||
metadata_cannot_find_crate =
|
||||
can't find crate for `{$crate_name}`{$add_info}
|
||||
|
||||
|
|
@ -60,10 +54,6 @@ metadata_crate_not_panic_runtime =
|
|||
metadata_dl_error =
|
||||
{$path}{$err}
|
||||
|
||||
metadata_empty_link_name =
|
||||
link name must not be empty
|
||||
.label = empty link name
|
||||
|
||||
metadata_empty_renaming_target =
|
||||
an empty renaming target was specified for library `{$lib_name}`
|
||||
|
||||
|
|
@ -108,15 +98,6 @@ metadata_full_metadata_not_found =
|
|||
metadata_global_alloc_required =
|
||||
no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
|
||||
|
||||
metadata_import_name_type_form =
|
||||
import name type must be of the form `import_name_type = "string"`
|
||||
|
||||
metadata_import_name_type_raw =
|
||||
import name type can only be used with link kind `raw-dylib`
|
||||
|
||||
metadata_import_name_type_x86 =
|
||||
import name type is only supported on x86
|
||||
|
||||
metadata_incompatible_panic_in_drop_strategy =
|
||||
the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
|
||||
|
||||
|
|
@ -143,15 +124,10 @@ metadata_incompatible_target_modifiers_r_missed =
|
|||
mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
|
||||
.note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
|
||||
.help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
|
||||
metadata_incompatible_wasm_link =
|
||||
`wasm_import_module` is incompatible with other arguments in `#[link]` attributes
|
||||
|
||||
metadata_install_missing_components =
|
||||
maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
|
||||
|
||||
metadata_invalid_link_modifier =
|
||||
invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
|
||||
|
||||
metadata_invalid_meta_files =
|
||||
found invalid metadata files for crate `{$crate_name}`{$add_info}
|
||||
|
||||
|
|
@ -164,67 +140,18 @@ metadata_lib_framework_apple =
|
|||
metadata_lib_required =
|
||||
crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
|
||||
|
||||
metadata_link_arg_unstable =
|
||||
link kind `link-arg` is unstable
|
||||
|
||||
metadata_link_cfg_form =
|
||||
link cfg must be of the form `cfg(/* predicate */)`
|
||||
|
||||
metadata_link_cfg_single_predicate =
|
||||
link cfg must have a single predicate argument
|
||||
|
||||
metadata_link_cfg_unstable =
|
||||
link cfg is unstable
|
||||
|
||||
metadata_link_framework_apple =
|
||||
link kind `framework` is only supported on Apple targets
|
||||
|
||||
metadata_link_kind_form =
|
||||
link kind must be of the form `kind = "string"`
|
||||
|
||||
metadata_link_modifiers_form =
|
||||
link modifiers must be of the form `modifiers = "string"`
|
||||
|
||||
metadata_link_name_form =
|
||||
link name must be of the form `name = "string"`
|
||||
|
||||
metadata_link_ordinal_raw_dylib =
|
||||
`#[link_ordinal]` is only supported if link kind is `raw-dylib`
|
||||
|
||||
metadata_link_requires_name =
|
||||
`#[link]` attribute requires a `name = "string"` argument
|
||||
.label = missing `name` argument
|
||||
|
||||
metadata_missing_native_library =
|
||||
could not find native static library `{$libname}`, perhaps an -L flag is missing?
|
||||
|
||||
metadata_multiple_candidates =
|
||||
multiple candidates for `{$flavor}` dependency `{$crate_name}` found
|
||||
|
||||
metadata_multiple_cfgs =
|
||||
multiple `cfg` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_multiple_import_name_type =
|
||||
multiple `import_name_type` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_multiple_kinds_in_link =
|
||||
multiple `kind` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_multiple_link_modifiers =
|
||||
multiple `modifiers` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_multiple_modifiers =
|
||||
multiple `{$modifier}` modifiers in a single `modifiers` argument
|
||||
|
||||
metadata_multiple_names_in_link =
|
||||
multiple `name` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_multiple_renamings =
|
||||
multiple renamings were specified for library `{$lib_name}`
|
||||
|
||||
metadata_multiple_wasm_import =
|
||||
multiple `wasm_import_module` arguments in a single `#[link]` attribute
|
||||
|
||||
metadata_newer_crate_version =
|
||||
found possibly newer version of crate `{$crate_name}`{$add_info}
|
||||
.note = perhaps that crate needs to be recompiled?
|
||||
|
|
@ -263,15 +190,6 @@ metadata_prev_alloc_error_handler =
|
|||
metadata_prev_global_alloc =
|
||||
previous global allocator defined here
|
||||
|
||||
metadata_raw_dylib_elf_unstable =
|
||||
link kind `raw-dylib` is unstable on ELF platforms
|
||||
|
||||
metadata_raw_dylib_no_nul =
|
||||
link name must not contain NUL characters if link kind is `raw-dylib`
|
||||
|
||||
metadata_raw_dylib_only_windows =
|
||||
link kind `raw-dylib` is only supported on Windows targets
|
||||
|
||||
metadata_raw_dylib_unsupported_abi =
|
||||
ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
|
||||
|
||||
|
|
@ -307,19 +225,6 @@ metadata_target_not_installed =
|
|||
metadata_two_panic_runtimes =
|
||||
cannot link together two panic runtimes: {$prev_name} and {$cur_name}
|
||||
|
||||
metadata_unexpected_link_arg =
|
||||
unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
|
||||
|
||||
metadata_unknown_import_name_type =
|
||||
unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
|
||||
|
||||
metadata_unknown_link_kind =
|
||||
unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg
|
||||
.label = unknown link kind
|
||||
|
||||
metadata_unknown_link_modifier =
|
||||
unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
|
||||
|
||||
metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
|
||||
|
||||
metadata_wasm_c_abi =
|
||||
|
|
|
|||
|
|
@ -83,187 +83,6 @@ pub struct IncompatiblePanicInDropStrategy {
|
|||
pub desired_strategy: PanicStrategy,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_names_in_link)]
|
||||
pub struct MultipleNamesInLink {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_kinds_in_link)]
|
||||
pub struct MultipleKindsInLink {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_name_form)]
|
||||
pub struct LinkNameForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_kind_form)]
|
||||
pub struct LinkKindForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_modifiers_form)]
|
||||
pub struct LinkModifiersForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_cfg_form)]
|
||||
pub struct LinkCfgForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_wasm_import_form)]
|
||||
pub struct WasmImportForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_empty_link_name, code = E0454)]
|
||||
pub struct EmptyLinkName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_framework_apple, code = E0455)]
|
||||
pub struct LinkFrameworkApple {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_raw_dylib_only_windows, code = E0455)]
|
||||
pub struct RawDylibOnlyWindows {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unknown_link_kind, code = E0458)]
|
||||
pub struct UnknownLinkKind<'a> {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
pub kind: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_link_modifiers)]
|
||||
pub struct MultipleLinkModifiers {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_cfgs)]
|
||||
pub struct MultipleCfgs {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_cfg_single_predicate)]
|
||||
pub struct LinkCfgSinglePredicate {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_wasm_import)]
|
||||
pub struct MultipleWasmImport {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unexpected_link_arg)]
|
||||
pub struct UnexpectedLinkArg {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_invalid_link_modifier)]
|
||||
pub struct InvalidLinkModifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_modifiers)]
|
||||
pub struct MultipleModifiers<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub modifier: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_bundle_needs_static)]
|
||||
pub struct BundleNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_whole_archive_needs_static)]
|
||||
pub struct WholeArchiveNeedsStatic {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_as_needed_compatibility)]
|
||||
pub struct AsNeededCompatibility {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unknown_link_modifier)]
|
||||
pub struct UnknownLinkModifier<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub modifier: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_incompatible_wasm_link)]
|
||||
pub struct IncompatibleWasmLink {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_requires_name, code = E0459)]
|
||||
pub struct LinkRequiresName {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_raw_dylib_no_nul)]
|
||||
pub struct RawDylibNoNul {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_link_ordinal_raw_dylib)]
|
||||
pub struct LinkOrdinalRawDylib {
|
||||
|
|
@ -706,42 +525,6 @@ pub struct LibFilenameForm<'a> {
|
|||
pub dll_suffix: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_multiple_import_name_type)]
|
||||
pub struct MultipleImportNameType {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_import_name_type_form)]
|
||||
pub struct ImportNameTypeForm {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_import_name_type_x86)]
|
||||
pub struct ImportNameTypeX86 {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_unknown_import_name_type)]
|
||||
pub struct UnknownImportNameType<'a> {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub import_name_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_import_name_type_raw)]
|
||||
pub struct ImportNameTypeRaw {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(metadata_wasm_c_abi)]
|
||||
pub(crate) struct WasmCAbi {
|
||||
|
|
|
|||
|
|
@ -3,25 +3,21 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::CRATE_NODE_ID;
|
||||
use rustc_attr_parsing as attr;
|
||||
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType};
|
||||
use rustc_hir::find_attr;
|
||||
use rustc_middle::query::LocalCrate;
|
||||
use rustc_middle::ty::{self, List, Ty, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::cstore::{
|
||||
DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
|
||||
};
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
use rustc_span::Symbol;
|
||||
use rustc_span::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc_span::{Symbol, sym};
|
||||
use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
|
||||
|
||||
use crate::{errors, fluent_generated};
|
||||
use crate::errors;
|
||||
|
||||
/// The fallback directories are passed to linker, but not used when rustc does the search,
|
||||
/// because in the latter case the set of fallback directories cannot always be determined
|
||||
|
|
@ -192,7 +188,9 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
|
|||
|
||||
pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
|
||||
match lib.cfg {
|
||||
Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
|
||||
Some(ref cfg) => {
|
||||
eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
|
||||
}
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
|
|
@ -213,289 +211,23 @@ impl<'tcx> Collector<'tcx> {
|
|||
return;
|
||||
}
|
||||
|
||||
// Process all of the #[link(..)]-style arguments
|
||||
let features = self.tcx.features();
|
||||
|
||||
for m in self.tcx.get_attrs(def_id, sym::link) {
|
||||
let Some(items) = m.meta_item_list() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let mut name = None;
|
||||
let mut kind = None;
|
||||
let mut modifiers = None;
|
||||
let mut cfg = None;
|
||||
let mut wasm_import_module = None;
|
||||
let mut import_name_type = None;
|
||||
for item in items.iter() {
|
||||
match item.name() {
|
||||
Some(sym::name) => {
|
||||
if name.is_some() {
|
||||
sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_name) = item.value_str() else {
|
||||
sess.dcx().emit_err(errors::LinkNameForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
let span = item.name_value_literal_span().unwrap();
|
||||
if link_name.is_empty() {
|
||||
sess.dcx().emit_err(errors::EmptyLinkName { span });
|
||||
}
|
||||
name = Some((link_name, span));
|
||||
}
|
||||
Some(sym::kind) => {
|
||||
if kind.is_some() {
|
||||
sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_kind) = item.value_str() else {
|
||||
sess.dcx().emit_err(errors::LinkKindForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
|
||||
let span = item.name_value_literal_span().unwrap();
|
||||
let link_kind = match link_kind.as_str() {
|
||||
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
|
||||
"dylib" => NativeLibKind::Dylib { as_needed: None },
|
||||
"framework" => {
|
||||
if !sess.target.is_like_darwin {
|
||||
sess.dcx().emit_err(errors::LinkFrameworkApple { span });
|
||||
}
|
||||
NativeLibKind::Framework { as_needed: None }
|
||||
}
|
||||
"raw-dylib" => {
|
||||
if sess.target.is_like_windows {
|
||||
// raw-dylib is stable and working on Windows
|
||||
} else if sess.target.binary_format == BinaryFormat::Elf
|
||||
&& features.raw_dylib_elf()
|
||||
{
|
||||
// raw-dylib is unstable on ELF, but the user opted in
|
||||
} else if sess.target.binary_format == BinaryFormat::Elf
|
||||
&& sess.is_nightly_build()
|
||||
{
|
||||
feature_err(
|
||||
sess,
|
||||
sym::raw_dylib_elf,
|
||||
span,
|
||||
fluent_generated::metadata_raw_dylib_elf_unstable,
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
|
||||
}
|
||||
|
||||
NativeLibKind::RawDylib
|
||||
}
|
||||
"link-arg" => {
|
||||
if !features.link_arg_attribute() {
|
||||
feature_err(
|
||||
sess,
|
||||
sym::link_arg_attribute,
|
||||
span,
|
||||
fluent_generated::metadata_link_arg_unstable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
NativeLibKind::LinkArg
|
||||
}
|
||||
kind => {
|
||||
sess.dcx().emit_err(errors::UnknownLinkKind { span, kind });
|
||||
continue;
|
||||
}
|
||||
};
|
||||
kind = Some(link_kind);
|
||||
}
|
||||
Some(sym::modifiers) => {
|
||||
if modifiers.is_some() {
|
||||
sess.dcx()
|
||||
.emit_err(errors::MultipleLinkModifiers { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_modifiers) = item.value_str() else {
|
||||
sess.dcx().emit_err(errors::LinkModifiersForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
|
||||
}
|
||||
Some(sym::cfg) => {
|
||||
if cfg.is_some() {
|
||||
sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_cfg) = item.meta_item_list() else {
|
||||
sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
let [link_cfg] = link_cfg else {
|
||||
sess.dcx()
|
||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
let Some(link_cfg) = link_cfg.meta_item_or_bool() else {
|
||||
sess.dcx()
|
||||
.emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
if !features.link_cfg() {
|
||||
feature_err(
|
||||
sess,
|
||||
sym::link_cfg,
|
||||
item.span(),
|
||||
fluent_generated::metadata_link_cfg_unstable,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
cfg = Some(link_cfg.clone());
|
||||
}
|
||||
Some(sym::wasm_import_module) => {
|
||||
if wasm_import_module.is_some() {
|
||||
sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_wasm_import_module) = item.value_str() else {
|
||||
sess.dcx().emit_err(errors::WasmImportForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
wasm_import_module = Some((link_wasm_import_module, item.span()));
|
||||
}
|
||||
Some(sym::import_name_type) => {
|
||||
if import_name_type.is_some() {
|
||||
sess.dcx()
|
||||
.emit_err(errors::MultipleImportNameType { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
let Some(link_import_name_type) = item.value_str() else {
|
||||
sess.dcx().emit_err(errors::ImportNameTypeForm { span: item.span() });
|
||||
continue;
|
||||
};
|
||||
if self.tcx.sess.target.arch != "x86" {
|
||||
sess.dcx().emit_err(errors::ImportNameTypeX86 { span: item.span() });
|
||||
continue;
|
||||
}
|
||||
|
||||
let link_import_name_type = match link_import_name_type.as_str() {
|
||||
"decorated" => PeImportNameType::Decorated,
|
||||
"noprefix" => PeImportNameType::NoPrefix,
|
||||
"undecorated" => PeImportNameType::Undecorated,
|
||||
import_name_type => {
|
||||
sess.dcx().emit_err(errors::UnknownImportNameType {
|
||||
span: item.span(),
|
||||
import_name_type,
|
||||
});
|
||||
continue;
|
||||
}
|
||||
};
|
||||
import_name_type = Some((link_import_name_type, item.span()));
|
||||
}
|
||||
_ => {
|
||||
sess.dcx().emit_err(errors::UnexpectedLinkArg { span: item.span() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do this outside the above loop so we don't depend on modifiers coming after kinds
|
||||
let mut verbatim = None;
|
||||
if let Some((modifiers, span)) = modifiers {
|
||||
for modifier in modifiers.as_str().split(',') {
|
||||
let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
|
||||
Some(m) => (m, modifier.starts_with('+')),
|
||||
None => {
|
||||
sess.dcx().emit_err(errors::InvalidLinkModifier { span });
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
macro report_unstable_modifier($feature: ident) {
|
||||
if !features.$feature() {
|
||||
// FIXME: make this translatable
|
||||
#[expect(rustc::untranslatable_diagnostic)]
|
||||
feature_err(
|
||||
sess,
|
||||
sym::$feature,
|
||||
span,
|
||||
format!("linking modifier `{modifier}` is unstable"),
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
let assign_modifier = |dst: &mut Option<bool>| {
|
||||
if dst.is_some() {
|
||||
sess.dcx().emit_err(errors::MultipleModifiers { span, modifier });
|
||||
} else {
|
||||
*dst = Some(value);
|
||||
}
|
||||
};
|
||||
match (modifier, &mut kind) {
|
||||
("bundle", Some(NativeLibKind::Static { bundle, .. })) => {
|
||||
assign_modifier(bundle)
|
||||
}
|
||||
("bundle", _) => {
|
||||
sess.dcx().emit_err(errors::BundleNeedsStatic { span });
|
||||
}
|
||||
|
||||
("verbatim", _) => assign_modifier(&mut verbatim),
|
||||
|
||||
("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => {
|
||||
assign_modifier(whole_archive)
|
||||
}
|
||||
("whole-archive", _) => {
|
||||
sess.dcx().emit_err(errors::WholeArchiveNeedsStatic { span });
|
||||
}
|
||||
|
||||
("as-needed", Some(NativeLibKind::Dylib { as_needed }))
|
||||
| ("as-needed", Some(NativeLibKind::Framework { as_needed })) => {
|
||||
report_unstable_modifier!(native_link_modifiers_as_needed);
|
||||
assign_modifier(as_needed)
|
||||
}
|
||||
("as-needed", _) => {
|
||||
sess.dcx().emit_err(errors::AsNeededCompatibility { span });
|
||||
}
|
||||
|
||||
_ => {
|
||||
sess.dcx().emit_err(errors::UnknownLinkModifier { span, modifier });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((_, span)) = wasm_import_module {
|
||||
if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
|
||||
sess.dcx().emit_err(errors::IncompatibleWasmLink { span });
|
||||
}
|
||||
}
|
||||
|
||||
if wasm_import_module.is_some() {
|
||||
(name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
|
||||
}
|
||||
let Some((name, name_span)) = name else {
|
||||
sess.dcx().emit_err(errors::LinkRequiresName { span: m.span() });
|
||||
continue;
|
||||
};
|
||||
|
||||
// Do this outside of the loop so that `import_name_type` can be specified before `kind`.
|
||||
if let Some((_, span)) = import_name_type {
|
||||
if kind != Some(NativeLibKind::RawDylib) {
|
||||
sess.dcx().emit_err(errors::ImportNameTypeRaw { span });
|
||||
}
|
||||
}
|
||||
|
||||
let dll_imports = match kind {
|
||||
Some(NativeLibKind::RawDylib) => {
|
||||
if name.as_str().contains('\0') {
|
||||
sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span });
|
||||
}
|
||||
foreign_items
|
||||
.iter()
|
||||
.map(|&child_item| {
|
||||
self.build_dll_import(
|
||||
abi,
|
||||
import_name_type.map(|(import_name_type, _)| import_name_type),
|
||||
child_item,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
for attr in
|
||||
find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::Link(links, _) => links)
|
||||
.iter()
|
||||
.map(|v| v.iter())
|
||||
.flatten()
|
||||
{
|
||||
let dll_imports = match attr.kind {
|
||||
NativeLibKind::RawDylib => foreign_items
|
||||
.iter()
|
||||
.map(|&child_item| {
|
||||
self.build_dll_import(
|
||||
abi,
|
||||
attr.import_name_type.map(|(import_name_type, _)| import_name_type),
|
||||
child_item,
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
_ => {
|
||||
for &child_item in foreign_items {
|
||||
if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span)
|
||||
|
|
@ -508,15 +240,20 @@ impl<'tcx> Collector<'tcx> {
|
|||
}
|
||||
};
|
||||
|
||||
let kind = kind.unwrap_or(NativeLibKind::Unspecified);
|
||||
let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
|
||||
let filename = find_bundled_library(
|
||||
attr.name,
|
||||
attr.verbatim,
|
||||
attr.kind,
|
||||
attr.cfg.is_some(),
|
||||
self.tcx,
|
||||
);
|
||||
self.libs.push(NativeLib {
|
||||
name,
|
||||
name: attr.name,
|
||||
filename,
|
||||
kind,
|
||||
cfg,
|
||||
kind: attr.kind,
|
||||
cfg: attr.cfg.clone(),
|
||||
foreign_module: Some(def_id.to_def_id()),
|
||||
verbatim,
|
||||
verbatim: attr.verbatim,
|
||||
dll_imports,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
&Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => {
|
||||
self.check_sanitize(attr_span, on_set | off_set, span, target);
|
||||
},
|
||||
Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {
|
||||
self.check_link(hir_id, *attr_span, span, target)
|
||||
}
|
||||
Attribute::Parsed(
|
||||
AttributeKind::BodyStability { .. }
|
||||
| AttributeKind::ConstStabilityIndirect
|
||||
|
|
@ -305,7 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
[sym::rustc_has_incoherent_inherent_impls, ..] => {
|
||||
self.check_has_incoherent_inherent_impls(attr, span, target)
|
||||
}
|
||||
[sym::link, ..] => self.check_link(hir_id, attr, span, target),
|
||||
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
|
||||
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
|
||||
self.check_autodiff(hir_id, attr, span, target)
|
||||
|
|
@ -1324,7 +1326,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
|
||||
/// Checks if `#[link]` is applied to an item other than a foreign module.
|
||||
fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
|
||||
fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
|
||||
if target == Target::ForeignMod
|
||||
&& let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
|
||||
&& let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
|
||||
|
|
@ -1336,7 +1338,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
attr_span,
|
||||
errors::Link { span: (target != Target::ForeignMod).then_some(span) },
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -466,6 +466,7 @@ symbols! {
|
|||
arm,
|
||||
arm_target_feature,
|
||||
array,
|
||||
as_dash_needed: "as-needed",
|
||||
as_ptr,
|
||||
as_ref,
|
||||
as_str,
|
||||
|
|
@ -592,6 +593,7 @@ symbols! {
|
|||
btreeset_iter,
|
||||
built,
|
||||
builtin_syntax,
|
||||
bundle,
|
||||
c,
|
||||
c_dash_variadic,
|
||||
c_str,
|
||||
|
|
@ -817,6 +819,7 @@ symbols! {
|
|||
decl_macro,
|
||||
declare_lint_pass,
|
||||
decode,
|
||||
decorated,
|
||||
default_alloc_error_handler,
|
||||
default_field_values,
|
||||
default_fn,
|
||||
|
|
@ -1075,6 +1078,7 @@ symbols! {
|
|||
format_macro,
|
||||
format_placeholder,
|
||||
format_unsafe_arg,
|
||||
framework,
|
||||
freeze,
|
||||
freeze_impls,
|
||||
freg,
|
||||
|
|
@ -1295,6 +1299,7 @@ symbols! {
|
|||
link_arg_attribute,
|
||||
link_args,
|
||||
link_cfg,
|
||||
link_dash_arg: "link-arg",
|
||||
link_llvm_intrinsics,
|
||||
link_name,
|
||||
link_ordinal,
|
||||
|
|
@ -1528,6 +1533,7 @@ symbols! {
|
|||
noop_method_borrow,
|
||||
noop_method_clone,
|
||||
noop_method_deref,
|
||||
noprefix,
|
||||
noreturn,
|
||||
nostack,
|
||||
not,
|
||||
|
|
@ -1741,6 +1747,7 @@ symbols! {
|
|||
quote,
|
||||
range_inclusive_new,
|
||||
range_step,
|
||||
raw_dash_dylib: "raw-dylib",
|
||||
raw_dylib,
|
||||
raw_dylib_elf,
|
||||
raw_eq,
|
||||
|
|
@ -2277,6 +2284,7 @@ symbols! {
|
|||
unchecked_shl,
|
||||
unchecked_shr,
|
||||
unchecked_sub,
|
||||
undecorated,
|
||||
underscore_const_names,
|
||||
underscore_imports,
|
||||
underscore_lifetimes,
|
||||
|
|
@ -2365,6 +2373,7 @@ symbols! {
|
|||
vecdeque_iter,
|
||||
vecdeque_reserve,
|
||||
vector,
|
||||
verbatim,
|
||||
version,
|
||||
vfp2,
|
||||
vis,
|
||||
|
|
@ -2389,6 +2398,7 @@ symbols! {
|
|||
weak_odr,
|
||||
where_clause_attrs,
|
||||
while_let,
|
||||
whole_dash_archive: "whole-archive",
|
||||
width,
|
||||
windows,
|
||||
windows_subsystem,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue