about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs38
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs27
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0044.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0130.md6
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0454.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0455.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0458.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0459.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0617.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0633.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0724.md2
-rw-r--r--compiler/rustc_lint/src/context.rs4
-rw-r--r--compiler/rustc_lint_defs/Cargo.toml1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs26
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs2
-rw-r--r--compiler/rustc_llvm/src/lib.rs2
16 files changed, 100 insertions, 34 deletions
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 4e9f9d66c5b..69257ce1c19 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -310,19 +310,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     );
                     let sig = hir::FnSig {
                         decl,
-                        header: this.lower_fn_header(header),
+                        header: this.lower_fn_header(header, fn_sig_span, id),
                         span: fn_sig_span,
                     };
                     hir::ItemKind::Fn(sig, generics, body_id)
                 })
             }
             ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
-            ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
-                abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
-                items: self
-                    .arena
-                    .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
-            },
+            ItemKind::ForeignMod(ref fm) => {
+                if fm.abi.is_none() {
+                    self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+                }
+                hir::ItemKind::ForeignMod {
+                    abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
+                    items: self
+                        .arena
+                        .alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
+                }
+            }
             ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
             ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
                 // We lower
@@ -801,13 +806,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
             AssocItemKind::Fn(_, ref sig, ref generics, None) => {
                 let names = self.lower_fn_params_to_names(&sig.decl);
                 let (generics, sig) =
-                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)))
             }
             AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => {
                 let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body));
                 let (generics, sig) =
-                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None);
+                    self.lower_method_sig(generics, sig, trait_item_def_id, false, None, i.id);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)))
             }
             AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => {
@@ -877,6 +882,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     impl_item_def_id,
                     impl_trait_return_allow,
                     asyncness.opt_return_id(),
+                    i.id,
                 );
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
@@ -1270,8 +1276,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
         fn_def_id: LocalDefId,
         impl_trait_return_allow: bool,
         is_async: Option<NodeId>,
