From 03733ca65a09a9b54b2c2a674e4145b165bd1cab Mon Sep 17 00:00:00 2001 From: cynecx Date: Mon, 22 Nov 2021 13:14:54 +0100 Subject: [PATCH 1/5] `#[used(linker)]` attribute (https://github.com/dtolnay/linkme/issues/41) --- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 9 +++++ compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../src/middle/codegen_fn_attrs.rs | 2 + compiler/rustc_passes/src/dead.rs | 5 ++- compiler/rustc_span/src/symbol.rs | 3 ++ compiler/rustc_typeck/src/collect.rs | 37 ++++++++++++++++++- 8 files changed, 58 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index ba4589bd81025..ddc2b88191bd0 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -144,7 +144,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // TODO(antoyo): set link section. } - if attrs.flags.contains(CodegenFnAttrFlags::USED) { + if attrs.flags.contains(CodegenFnAttrFlags::USED) || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { self.add_used_global(global.to_rvalue()); } } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index d43c7c6065179..6707de933522b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -522,6 +522,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { } if attrs.flags.contains(CodegenFnAttrFlags::USED) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + // The semantics of #[used] in Rust only require the symbol to make it into the // object file. It is explicitly allowed for the linker to strip the symbol if it // is dead. As such, use llvm.compiler.used instead of llvm.used. @@ -530,6 +533,12 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // in some versions of the gold linker. self.add_compiler_used_global(g); } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED)); + + self.add_used_global(g); + } } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index bfe2459dc8dc1..d958a14afabb9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -533,6 +533,8 @@ declare_features! ( /// /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), + /// Allows using the `#[used(retain)]` attribute. + (active, used_with_arg, "1.60.0", None, None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3933746c319ec..739e545043842 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_mangle, Normal, template!(Word), WarnFollowing), - ungated!(used, Normal, template!(Word), WarnFollowing), + ungated!(used, Normal, template!(Word, List: "used"), WarnFollowing), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b054d21adaa13..54eb2dc9e2890 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -89,6 +89,8 @@ bitflags! { /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. const NO_COVERAGE = 1 << 15; + /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function. + const USED_LINKER = 1 << 16; } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e7e56711b33c5..dc3ce1afa3361 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; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 18627cd2c099d..4a1fd476b8c0a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -449,6 +449,7 @@ symbols! { compare_exchange_weak, compile_error, compile_error_macro, + compiler, compiler_builtins, compiler_fence, concat, @@ -815,6 +816,7 @@ symbols! { link_ordinal, link_section, linkage, + linker, lint_reasons, literal, load, @@ -1458,6 +1460,7 @@ symbols! { use_extern_macros, use_nested_groups, used, + used_with_arg, usize, v1, va_arg, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index cf519a9ab3274..4a3c477021cf4 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2849,7 +2849,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } else if attr.has_name(sym::used) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; + let inner = attr.meta_item_list(); + match inner.as_deref() { + Some([item]) if item.has_name(sym::linker) => { + if !tcx.features().used_with_arg { + feature_err( + &tcx.sess.parse_sess, + sym::used_with_arg, + attr.span, + "`#[used(linker)]` is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER; + } + Some([item]) if item.has_name(sym::compiler) => { + if !tcx.features().used_with_arg { + feature_err( + &tcx.sess.parse_sess, + sym::used_with_arg, + attr.span, + "`#[used(compiler)]` is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; + } + Some(_) => { + tcx.sess + .struct_span_err( + attr.span, + "expected `used`, `used(compiler)` or `used(linker)`", + ) + .emit(); + } + None => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED, + } } else if attr.has_name(sym::cmse_nonsecure_entry) { if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) { struct_span_err!( From e075586d4fd428374a788eecc391e23ec4a17b46 Mon Sep 17 00:00:00 2001 From: cynecx Date: Mon, 7 Feb 2022 01:21:23 +0100 Subject: [PATCH 2/5] add tests and fix comments --- compiler/rustc_feature/src/active.rs | 4 ++-- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- src/test/codegen/used_with_arg.rs | 12 ++++++++++++ .../feature-gate-used_with_arg.rs | 7 +++++++ .../feature-gate-used_with_arg.stderr | 19 +++++++++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/used_with_arg.rs create mode 100644 src/test/ui/feature-gates/feature-gate-used_with_arg.rs create mode 100644 src/test/ui/feature-gates/feature-gate-used_with_arg.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index d958a14afabb9..0908e9d1ef905 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -533,8 +533,8 @@ declare_features! ( /// /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), - /// Allows using the `#[used(retain)]` attribute. - (active, used_with_arg, "1.60.0", None, None), + /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. + (active, used_with_arg, "1.60.0", Some(00000), None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 739e545043842..13b482cb469bd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_mangle, Normal, template!(Word), WarnFollowing), - ungated!(used, Normal, template!(Word, List: "used"), WarnFollowing), + ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), diff --git a/src/test/codegen/used_with_arg.rs b/src/test/codegen/used_with_arg.rs new file mode 100644 index 0000000000000..cd759b167c0df --- /dev/null +++ b/src/test/codegen/used_with_arg.rs @@ -0,0 +1,12 @@ +// compile-flags: -O + +#![crate_type = "lib"] +#![feature(used_with_arg)] + +// CHECK: @llvm.used = appending global [1 x i8*] +#[used(linker)] +static mut USED_LINKER: [usize; 1] = [0]; + +// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*] +#[used(compiler)] +static mut USED_COMPILER: [usize; 1] = [0]; diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.rs b/src/test/ui/feature-gates/feature-gate-used_with_arg.rs new file mode 100644 index 0000000000000..1c8f01bdef116 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.rs @@ -0,0 +1,7 @@ +#[used(linker)] //~ ERROR `#[used(linker)]` is currently unstable +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `#[used(compiler)]` is currently unstable +static mut USED_COMPILER: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr new file mode 100644 index 0000000000000..aaf4ceaf79537 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr @@ -0,0 +1,19 @@ +error[E0658]: `#[used(linker)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:1:1 + | +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error[E0658]: `#[used(compiler)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:4:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From 438826fd1a9a119d00992ede948cdd479431ecbb Mon Sep 17 00:00:00 2001 From: cynecx Date: Tue, 8 Feb 2022 23:51:17 +0100 Subject: [PATCH 3/5] 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 + From 933963e10ae8837965f44b7e9748ff135f6c57a5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Feb 2022 10:59:33 +0100 Subject: [PATCH 4/5] Add tracking issue --- compiler/rustc_feature/src/active.rs | 2 +- src/test/ui/feature-gates/feature-gate-used_with_arg.stderr | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 0908e9d1ef905..c652e54ffe7b8 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -534,7 +534,7 @@ declare_features! ( /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. - (active, used_with_arg, "1.60.0", Some(00000), None), + (active, used_with_arg, "1.60.0", Some(93798), None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr index aaf4ceaf79537..d115bf4e365a7 100644 --- a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr @@ -4,6 +4,7 @@ error[E0658]: `#[used(linker)]` is currently unstable LL | #[used(linker)] | ^^^^^^^^^^^^^^^ | + = note: see issue #93798 for more information = help: add `#![feature(used_with_arg)]` to the crate attributes to enable error[E0658]: `#[used(compiler)]` is currently unstable @@ -12,6 +13,7 @@ error[E0658]: `#[used(compiler)]` is currently unstable LL | #[used(compiler)] | ^^^^^^^^^^^^^^^^^ | + = note: see issue #93798 for more information = help: add `#![feature(used_with_arg)]` to the crate attributes to enable error: aborting due to 2 previous errors From 170593313a6ac2206107ec52a0d3bb9cc873a97c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Feb 2022 11:00:39 +0100 Subject: [PATCH 5/5] Move tests into attributes directory to pacify tidy --- src/test/ui/{ => attributes}/used_with_arg.rs | 0 src/test/ui/{ => attributes}/used_with_arg.stderr | 0 src/test/ui/{ => attributes}/used_with_multi_args.rs | 0 src/test/ui/{ => attributes}/used_with_multi_args.stderr | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => attributes}/used_with_arg.rs (100%) rename src/test/ui/{ => attributes}/used_with_arg.stderr (100%) rename src/test/ui/{ => attributes}/used_with_multi_args.rs (100%) rename src/test/ui/{ => attributes}/used_with_multi_args.stderr (100%) diff --git a/src/test/ui/used_with_arg.rs b/src/test/ui/attributes/used_with_arg.rs similarity index 100% rename from src/test/ui/used_with_arg.rs rename to src/test/ui/attributes/used_with_arg.rs diff --git a/src/test/ui/used_with_arg.stderr b/src/test/ui/attributes/used_with_arg.stderr similarity index 100% rename from src/test/ui/used_with_arg.stderr rename to src/test/ui/attributes/used_with_arg.stderr diff --git a/src/test/ui/used_with_multi_args.rs b/src/test/ui/attributes/used_with_multi_args.rs similarity index 100% rename from src/test/ui/used_with_multi_args.rs rename to src/test/ui/attributes/used_with_multi_args.rs diff --git a/src/test/ui/used_with_multi_args.stderr b/src/test/ui/attributes/used_with_multi_args.stderr similarity index 100% rename from src/test/ui/used_with_multi_args.stderr rename to src/test/ui/attributes/used_with_multi_args.stderr