]> git.lizzy.rs Git - rust.git/commitdiff
Move `allow_c_varadic` logic to `ast_validation`.
authorMazdak Farrokhzad <twingoow@gmail.com>
Mon, 2 Dec 2019 01:38:33 +0000 (02:38 +0100)
committerMazdak Farrokhzad <twingoow@gmail.com>
Thu, 12 Dec 2019 17:01:33 +0000 (18:01 +0100)
12 files changed:
src/librustc_parse/parser/item.rs
src/librustc_parse/parser/ty.rs
src/librustc_passes/ast_validation.rs
src/test/ui/invalid/invalid-variadic-function.rs [deleted file]
src/test/ui/invalid/invalid-variadic-function.stderr [deleted file]
src/test/ui/parser/variadic-ffi-3.rs [deleted file]
src/test/ui/parser/variadic-ffi-3.stderr [deleted file]
src/test/ui/parser/variadic-ffi-4.rs [deleted file]
src/test/ui/parser/variadic-ffi-4.stderr [deleted file]
src/test/ui/parser/variadic-ffi-semantic-restrictions.rs [new file with mode: 0644]
src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr [new file with mode: 0644]
src/test/ui/parser/variadic-ffi-syntactic-pass.rs [new file with mode: 0644]

index 0126297a3586e6173d77913a801b3529fe1b7550..d4b62e8ebba6bcbd2f50d9723486f41e2b3eecbb 100644 (file)
@@ -1727,8 +1727,6 @@ fn mk_item(&self, span: Span, ident: Ident, kind: ItemKind, vis: Visibility,
 pub(super) struct ParamCfg {
     /// Is `self` is allowed as the first parameter?
     pub is_self_allowed: bool,
-    /// Is `...` allowed as the tail of the parameter list?
-    pub allow_c_variadic: bool,
     /// `is_name_required` decides if, per-parameter,
     /// the parameter must have a pattern or just a type.
     pub is_name_required: fn(&token::Token) -> bool,
@@ -1744,16 +1742,8 @@ fn parse_item_fn(
         attrs: Vec<Attribute>,
         header: FnHeader,
     ) -> PResult<'a, Option<P<Item>>> {
-        let is_c_abi = match header.ext {
-            ast::Extern::None => false,
-            ast::Extern::Implicit => true,
-            ast::Extern::Explicit(abi) => abi.symbol_unescaped == sym::C,
-        };
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            // FIXME: Parsing should not depend on ABI or unsafety and
-            // the variadic parameter should always be parsed.
-            allow_c_variadic: is_c_abi && header.unsafety == Unsafety::Unsafe,
             is_name_required: |_| true,
         })?;
         let (inner_attrs, body) = self.parse_inner_attrs_and_block()?;
@@ -1772,7 +1762,6 @@ fn parse_item_foreign_fn(
         self.expect_keyword(kw::Fn)?;
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: true,
             is_name_required: |_| true,
         })?;
         let span = lo.to(self.token.span);
@@ -1797,7 +1786,6 @@ fn parse_assoc_fn(
         let header = self.parse_fn_front_matter()?;
         let (ident, decl, generics) = self.parse_fn_sig(ParamCfg {
             is_self_allowed: true,
-            allow_c_variadic: false,
             is_name_required,
         })?;
         let sig = FnSig { header, decl };
@@ -1993,12 +1981,12 @@ fn parse_param_general(&mut self, cfg: &ParamCfg, is_trait_item: bool) -> PResul
             }
 
             self.eat_incorrect_doc_comment_for_param_type();
-            (pat, self.parse_ty_for_param(cfg.allow_c_variadic)?)
+            (pat, self.parse_ty_for_param()?)
         } else {
             debug!("parse_param_general ident_to_pat");
             let parser_snapshot_before_ty = self.clone();
             self.eat_incorrect_doc_comment_for_param_type();
-            let mut ty = self.parse_ty_for_param(cfg.allow_c_variadic);
+            let mut ty = self.parse_ty_for_param();
             if ty.is_ok() && self.token != token::Comma &&
                self.token != token::CloseDelim(token::Paren) {
                 // This wasn't actually a type, but a pattern looking like a type,
index 1dffa6c94a898ea7d17722c3abd3a14f68611c5e..3ab290d1cbbc5a594b8b40f3238ac2acdd7719b6 100644 (file)
@@ -33,8 +33,8 @@ pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
     /// Parse a type suitable for a function or function pointer parameter.
     /// The difference from `parse_ty` is that this version allows `...`
     /// (`CVarArgs`) at the top level of the the type.
-    pub(super) fn parse_ty_for_param(&mut self, allow_c_variadic: bool) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true, true, allow_c_variadic)
+    pub(super) fn parse_ty_for_param(&mut self) -> PResult<'a, P<Ty>> {
+        self.parse_ty_common(true, true, true)
     }
 
     /// Parses a type in restricted contexts where `+` is not permitted.
@@ -306,7 +306,6 @@ fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a,
         self.expect_keyword(kw::Fn)?;
         let cfg = ParamCfg {
             is_self_allowed: false,
-            allow_c_variadic: true,
             is_name_required: |_| false,
         };
         let decl = self.parse_fn_decl(cfg, false)?;
index ad6c99494a60fd28012eec9d66aae02d0bad6daa..a26c991c9cfb25f81975f7162442e9700b5e55ee 100644 (file)
@@ -306,6 +306,19 @@ fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) {
             .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect")
             .emit();
     }
+
+    fn check_c_varadic_type(&self, decl: &FnDecl) {
+        for Param { ty, span, .. } in &decl.inputs {
+            if let TyKind::CVarArgs = ty.kind {
+                self.err_handler()
+                    .struct_span_err(
+                        *span,
+                        "only foreign or `unsafe extern \"C\" functions may be C-variadic",
+                    )
+                    .emit();
+            }
+        }
+    }
 }
 
 enum GenericPosition {
@@ -554,6 +567,12 @@ fn visit_item(&mut self, item: &'a Item) {
                         }
                     }
                 }
