From 438826fd1a9a119d00992ede948cdd479431ecbb Mon Sep 17 00:00:00 2001 From: cynecx Date: Tue, 8 Feb 2022 23:51:17 +0100 Subject: [PATCH] add more tests and make used(linker/compiler) mutually exclusive --- compiler/rustc_passes/src/check_attr.rs | 34 +++++++++++++++++++++++++ compiler/rustc_typeck/src/collect.rs | 1 + src/test/codegen/used_with_arg.rs | 6 ++--- src/test/ui/used_with_arg.rs | 19 ++++++++++++++ src/test/ui/used_with_arg.stderr | 18 +++++++++++++ src/test/ui/used_with_multi_args.rs | 6 +++++ src/test/ui/used_with_multi_args.stderr | 8 ++++++ 7 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/used_with_arg.rs create mode 100644 src/test/ui/used_with_arg.stderr create mode 100644 src/test/ui/used_with_multi_args.rs create mode 100644 src/test/ui/used_with_multi_args.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ca511f7b814be..479a08e43c01a 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_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 4a3c477021cf4..2a280ff97e96d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! "Collection" is the process of determining the type and other external //! details of each item in Rust. Collection is specifically concerned //! with *inter-procedural* things -- for example, for a function diff --git a/src/test/codegen/used_with_arg.rs b/src/test/codegen/used_with_arg.rs index cd759b167c0df..5bff50a40d4e8 100644 --- a/src/test/codegen/used_with_arg.rs +++ b/src/test/codegen/used_with_arg.rs @@ -1,12 +1,10 @@ -// compile-flags: -O - #![crate_type = "lib"] #![feature(used_with_arg)] -// CHECK: @llvm.used = appending global [1 x i8*] +// CHECK: @llvm.used = appending global [1 x i8*]{{.*}}USED_LINKER #[used(linker)] static mut USED_LINKER: [usize; 1] = [0]; -// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*] +// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*]{{.*}}USED_COMPILER #[used(compiler)] static mut USED_COMPILER: [usize; 1] = [0]; diff --git a/src/test/ui/used_with_arg.rs b/src/test/ui/used_with_arg.rs new file mode 100644 index 0000000000000..ad80ff53f0ef0 --- /dev/null +++ b/src/test/ui/used_with_arg.rs @@ -0,0 +1,19 @@ +#![feature(used_with_arg)] + +#[used(linker)] +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] +static mut USED_COMPILER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +static mut USED_COMPILER_LINKER2: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +#[used(compiler)] +#[used(linker)] +static mut USED_COMPILER_LINKER3: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/used_with_arg.stderr b/src/test/ui/used_with_arg.stderr new file mode 100644 index 0000000000000..440e5c4a5a020 --- /dev/null +++ b/src/test/ui/used_with_arg.stderr @@ -0,0 +1,18 @@ +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:9:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:13:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/used_with_multi_args.rs b/src/test/ui/used_with_multi_args.rs new file mode 100644 index 0000000000000..2e17fcfd7a493 --- /dev/null +++ b/src/test/ui/used_with_multi_args.rs @@ -0,0 +1,6 @@ +#![feature(used_with_arg)] + +#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)` +static mut USED_COMPILER_LINKER: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/used_with_multi_args.stderr b/src/test/ui/used_with_multi_args.stderr new file mode 100644 index 0000000000000..c93aafcfc7cce --- /dev/null +++ b/src/test/ui/used_with_multi_args.stderr @@ -0,0 +1,8 @@ +error: expected `used`, `used(compiler)` or `used(linker)` + --> $DIR/used_with_multi_args.rs:3:1 + | +LL | #[used(compiler, linker)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error +