+        id: NodeId,
     ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) {
-        let header = self.lower_fn_header(sig.header);
+        let header = self.lower_fn_header(sig.header, sig.span, id);
         let (generics, decl) = self.add_in_band_defs(
             generics,
             fn_def_id,
@@ -1288,12 +1295,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (generics, hir::FnSig { header, decl, span: sig.span })
     }
 
-    fn lower_fn_header(&mut self, h: FnHeader) -> hir::FnHeader {
+    fn lower_fn_header(&mut self, h: FnHeader, span: Span, id: NodeId) -> hir::FnHeader {
         hir::FnHeader {
             unsafety: self.lower_unsafety(h.unsafety),
             asyncness: self.lower_asyncness(h.asyncness),
             constness: self.lower_constness(h.constness),
-            abi: self.lower_extern(h.ext),
+            abi: self.lower_extern(h.ext, span, id),
         }
     }
 
@@ -1304,10 +1311,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
-    pub(super) fn lower_extern(&mut self, ext: Extern) -> abi::Abi {
+    pub(super) fn lower_extern(&mut self, ext: Extern, span: Span, id: NodeId) -> abi::Abi {
         match ext {
             Extern::None => abi::Abi::Rust,
-            Extern::Implicit => abi::Abi::C,
+            Extern::Implicit => {
+                self.maybe_lint_missing_abi(span, id, abi::Abi::C);
+                abi::Abi::C
+            }
             Extern::Explicit(abi) => self.lower_abi(abi),
         }
     }
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 89557c29dd1..6d95da02151 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -53,13 +53,15 @@ use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
 use rustc_hir::intravisit;
 use rustc_hir::{ConstArg, GenericArg, ParamName};
 use rustc_index::vec::{Idx, IndexVec};
-use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
+use rustc_session::lint::builtin::{BARE_TRAIT_OBJECTS, MISSING_ABI};
+use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer};
 use rustc_session::parse::ParseSess;
 use rustc_session::Session;
 use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::{respan, DesugaringKind};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
 
 use smallvec::{smallvec, SmallVec};
 use std::collections::BTreeMap;
@@ -1288,6 +1290,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
             TyKind::BareFn(ref f) => self.with_in_scope_lifetime_defs(&f.generic_params, |this| {
                 this.with_anonymous_lifetime_mode(AnonymousLifetimeMode::PassThrough, |this| {
+                    let span = this.sess.source_map().next_point(t.span.shrink_to_lo());
                     hir::TyKind::BareFn(this.arena.alloc(hir::BareFnTy {
                         generic_params: this.lower_generic_params(
                             &f.generic_params,
@@ -1295,7 +1298,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             ImplTraitContext::disallowed(),
                         ),
                         unsafety: this.lower_unsafety(f.unsafety),
-                        abi: this.lower_extern(f.ext),
+                        abi: this.lower_extern(f.ext, span, t.id),
                         decl: this.lower_fn_decl(&f.decl, None, false, None),
                         param_names: this.lower_fn_params_to_names(&f.decl),
                     }))
@@ -2777,6 +2780,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             )
         }
     }
+
+    fn maybe_lint_missing_abi(&mut self, span: Span, id: NodeId, default: Abi) {
+        // FIXME(davidtwco): This is a hack to detect macros which produce spans of the
+        // call site which do not have a macro backtrace. See #61963.
+        let is_macro_callsite = self
+            .sess
+            .source_map()
+            .span_to_snippet(span)
+            .map(|snippet| snippet.starts_with("#["))
+            .unwrap_or(true);
+        if !is_macro_callsite {
+            self.resolver.lint_buffer().buffer_lint_with_diagnostic(
+                MISSING_ABI,
+                id,
+                span,
+                "extern declarations without an explicit ABI are deprecated",
+                BuiltinLintDiagnostics::MissingAbi(span, default),
+            )
+        }
+    }
 }
 
 fn body_ids(bodies: &BTreeMap<hir::BodyId, hir::Body<'_>>) -> Vec<hir::BodyId> {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0044.md b/compiler/rustc_error_codes/src/error_codes/E0044.md
index 635ff953290..ed7daf8ddd9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0044.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0044.md
@@ -3,13 +3,13 @@ You cannot use type or const parameters on foreign items.
 Example of erroneous code:
 
 ```compile_fail,E0044
-extern { fn some_func<T>(x: T); }
+extern "C" { fn some_func<T>(x: T); }
 ```
 
 To fix this, replace the generic parameter with the specializations that you
 need:
 
 ```
-extern { fn some_func_i32(x: i32); }
-extern { fn some_func_i64(x: i64); }
+extern "C" { fn some_func_i32(x: i32); }
+extern "C" { fn some_func_i64(x: i64); }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0130.md b/compiler/rustc_error_codes/src/error_codes/E0130.md
index a270feaf58c..2cd27b5ec05 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0130.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0130.md
@@ -3,7 +3,7 @@ A pattern was declared as an argument in a foreign function declaration.
 Erroneous code example:
 
 ```compile_fail,E0130
-extern {
+extern "C" {
     fn foo((a, b): (u32, u32)); // error: patterns aren't allowed in foreign
                                 //        function declarations
 }
@@ -17,7 +17,7 @@ struct SomeStruct {
     b: u32,
 }
 
-extern {
+extern "C" {
     fn foo(s: SomeStruct); // ok!
 }
 ```
@@ -25,7 +25,7 @@ extern {
 Or:
 
 ```
-extern {
+extern "C" {
     fn foo(a: (u32, u32)); // ok!
 }
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0454.md b/compiler/rustc_error_codes/src/error_codes/E0454.md
index 23ca6c7824d..95a22b92e36 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0454.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0454.md
@@ -3,7 +3,7 @@ A link name was given with an empty name.
 Erroneous code example:
 
 ```compile_fail,E0454
-#[link(name = "")] extern {}
+#[link(name = "")] extern "C" {}
 // error: `#[link(name = "")]` given with empty name
 ```
 
@@ -11,5 +11,5 @@ The rust compiler cannot link to an external library if you don't give it its
 name. Example:
 
 ```no_run
-#[link(name = "some_lib")] extern {} // ok!
+#[link(name = "some_lib")] extern "C" {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0455.md b/compiler/rustc_error_codes/src/error_codes/E0455.md
index 2f80c34b889..84689b3ece6 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0455.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0455.md
@@ -4,7 +4,7 @@ as frameworks are specific to that operating system.
 Erroneous code example:
 
 ```ignore (should-compile_fail-but-cannot-doctest-conditionally-without-macos)
-#[link(name = "FooCoreServices", kind = "framework")] extern {}
+#[link(name = "FooCoreServices", kind = "framework")] extern "C" {}
 // OS used to compile is Linux for example
 ```
 
@@ -12,7 +12,7 @@ To solve this error you can use conditional compilation:
 
 ```
 #[cfg_attr(target="macos", link(name = "FooCoreServices", kind = "framework"))]
-extern {}
+extern "C" {}
 ```
 
 Learn more in the [Conditional Compilation][conditional-compilation] section
diff --git a/compiler/rustc_error_codes/src/error_codes/E0458.md b/compiler/rustc_error_codes/src/error_codes/E0458.md
index 075226ac98b..359aeb6fd9a 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0458.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0458.md
@@ -3,7 +3,7 @@ An unknown "kind" was specified for a link attribute.
 Erroneous code example:
 
 ```compile_fail,E0458
-#[link(kind = "wonderful_unicorn")] extern {}
+#[link(kind = "wonderful_unicorn")] extern "C" {}
 // error: unknown kind: `wonderful_unicorn`
 ```
 
diff --git a/compiler/rustc_error_codes/src/error_codes/E0459.md b/compiler/rustc_error_codes/src/error_codes/E0459.md
index 6f75f2a99a5..4a49a765445 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0459.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0459.md
@@ -3,7 +3,7 @@ A link was used without a name parameter.
 Erroneous code example:
 
 ```compile_fail,E0459
-#[link(kind = "dylib")] extern {}
+#[link(kind = "dylib")] extern "C" {}
 // error: `#[link(...)]` specified without `name = "foo"`
 ```
 
@@ -11,5 +11,5 @@ Please add the name parameter to allow the rust compiler to find the library
 you want. Example:
 
 ```no_run
-#[link(kind = "dylib", name = "some_lib")] extern {} // ok!
+#[link(kind = "dylib", name = "some_lib")] extern "C" {} // ok!
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0617.md b/compiler/rustc_error_codes/src/error_codes/E0617.md
index 61b56766c26..1c5d1f87b91 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0617.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0617.md
@@ -3,7 +3,7 @@ Attempted to pass an invalid type of variable into a variadic function.
 Erroneous code example:
 
 ```compile_fail,E0617
-extern {
+extern "C" {
     fn printf(c: *const i8, ...);
 }
 
@@ -21,7 +21,7 @@ to import from `std::os::raw`).
 In this case, `c_double` has the same size as `f64` so we can use it directly:
 
 ```no_run
-# extern {
+# extern "C" {
 #     fn printf(c: *const i8, ...);
 # }
 unsafe {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0633.md b/compiler/rustc_error_codes/src/error_codes/E0633.md
index 7f488cde664..4d1f0c47829 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0633.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0633.md
@@ -6,7 +6,7 @@ Erroneous code example:
 #![feature(unwind_attributes)]
 
 #[unwind()] // error: expected one argument
-pub extern fn something() {}
+pub extern "C" fn something() {}
 
 fn main() {}
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0724.md b/compiler/rustc_error_codes/src/error_codes/E0724.md
index e8f84d0fc7d..70578acbe0d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0724.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0724.md
@@ -18,7 +18,7 @@ the function inside of an `extern` block.
 ```
 #![feature(ffi_returns_twice)]
 
-extern {
+extern "C" {
    #[ffi_returns_twice] // ok!
    pub fn foo();
 }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index f4740be34cb..0f40324acb1 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -600,6 +600,10 @@ pub trait LintContext: Sized {
                 BuiltinLintDiagnostics::PatternsInFnsWithoutBody(span, ident) => {
                     db.span_suggestion(span, "remove `mut` from the parameter", ident.to_string(), Applicability::MachineApplicable);
                 }
+                BuiltinLintDiagnostics::MissingAbi(span, default_abi) => {
+                    db.span_label(span, "ABI should be specified here");
+                    db.help(&format!("the default ABI is {}", default_abi.name()));
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(LintDiagnosticBuilder::new(db));
diff --git a/compiler/rustc_lint_defs/Cargo.toml b/compiler/rustc_lint_defs/Cargo.toml
index 7f908088cf5..f909f159784 100644
--- a/compiler/rustc_lint_defs/Cargo.toml
+++ b/compiler/rustc_lint_defs/Cargo.toml
@@ -11,3 +11,4 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_span = { path = "../rustc_span" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_macros = { path = "../rustc_macros" }
+rustc_target = { path = "../rustc_target" }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f90fc7fc9ab..e9632796704 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2917,6 +2917,7 @@ declare_lint_pass! {
         FUNCTION_ITEM_REFERENCES,
         USELESS_DEPRECATED,
         UNSUPPORTED_NAKED_FUNCTIONS,
+        MISSING_ABI,
     ]
 }
 
@@ -2944,3 +2945,28 @@ declare_lint! {
 }
 
 declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
+
+declare_lint! {
+    /// The `missing_abi` lint detects cases where the ABI is omitted from
+    /// extern declarations.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(missing_abi)]
+    ///
+    /// extern fn foo() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Historically, Rust implicitly selected C as the ABI for extern
+    /// declarations. We expect to add new ABIs, like `C-unwind`, in the future,
+    /// though this has not yet happened, and especially with their addition
+    /// seeing the ABI easily will make code review easier.
+    pub MISSING_ABI,
+    Allow,
+    "No declared ABI for extern declaration"
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 2bfc6a85576..9d60a51a0af 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -6,6 +6,7 @@ use rustc_ast::node_id::{NodeId, NodeMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
 use rustc_span::edition::Edition;
 use rustc_span::{sym, symbol::Ident, MultiSpan, Span, Symbol};
+use rustc_target::spec::abi::Abi;
 
 pub mod builtin;
 
@@ -252,6 +253,7 @@ pub enum BuiltinLintDiagnostics {
     UnusedImports(String, Vec<(Span, String)>),
     RedundantImport(Vec<(Span, bool)>, Ident),
     DeprecatedMacro(Option<Symbol>, Span),
+    MissingAbi(Span, Abi),
     UnusedDocComment(Span),
     PatternsInFnsWithoutBody(Span, Ident),
 }
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index b2ffa271f62..592010d78cf 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -38,7 +38,7 @@ pub fn initialize_available_targets() {
         ($cfg:meta, $($method:ident),*) => { {
             #[cfg($cfg)]
             fn init() {
-                extern {
+                extern "C" {
                     $(fn $method();)*
                 }
                 unsafe {