+                // Reject C-varadic type unless the function is `unsafe extern "C"` semantically.
+                match sig.header.ext {
+                    Extern::Explicit(StrLit { symbol_unescaped: sym::C, .. }) |
+                    Extern::Implicit if sig.header.unsafety == Unsafety::Unsafe => {}
+                    _ => self.check_c_varadic_type(&sig.decl),
+                }
             }
             ItemKind::ForeignMod(..) => {
                 self.invalid_visibility(
@@ -795,6 +814,13 @@ fn visit_trait_item(&mut self, ti: &'a AssocItem) {
         self.check_defaultness(ti.span, ti.defaultness);
         visit::walk_trait_item(self, ti);
     }
+
+    fn visit_assoc_item(&mut self, item: &'a AssocItem) {
+        if let AssocItemKind::Method(sig, _) = &item.kind {
+            self.check_c_varadic_type(&sig.decl);
+        }
+        visit::walk_assoc_item(self, item);
+    }
 }
 
 pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffer) -> bool {
diff --git a/src/test/ui/invalid/invalid-variadic-function.rs b/src/test/ui/invalid/invalid-variadic-function.rs
deleted file mode 100644 (file)
index 8d23f0e..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-extern "C" fn foo(x: u8, ...);
-//~^ ERROR only foreign functions are allowed to be C-variadic
-//~| ERROR expected one of `->`, `where`, or `{`, found `;`
diff --git a/src/test/ui/invalid/invalid-variadic-function.stderr b/src/test/ui/invalid/invalid-variadic-function.stderr
deleted file mode 100644 (file)
index 7e58b17..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/invalid-variadic-function.rs:1:26
-   |
-LL | extern "C" fn foo(x: u8, ...);
-   |                          ^^^
-
-error: expected one of `->`, `where`, or `{`, found `;`
-  --> $DIR/invalid-variadic-function.rs:1:30
-   |
-LL | extern "C" fn foo(x: u8, ...);
-   |                              ^ expected one of `->`, `where`, or `{`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/parser/variadic-ffi-3.rs b/src/test/ui/parser/variadic-ffi-3.rs
deleted file mode 100644 (file)
index ce83cc8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-fn foo(x: isize, ...) {
-    //~^ ERROR: only foreign functions are allowed to be C-variadic
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-3.stderr b/src/test/ui/parser/variadic-ffi-3.stderr
deleted file mode 100644 (file)
index aeeebdb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/variadic-ffi-3.rs:1:18
-   |
-LL | fn foo(x: isize, ...) {
-   |                  ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/parser/variadic-ffi-4.rs b/src/test/ui/parser/variadic-ffi-4.rs
deleted file mode 100644 (file)
index 5f8b3f8..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-extern "C" fn foo(x: isize, ...) {
-    //~^ ERROR: only foreign functions are allowed to be C-variadic
-}
-
-fn main() {}
diff --git a/src/test/ui/parser/variadic-ffi-4.stderr b/src/test/ui/parser/variadic-ffi-4.stderr
deleted file mode 100644 (file)
index da83276..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0743]: only foreign functions are allowed to be C-variadic
-  --> $DIR/variadic-ffi-4.rs:1:29
-   |
-LL | extern "C" fn foo(x: isize, ...) {
-   |                             ^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0743`.
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs b/src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
new file mode 100644 (file)
index 0000000..57086bc
--- /dev/null
@@ -0,0 +1,26 @@
+#![feature(c_variadic)]
+
+fn main() {}
+
+fn f1(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
+
+extern fn f3(x: isize, ...) {}
+//~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+
+struct X;
+
+impl X {
+    fn f4(x: isize, ...) {}
+    //~^ ERROR: only foreign or `unsafe extern "C" functions may be C-variadic
+}
+
+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
+}
diff --git a/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr b/src/test/ui/parser/variadic-ffi-semantic-restrictions.stderr
new file mode 100644 (file)
index 0000000..69244d9
--- /dev/null
@@ -0,0 +1,38 @@
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:5:17
+   |
+LL | fn f1(x: isize, ...) {}
+   |                 ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:8:28
+   |
+LL | extern "C" fn f2(x: isize, ...) {}
+   |                            ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:11:24
+   |
+LL | extern fn f3(x: isize, ...) {}
+   |                        ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:17:21
+   |
+LL |     fn f4(x: isize, ...) {}
+   |                     ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:22:21
+   |
+LL |     fn f5(x: isize, ...) {}
+   |                     ^^^^
+
+error: only foreign or `unsafe extern "C" functions may be C-variadic
+  --> $DIR/variadic-ffi-semantic-restrictions.rs:24:21
+   |
+LL |     fn f6(x: isize, ...);
+   |                     ^^^^
+
+error: aborting due to 6 previous errors
+
diff --git a/src/test/ui/parser/variadic-ffi-syntactic-pass.rs b/src/test/ui/parser/variadic-ffi-syntactic-pass.rs
new file mode 100644 (file)
index 0000000..f8fcce6
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+
+fn main() {}
+
+#[cfg(FALSE)]
+fn f1(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern "C" fn f2(x: isize, ...) {}
+
+#[cfg(FALSE)]
+extern fn f3(x: isize, ...) {}
+
+struct X;
+
+#[cfg(FALSE)]
+impl X {
+    fn f4(x: isize, ...) {}
+}
+
+#[cfg(FALSE)]
+trait T {
+    fn f5(x: isize, ...) {}
+    fn f6(x: isize, ...);
+}