Skip to content

Commit

Permalink
Auto merge of #79388 - tmiasko:naked-def-only, r=lcnr
Browse files Browse the repository at this point in the history
Validate that `#[naked]` is applied to a function definition
  • Loading branch information
bors committed Nov 25, 2020
2 parents ec039bd + 75e00e8 commit 773ddba
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 14 deletions.
23 changes: 22 additions & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ impl CheckAttrVisitor<'tcx> {
self.check_allow_internal_unstable(&attr, span, target, &attrs)
} else if self.tcx.sess.check_name(attr, sym::rustc_allow_const_fn_unstable) {
self.check_rustc_allow_const_fn_unstable(hir_id, &attr, span, target)
} else if self.tcx.sess.check_name(attr, sym::naked) {
self.check_naked(attr, span, target)
} else {
// lint-only checks
if self.tcx.sess.check_name(attr, sym::cold) {
Expand Down Expand Up @@ -162,6 +164,25 @@ impl CheckAttrVisitor<'tcx> {
}
}

/// Checks if `#[naked]` is applied to a function definition.
fn check_naked(&self, attr: &Attribute, span: &Span, target: Target) -> bool {
match target {
Target::Fn
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
_ => {
self.tcx
.sess
.struct_span_err(
attr.span,
"attribute should be applied to a function definition",
)
.span_label(*span, "not a function definition")
.emit();
false
}
}
}

/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
fn check_track_caller(
&self,
Expand All @@ -171,7 +192,7 @@ impl CheckAttrVisitor<'tcx> {
target: Target,
) -> bool {
match target {
_ if self.tcx.sess.contains_name(attrs, sym::naked) => {
_ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
struct_span_err!(
self.tcx.sess,
*attr_span,
Expand Down
51 changes: 51 additions & 0 deletions src/test/ui/asm/naked-invalid-attr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Checks that #[naked] attribute can be placed on function definitions only.
//
// ignore-wasm32 asm unsupported
#![feature(asm)]
#![feature(naked_functions)]
#![naked] //~ ERROR should be applied to a function definition

extern "C" {
#[naked] //~ ERROR should be applied to a function definition
fn f();
}

#[naked] //~ ERROR should be applied to a function definition
#[repr(C)]
struct S {
a: u32,
b: u32,
}

trait Invoke {
#[naked] //~ ERROR should be applied to a function definition
extern "C" fn invoke(&self);
}

impl Invoke for S {
#[naked]
extern "C" fn invoke(&self) {
unsafe { asm!("", options(noreturn)) }
}
}

#[naked]
extern "C" fn ok() {
unsafe { asm!("", options(noreturn)) }
}

impl S {
#[naked]
extern "C" fn g() {
unsafe { asm!("", options(noreturn)) }
}

#[naked]
extern "C" fn h(&self) {
unsafe { asm!("", options(noreturn)) }
}
}

fn main() {
#[naked] || {}; //~ ERROR should be applied to a function definition
}
42 changes: 42 additions & 0 deletions src/test/ui/asm/naked-invalid-attr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:9:5
|
LL | #[naked]
| ^^^^^^^^
LL | fn f();
| ------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:13:1
|
LL | #[naked]
| ^^^^^^^^
LL | #[repr(C)]
LL | / struct S {
LL | | a: u32,
LL | | b: u32,
LL | | }
| |_- not a function definition

error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:50:5
|
LL | #[naked] || {};
| ^^^^^^^^ ----- not a function definition

error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:21:5
|
LL | #[naked]
| ^^^^^^^^
LL | extern "C" fn invoke(&self);
| ---------------------------- not a function definition

error: attribute should be applied to a function definition
--> $DIR/naked-invalid-attr.rs:6:1
|
LL | #![naked]
| ^^^^^^^^^

error: aborting due to 5 previous errors

6 changes: 0 additions & 6 deletions src/test/ui/rfc-2091-track-caller/error-with-naked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,4 @@ impl S {
fn g() {}
}

extern "Rust" {
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
#[naked]
fn h();
}

fn main() {}
8 changes: 1 addition & 7 deletions src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,12 @@ error[E0736]: cannot use `#[track_caller]` with `#[naked]`
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error[E0736]: cannot use `#[track_caller]` with `#[naked]`
--> $DIR/error-with-naked.rs:16:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error[E0736]: cannot use `#[track_caller]` with `#[naked]`
--> $DIR/error-with-naked.rs:10:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0736`.

0 comments on commit 773ddba

Please sign in to comment.