about summary refs log tree commit diff
path: root/compiler/rustc_passes
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-02-09 23:29:56 +0100
committerGitHub <noreply@github.com>2022-02-09 23:29:56 +0100
commit3f4aaf4f2e9fd49736e660475f446619e8734e09 (patch)
treeee6ff4aed191d3baab16454560fe605299af423c /compiler/rustc_passes
parent9634559599537e334cbfa854446d048e6ebe5ee9 (diff)
parent170593313a6ac2206107ec52a0d3bb9cc873a97c (diff)
downloadrust-3f4aaf4f2e9fd49736e660475f446619e8734e09.tar.gz
rust-3f4aaf4f2e9fd49736e660475f446619e8734e09.zip
Rollup merge of #91504 - cynecx:used_retain, r=nikic
`#[used(linker)]` attribute

See https://github.com/dtolnay/linkme/issues/41#issuecomment-927255631.
Diffstat (limited to 'compiler/rustc_passes')
-rw-r--r--compiler/rustc_passes/src/check_attr.rs34
-rw-r--r--compiler/rustc_passes/src/dead.rs5
2 files changed, 38 insertions, 1 deletions
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index ca511f7b814..479a08e43c0 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1741,12 +1741,46 @@ impl CheckAttrVisitor<'_> {
     }
 
     fn check_used(&self, attrs: &[Attribute], target: Target) {
+        let mut used_linker_span = None;
+        let mut used_compiler_span = None;
         for attr in attrs {
             if attr.has_name(sym::used) && target != Target::Static {
                 self.tcx
                     .sess
                     .span_err(attr.span, "attribute must be applied to a `static` variable");
             }
+            let inner = attr.meta_item_list();
+            match inner.as_deref() {
+                Some([item]) if item.has_name(sym::linker) => {
+                    if used_linker_span.is_none() {
+                        used_linker_span = Some(attr.span);
+                    }
+                }
+                Some([item]) if item.has_name(sym::compiler) => {
+                    if used_compiler_span.is_none() {
+                        used_compiler_span = Some(attr.span);
+                    }
+                }
+                Some(_) => {
+                    // This error case is handled in rustc_typeck::collect.
+                }
+                None => {
+                    // Default case (compiler) when arg isn't defined.
+                    if used_compiler_span.is_none() {
+                        used_compiler_span = Some(attr.span);
+                    }
+                }
+            }
+        }
+        if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) {
+            let spans = vec![linker_span, compiler_span];
+            self.tcx
+                .sess
+                .struct_span_err(
+                    spans,
+                    "`used(compiler)` and `used(linker)` can't be used together",
+                )
+                .emit();
         }
     }
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index e7e56711b33..dc3ce1afa33 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -466,7 +466,10 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool {
 
     // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
     // forcefully, e.g., for placing it in a specific section.
-    if cg_attrs.contains_extern_indicator() || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) {
+    if cg_attrs.contains_extern_indicator()
+        || cg_attrs.flags.contains(CodegenFnAttrFlags::USED)
+        || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
+    {
         return true;
     }