More c-variadic errors as semantic restrictions.

This commit is contained in:
Mazdak Farrokhzad 2019-12-02 03:16:12 +01:00
parent 3a57a2cca4
commit 35e9e097e7
7 changed files with 322 additions and 86 deletions

View file

@ -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 {

View file

@ -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)
}

View file

@ -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")
});

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

@ -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);
}