More c-variadic errors as semantic restrictions.
This commit is contained in:
parent
3a57a2cca4
commit
35e9e097e7
7 changed files with 322 additions and 86 deletions
|
@ -1426,7 +1426,13 @@ impl<'a> LoweringContext<'a> {
|
|||
}
|
||||
}
|
||||
TyKind::Mac(_) => bug!("`TyKind::Mac` should have been expanded by now"),
|
||||
TyKind::CVarArgs => bug!("`TyKind::CVarArgs` should have been handled elsewhere"),
|
||||
TyKind::CVarArgs => {
|
||||
self.sess.delay_span_bug(
|
||||
t.span,
|
||||
"`TyKind::CVarArgs` should have been handled elsewhere",
|
||||
);
|
||||
hir::TyKind::Err
|
||||
}
|
||||
};
|
||||
|
||||
hir::Ty {
|
||||
|
|
|
@ -1885,58 +1885,23 @@ impl<'a> Parser<'a> {
|
|||
|
||||
/// Parses the parameter list of a function, including the `(` and `)` delimiters.
|
||||
fn parse_fn_params(&mut self, mut cfg: ParamCfg) -> PResult<'a, Vec<Param>> {
|
||||
let sp = self.token.span;
|
||||
let is_trait_item = cfg.is_self_allowed;
|
||||
let mut c_variadic = false;
|
||||
// Parse the arguments, starting out with `self` being possibly allowed...
|
||||
let (params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item);
|
||||
let (mut params, _) = self.parse_paren_comma_seq(|p| {
|
||||
let param = p.parse_param_general(&cfg, is_trait_item).or_else(|mut e| {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
Ok(dummy_arg(Ident::new(kw::Invalid, lo.to(p.prev_span))))
|
||||
});
|
||||
// ...now that we've parsed the first argument, `self` is no longer allowed.
|
||||
cfg.is_self_allowed = false;
|
||||
|
||||
match param {
|
||||
Ok(param) => Ok(
|
||||
if let TyKind::CVarArgs = param.ty.kind {
|
||||
c_variadic = true;
|
||||
if p.token != token::CloseDelim(token::Paren) {
|
||||
p.span_err(
|
||||
p.token.span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
// FIXME(eddyb) this should probably still push `CVarArgs`.
|
||||
// Maybe AST validation/HIR lowering should emit the above error?
|
||||
None
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
} else {
|
||||
Some(param)
|
||||
}
|
||||
),
|
||||
Err(mut e) => {
|
||||
e.emit();
|
||||
let lo = p.prev_span;
|
||||
// Skip every token until next possible arg or end.
|
||||
p.eat_to_tokens(&[&token::Comma, &token::CloseDelim(token::Paren)]);
|
||||
// Create a placeholder argument for proper arg count (issue #34264).
|
||||
let span = lo.to(p.prev_span);
|
||||
Ok(Some(dummy_arg(Ident::new(kw::Invalid, span))))
|
||||
}
|
||||
}
|
||||
param
|
||||
})?;
|
||||
|
||||
let mut params: Vec<_> = params.into_iter().filter_map(|x| x).collect();
|
||||
|
||||
// Replace duplicated recovered params with `_` pattern to avoid unnecessary errors.
|
||||
self.deduplicate_recovered_params_names(&mut params);
|
||||
|
||||
if c_variadic && params.len() <= 1 {
|
||||
self.span_err(
|
||||
sp,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
}
|
||||
|
||||
Ok(params)
|
||||
}
|
||||
|
||||
|
|
|
@ -250,6 +250,26 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn check_fn_decl(&self, fn_decl: &FnDecl) {
|
||||
match &*fn_decl.inputs {
|
||||
[Param { ty, span, .. }] => if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler()
|
||||
.span_err(
|
||||
*span,
|
||||
"C-variadic function must be declared with at least one named argument",
|
||||
);
|
||||
},
|
||||
[ps @ .., _] => for Param { ty, span, .. } in ps {
|
||||
if let TyKind::CVarArgs = ty.kind {
|
||||
self.err_handler()
|
||||
.span_err(
|
||||
*span,
|
||||
"`...` must be the last argument of a C-variadic function",
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
fn_decl
|
||||
.inputs
|
||||
.iter()
|
||||
|
@ -265,8 +285,7 @@ impl<'a> AstValidator<'a> {
|
|||
)
|
||||
.span_label(attr.span, "doc comments are not allowed here")
|
||||
.emit();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
self.err_handler().span_err(attr.span, "allow, cfg, cfg_attr, deny, \
|
||||
forbid, and warn are the only allowed built-in attributes in function parameters")
|
||||
});
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-no-fixed-args.rs:2:11
|
||||
--> $DIR/variadic-ffi-no-fixed-args.rs:2:12
|
||||
|
|
||||
LL | fn foo(...);
|
||||
| ^
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -2,25 +2,75 @@
|
|||
|
||||
fn main() {}
|
||||
|
||||
fn f1(x: isize, ...) {}
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn f1_1(x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
|
||||
extern "C" fn f2(x: isize, ...) {}
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn f1_2(...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
|
||||
extern fn f3(x: isize, ...) {}
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
extern "C" fn f2_1(x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
|
||||
extern "C" fn f2_2(...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
|
||||
extern "C" fn f2_3(..., x: isize) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
extern fn f3_1(x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
|
||||
extern fn f3_2(...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
|
||||
extern fn f3_3(..., x: isize) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
|
||||
extern {
|
||||
fn e_f1(...);
|
||||
//~^ ERROR C-variadic function must be declared with at least one named argument
|
||||
fn e_f2(..., x: isize);
|
||||
//~^ ERROR `...` must be the last argument of a C-variadic function
|
||||
}
|
||||
|
||||
struct X;
|
||||
|
||||
impl X {
|
||||
fn f4(x: isize, ...) {}
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn i_f1(x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn i_f2(...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
fn i_f3(..., x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
fn i_f4(..., x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
}
|
||||
|
||||
trait T {
|
||||
fn f5(x: isize, ...) {}
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn f6(x: isize, ...);
|
||||
//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn t_f1(x: isize, ...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn t_f2(x: isize, ...);
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
fn t_f3(...) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
fn t_f4(...);
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR C-variadic function must be declared with at least one named argument
|
||||
fn t_f5(..., x: isize) {}
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
fn t_f6(..., x: isize);
|
||||
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
//~| ERROR `...` must be the last argument of a C-variadic function
|
||||
}
|
||||
|
|
|
@ -1,38 +1,206 @@
|
|||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:17
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:5:19
|
||||
|
|
||||
LL | fn f1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
LL | fn f1_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||
|
|
||||
LL | fn f1_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:28
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:8:9
|
||||
|
|
||||
LL | extern "C" fn f2(x: isize, ...) {}
|
||||
LL | fn f1_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:12:30
|
||||
|
|
||||
LL | extern "C" fn f2_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
|
|
||||
LL | extern "C" fn f2_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:15:20
|
||||
|
|
||||
LL | extern "C" fn f2_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||
|
|
||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:19:20
|
||||
|
|
||||
LL | extern "C" fn f2_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
|
||||
|
|
||||
LL | extern fn f3_1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||
|
|
||||
LL | extern fn f3_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:26:16
|
||||
|
|
||||
LL | extern fn f3_2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||
|
|
||||
LL | extern fn f3_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:30:16
|
||||
|
|
||||
LL | extern fn f3_3(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:35:13
|
||||
|
|
||||
LL | fn e_f1(...);
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:37:13
|
||||
|
|
||||
LL | fn e_f2(..., x: isize);
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:44:23
|
||||
|
|
||||
LL | fn i_f1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:46:13
|
||||
|
|
||||
LL | fn i_f2(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:13
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:49:28
|
||||
|
|
||||
LL | fn i_f3(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:53:28
|
||||
|
|
||||
LL | fn i_f4(..., x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:11:24
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
|
||||
|
|
||||
LL | extern fn f3(x: isize, ...) {}
|
||||
| ^^^^
|
||||
LL | fn t_f1(x: isize, ...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:17:21
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
|
||||
|
|
||||
LL | fn f4(x: isize, ...) {}
|
||||
| ^^^^
|
||||
LL | fn t_f2(x: isize, ...);
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||
|
|
||||
LL | fn t_f3(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:22:21
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:64:13
|
||||
|
|
||||
LL | fn f5(x: isize, ...) {}
|
||||
| ^^^^
|
||||
LL | fn t_f3(...) {}
|
||||
| ^^^^
|
||||
|
||||
error: C-variadic function must be declared with at least one named argument
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||
|
|
||||
LL | fn t_f4(...);
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:21
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:67:13
|
||||
|
|
||||
LL | fn f6(x: isize, ...);
|
||||
| ^^^^
|
||||
LL | fn t_f4(...);
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||
|
|
||||
LL | fn t_f5(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:70:13
|
||||
|
|
||||
LL | fn t_f5(..., x: isize) {}
|
||||
| ^^^^
|
||||
|
||||
error: `...` must be the last argument of a C-variadic function
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||
|
|
||||
LL | fn t_f6(..., x: isize);
|
||||
| ^^^^
|
||||
|
||||
error: only foreign or `unsafe extern "C" functions may be C-variadic
|
||||
--> $DIR/variadic-ffi-semantic-restrictions.rs:73:13
|
||||
|
|
||||
LL | fn t_f6(..., x: isize);
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to 34 previous errors
|
||||
|
||||
|
|
|
@ -3,23 +3,51 @@
|
|||
fn main() {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
fn f1(x: isize, ...) {}
|
||||
fn f1_1(x: isize, ...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern "C" fn f2(x: isize, ...) {}
|
||||
fn f1_2(...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern fn f3(x: isize, ...) {}
|
||||
extern "C" fn f2_1(x: isize, ...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern "C" fn f2_2(...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern "C" fn f2_3(..., x: isize) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern fn f3_1(x: isize, ...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern fn f3_2(...) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern fn f3_3(..., x: isize) {}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
extern {
|
||||
fn e_f1(...);
|
||||
fn e_f2(..., x: isize);
|
||||
}
|
||||
|
||||
struct X;
|
||||
|
||||
#[cfg(FALSE)]
|
||||
impl X {
|
||||
fn f4(x: isize, ...) {}
|
||||
fn i_f1(x: isize, ...) {}
|
||||
fn i_f2(...) {}
|
||||
fn i_f3(..., x: isize, ...) {}
|
||||
fn i_f4(..., x: isize, ...) {}
|
||||
}
|
||||
|
||||
#[cfg(FALSE)]
|
||||
trait T {
|
||||
fn f5(x: isize, ...) {}
|
||||
fn f6(x: isize, ...);
|
||||
fn t_f1(x: isize, ...) {}
|
||||
fn t_f2(x: isize, ...);
|
||||
fn t_f3(...) {}
|
||||
fn t_f4(...);
|
||||
fn t_f5(..., x: isize) {}
|
||||
fn t_f6(..., x: isize);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue