Skip to content

Commit 05b7cc8

Browse files
Move FFI attribute validation to check_attr
1 parent 3984bc5 commit 05b7cc8

File tree

4 files changed

+78
-47
lines changed

4 files changed

+78
-47
lines changed

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

+3-47
Original file line numberDiff line numberDiff line change
@@ -85,55 +85,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
8585
} else if attr.has_name(sym::rustc_allocator) {
8686
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
8787
} else if attr.has_name(sym::ffi_returns_twice) {
88-
if tcx.is_foreign_item(did) {
89-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
90-
} else {
91-
// `#[ffi_returns_twice]` is only allowed `extern fn`s.
92-
struct_span_err!(
93-
tcx.sess,
94-
attr.span,
95-
E0724,
96-
"`#[ffi_returns_twice]` may only be used on foreign functions"
97-
)
98-
.emit();
99-
}
88+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
10089
} else if attr.has_name(sym::ffi_pure) {
101-
if tcx.is_foreign_item(did) {
102-
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
103-
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
104-
struct_span_err!(
105-
tcx.sess,
106-
attr.span,
107-
E0757,
108-
"`#[ffi_const]` function cannot be `#[ffi_pure]`"
109-
)
110-
.emit();
111-
} else {
112-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
113-
}
114-
} else {
115-
// `#[ffi_pure]` is only allowed on foreign functions
116-
struct_span_err!(
117-
tcx.sess,
118-
attr.span,
119-
E0755,
120-
"`#[ffi_pure]` may only be used on foreign functions"
121-
)
122-
.emit();
123-
}
90+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
12491
} else if attr.has_name(sym::ffi_const) {
125-
if tcx.is_foreign_item(did) {
126-
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
127-
} else {
128-
// `#[ffi_const]` is only allowed on foreign functions
129-
struct_span_err!(
130-
tcx.sess,
131-
attr.span,
132-
E0756,
133-
"`#[ffi_const]` may only be used on foreign functions"
134-
)
135-
.emit();
136-
}
92+
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
13793
} else if attr.has_name(sym::rustc_nounwind) {
13894
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
13995
} else if attr.has_name(sym::rustc_reallocator) {

compiler/rustc_error_messages/locales/en-US/passes.ftl

+12
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,18 @@ passes_has_incoherent_inherent_impl =
182182
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
183183
.label = only adts, extern types and traits are supported
184184
185+
passes_both_ffi_const_and_pure =
186+
`#[ffi_const]` function cannot be `#[ffi_pure]`
187+
188+
passes_ffi_pure_invalid_target =
189+
`#[ffi_pure]` may only be used on foreign functions
190+
191+
passes_ffi_const_invalid_target =
192+
`#[ffi_const]` may only be used on foreign functions
193+
194+
passes_ffi_returns_twice_invalid_target =
195+
`#[ffi_returns_twice]` may only be used on foreign functions
196+
185197
passes_must_use_async =
186198
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
187199
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`

compiler/rustc_passes/src/check_attr.rs

+35
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ impl CheckAttrVisitor<'_> {
150150
sym::rustc_has_incoherent_inherent_impls => {
151151
self.check_has_incoherent_inherent_impls(&attr, span, target)
152152
}
153+
sym::ffi_pure => self.check_ffi_pure(hir_id, attr.span, attrs),
154+
sym::ffi_const => self.check_ffi_const(hir_id, attr.span),
155+
sym::ffi_returns_twice => self.check_ffi_returns_twice(hir_id, attr.span),
153156
sym::rustc_const_unstable
154157
| sym::rustc_const_stable
155158
| sym::unstable
@@ -1171,6 +1174,38 @@ impl CheckAttrVisitor<'_> {
11711174
}
11721175
}
11731176

1177+
fn check_ffi_pure(&self, hir_id: HirId, attr_span: Span, attrs: &[Attribute]) -> bool {
1178+
if !self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
1179+
self.tcx.sess.emit_err(errors::FfiPureInvalidTarget { attr_span });
1180+
return false;
1181+
}
1182+
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
1183+
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
1184+
self.tcx.sess.emit_err(errors::BothFfiConstAndPure { attr_span });
1185+
false
1186+
} else {
1187+
true
1188+
}
1189+
}
1190+
1191+
fn check_ffi_const(&self, hir_id: HirId, attr_span: Span) -> bool {
1192+
if self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
1193+
true
1194+
} else {
1195+
self.tcx.sess.emit_err(errors::FfiConstInvalidTarget { attr_span });
1196+
false
1197+
}
1198+
}
1199+
1200+
fn check_ffi_returns_twice(&self, hir_id: HirId, attr_span: Span) -> bool {
1201+
if self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
1202+
true
1203+
} else {
1204+
self.tcx.sess.emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
1205+
false
1206+
}
1207+
}
1208+
11741209
/// Warns against some misuses of `#[must_use]`
11751210
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
11761211
if !matches!(

compiler/rustc_passes/src/errors.rs

+28
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,34 @@ pub struct HasIncoherentInherentImpl {
347347
pub span: Span,
348348
}
349349

350+
#[derive(Diagnostic)]
351+
#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
352+
pub struct BothFfiConstAndPure {
353+
#[primary_span]
354+
pub attr_span: Span,
355+
}
356+
357+
#[derive(Diagnostic)]
358+
#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
359+
pub struct FfiPureInvalidTarget {
360+
#[primary_span]
361+
pub attr_span: Span,
362+
}
363+
364+
#[derive(Diagnostic)]
365+
#[diag(passes_ffi_const_invalid_target, code = "E0756")]
366+
pub struct FfiConstInvalidTarget {
367+
#[primary_span]
368+
pub attr_span: Span,
369+
}
370+
371+
#[derive(Diagnostic)]
372+
#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
373+
pub struct FfiReturnsTwiceInvalidTarget {
374+
#[primary_span]
375+
pub attr_span: Span,
376+
}
377+
350378
#[derive(LintDiagnostic)]
351379
#[diag(passes_must_use_async)]
352380
pub struct MustUseAsync {

0 commit comments

Comments
 (0)