]> git.lizzy.rs Git - rust.git/commitdiff
More c-variadic errors as semantic restrictions.
authorMazdak Farrokhzad <twingoow@gmail.com>
Mon, 2 Dec 2019 02:16:12 +0000 (03:16 +0100)
committerMazdak Farrokhzad <twingoow@gmail.com>
Thu, 12 Dec 2019 17:01:33 +0000 (18:01 +0100)
src/librustc/hir/lowering.rs
src/librustc_parse/parser/item.rs
src/librustc_passes/ast_validation.rs
src/test/ui/c-variadic/variadic-ffi-no-fixed-args.stderr
src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
src/test/ui/parser/variadic-ffi-syntactic-pass.rs

index e2c99f456e988dacfb93f221ebdda3dc354a34d6..58225e87f2682bb80f42487bd01e4e5aeda28633 100644 (file)
@@ -1426,7 +1426,13 @@ fn lower_ty_direct(&mut self, t: &Ty, mut itctx: ImplTraitContext<'_>) -> hir::T
                 }
             }
             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 {
index d4b62e8ebba6bcbd2f50d9723486f41e2b3eecbb..a7c98886622807a30d5722d168d0237879b32b6b 100644 (file)
@@ -1885,58 +1885,23 @@ pub(super) fn parse_fn_decl(
 
     /// 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)
     }
 
index 884af188ed64ccce7264eef60d1818a757c3f73b..c75bd996e10c1cfea867fd1dd831dfef9f22635f 100644 (file)
@@ -250,6 +250,26 @@ fn check_late_bound_lifetime_defs(&self, params: &[GenericParam]) {
     }
 
     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 @@ fn check_fn_decl(&self, fn_decl: &FnDecl) {
                 )
                 .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")
             });
index cb6060525fc0d17a6d9bb82dc0843912b3e70c51..7af38c88f4334c6eb4c2f22f774bf5fbdbaf0d64 100644 (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
 
index 57086bca2f42868aaa3556692c3c07bfed2f7440..aa85f6d6b522b25566f6c152d48b062ad210e54f 100644 (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
 }
index 69244d92ee3920cc8842069769a63826dc452d6f..21992a29670c9bcfd33b2950f471ded48e26d0aa 100644 (file)
 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:9
+   |
+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:8:28
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:23:26
    |
-LL | extern "C" fn f2(x: isize, ...) {}
+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:11:24
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:53:13
    |
-LL | extern fn f3(x: isize, ...) {}
-   |                        ^^^^
+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:17:21
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:60:23
    |
-LL |     fn f4(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:22:21
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:62:23
+   |
+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:64:13
+   |
+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:67:13
+   |
+LL |     fn t_f4(...);
+   |             ^^^^
+
+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 f5(x: isize, ...) {}
-   |                     ^^^^
+LL |     fn t_f6(..., x: isize);
+   |             ^^^^
 
 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:73:13
    |
-LL |     fn f6(x: isize, ...);
-   |                     ^^^^
+LL |     fn t_f6(..., x: isize);
+   |             ^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 34 previous errors
 
index f8fcce6ba73f5a4ef677caa6bc91f3b3d0294e98..3875d6af1371678549e3410a64b5b2c63df7e9a3 100644 (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);
 }