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/src/ast.rs5
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs31
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl4
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs65
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs11
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs136
-rw-r--r--compiler/rustc_expand/messages.ftl5
-rw-r--r--compiler/rustc_expand/src/errors.rs17
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs23
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs7
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs7
-rw-r--r--compiler/rustc_passes/src/naked_functions.rs5
13 files changed, 195 insertions, 123 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 564213ee7ee..628badd6f23 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2266,6 +2266,11 @@ bitflags::bitflags! {
 }
 
 impl InlineAsmOptions {
+    pub const COUNT: usize = Self::all().bits().count_ones() as usize;
+
+    pub const GLOBAL_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW);
+    pub const NAKED_OPTIONS: Self = Self::ATT_SYNTAX.union(Self::RAW).union(Self::NORETURN);
+
     pub fn human_readable_names(&self) -> Vec<&'static str> {
         let mut options = vec![];
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index e5bc4b38748..6fe50ad0d96 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1306,37 +1306,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
                     // result of `foo(...)` won't help.
                     break 'outer;
                 }
-
-                // We're suggesting `.clone()` on an borrowed value. See if the expression we have
-                // is an argument to a function or method call, and try to suggest cloning the
-                // *result* of the call, instead of the argument. This is closest to what people
-                // would actually be looking for in most cases, with maybe the exception of things
-                // like `fn(T) -> T`, but even then it is reasonable.
-                let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
-                let mut prev = expr;
-                while let hir::Node::Expr(parent) = self.infcx.tcx.parent_hir_node(prev.hir_id) {
-                    if let hir::ExprKind::Call(..) | hir::ExprKind::MethodCall(..) = parent.kind
-                        && let Some(call_ty) = typeck_results.node_type_opt(parent.hir_id)
-                        && let call_ty = call_ty.peel_refs()
-                        && (!call_ty
-                            .walk()
-                            .any(|t| matches!(t.unpack(), ty::GenericArgKind::Lifetime(_)))
-                            || if let ty::Alias(ty::Projection, _) = call_ty.kind() {
-                                // FIXME: this isn't quite right with lifetimes on assoc types,
-                                // but ignore for now. We will only suggest cloning if
-                                // `<Ty as Trait>::Assoc: Clone`, which should keep false positives
-                                // down to a managable ammount.
-                                true
-                            } else {
-                                false
-                            })
-                        && self.implements_clone(call_ty)
-                        && self.suggest_cloning_inner(err, call_ty, parent)
-                    {
-                        return;
-                    }
-                    prev = parent;
-                }
             }
         }
         let ty = ty.peel_refs();
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index b56bfa98357..876f3c2b135 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -199,6 +199,10 @@ builtin_macros_format_use_positional = consider using a positional formatting ar
 
 builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!`
 
+builtin_macros_global_asm_unsupported_option = the `{$symbol}` option cannot be used with `global_asm!`
+    .label = the `{$symbol}` option is not meaningful for global-scoped inline assembly
+    .suggestion = remove this option
+
 builtin_macros_invalid_crate_attribute = invalid crate attribute
 
 builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index b8fe6338493..62e59f1f4d4 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -310,6 +310,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
     p.dcx().emit_err(errors::AsmOptAlreadyprovided { span, symbol, full_span });
 }
 
+/// Report an invalid option error.
+///
+/// This function must be called immediately after the option token is parsed.
+/// Otherwise, the suggestion will be incorrect.
+fn err_unsupported_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
+    // Tool-only output
+    let full_span = if p.token.kind == token::Comma { span.to(p.token.span) } else { span };
+    p.dcx().emit_err(errors::GlobalAsmUnsupportedOption { span, symbol, full_span });
+}
+
 /// Try to set the provided option in the provided `AsmArgs`.
 /// If it is already set, report a duplicate option error.
 ///
@@ -318,13 +328,16 @@ fn err_duplicate_option(p: &Parser<'_>, symbol: Symbol, span: Span) {
 fn try_set_option<'a>(
     p: &Parser<'a>,
     args: &mut AsmArgs,
+    is_global_asm: bool,
     symbol: Symbol,
     option: ast::InlineAsmOptions,
 ) {
-    if !args.options.contains(option) {
-        args.options |= option;
-    } else {
+    if is_global_asm && !ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
+        err_unsupported_option(p, symbol, p.prev_token.span);
+    } else if args.options.contains(option) {
         err_duplicate_option(p, symbol, p.prev_token.span);
+    } else {
+        args.options |= option;
     }
 }
 
@@ -338,25 +351,33 @@ fn parse_options<'a>(
     p.expect(&token::OpenDelim(Delimiter::Parenthesis))?;
 
     while !p.eat(&token::CloseDelim(Delimiter::Parenthesis)) {
-        if !is_global_asm && p.eat_keyword(sym::pure) {
-            try_set_option(p, args, sym::pure, ast::InlineAsmOptions::PURE);
-        } else if !is_global_asm && p.eat_keyword(sym::nomem) {
-            try_set_option(p, args, sym::nomem, ast::InlineAsmOptions::NOMEM);
-        } else if !is_global_asm && p.eat_keyword(sym::readonly) {
-            try_set_option(p, args, sym::readonly, ast::InlineAsmOptions::READONLY);
-        } else if !is_global_asm && p.eat_keyword(sym::preserves_flags) {
-            try_set_option(p, args, sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS);
-        } else if !is_global_asm && p.eat_keyword(sym::noreturn) {
-            try_set_option(p, args, sym::noreturn, ast::InlineAsmOptions::NORETURN);
-        } else if !is_global_asm && p.eat_keyword(sym::nostack) {
-            try_set_option(p, args, sym::nostack, ast::InlineAsmOptions::NOSTACK);
-        } else if !is_global_asm && p.eat_keyword(sym::may_unwind) {
-            try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::MAY_UNWIND);
-        } else if p.eat_keyword(sym::att_syntax) {
-            try_set_option(p, args, sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX);
-        } else if p.eat_keyword(kw::Raw) {
-            try_set_option(p, args, kw::Raw, ast::InlineAsmOptions::RAW);
-        } else {
+        const OPTIONS: [(Symbol, ast::InlineAsmOptions); ast::InlineAsmOptions::COUNT] = [
+            (sym::pure, ast::InlineAsmOptions::PURE),
+            (sym::nomem, ast::InlineAsmOptions::NOMEM),
+            (sym::readonly, ast::InlineAsmOptions::READONLY),
+            (sym::preserves_flags, ast::InlineAsmOptions::PRESERVES_FLAGS),
+            (sym::noreturn, ast::InlineAsmOptions::NORETURN),
+            (sym::nostack, ast::InlineAsmOptions::NOSTACK),
+            (sym::may_unwind, ast::InlineAsmOptions::MAY_UNWIND),
+            (sym::att_syntax, ast::InlineAsmOptions::ATT_SYNTAX),
+            (kw::Raw, ast::InlineAsmOptions::RAW),
+        ];
+
+        'blk: {
+            for (symbol, option) in OPTIONS {
+                let kw_matched =
+                    if !is_global_asm || ast::InlineAsmOptions::GLOBAL_OPTIONS.contains(option) {
+                        p.eat_keyword(symbol)
+                    } else {
+                        p.eat_keyword_noexpect(symbol)
+                    };
+
+                if kw_matched {
+                    try_set_option(p, args, is_global_asm, symbol, option);
+                    break 'blk;
+                }
+            }
+
             return p.unexpected();
         }
 
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 49d640436c2..2e6bdae14a8 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -846,6 +846,17 @@ pub(crate) struct AsmOptAlreadyprovided {
 }
 
 #[derive(Diagnostic)]
+#[diag(builtin_macros_global_asm_unsupported_option)]
+pub(crate) struct GlobalAsmUnsupportedOption {
+    #[primary_span]
+    #[label]
+    pub(crate) span: Span,
+    pub(crate) symbol: Symbol,
+    #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
+    pub(crate) full_span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(builtin_macros_test_runner_invalid)]
 pub(crate) struct TestRunnerInvalid {
     #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 0cd3e60b0cc..491b457358a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -8,7 +8,6 @@ use crate::traits::*;
 use crate::MemFlags;
 
 use rustc_middle::mir;
-use rustc_middle::ty::cast::{CastTy, IntTy};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -238,21 +237,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 }
             }
             OperandValue::Immediate(imm) => {
-                let OperandValueKind::Immediate(in_scalar) = operand_kind else {
+                let OperandValueKind::Immediate(from_scalar) = operand_kind else {
                     bug!("Found {operand_kind:?} for operand {operand:?}");
                 };
-                if let OperandValueKind::Immediate(out_scalar) = cast_kind
-                    && in_scalar.size(self.cx) == out_scalar.size(self.cx)
+                if let OperandValueKind::Immediate(to_scalar) = cast_kind
+                    && from_scalar.size(self.cx) == to_scalar.size(self.cx)
                 {
-                    let operand_bty = bx.backend_type(operand.layout);
-                    let cast_bty = bx.backend_type(cast);
+                    let from_backend_ty = bx.backend_type(operand.layout);
+                    let to_backend_ty = bx.backend_type(cast);
                     Some(OperandValue::Immediate(self.transmute_immediate(
                         bx,
                         imm,
-                        in_scalar,
-                        operand_bty,
-                        out_scalar,
-                        cast_bty,
+                        from_scalar,
+                        from_backend_ty,
+                        to_scalar,
+                        to_backend_ty,
                     )))
                 } else {
                     None
@@ -281,6 +280,58 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         }
     }
 
+    /// Cast one of the immediates from an [`OperandValue::Immediate`]
+    /// or an [`OperandValue::Pair`] to an immediate of the target type.
+    ///
+    /// Returns `None` if the cast is not possible.
+    fn cast_immediate(
+        &self,
+        bx: &mut Bx,
+        mut imm: Bx::Value,
+        from_scalar: abi::Scalar,
+        from_backend_ty: Bx::Type,
+        to_scalar: abi::Scalar,
+        to_backend_ty: Bx::Type,
+    ) -> Option<Bx::Value> {
+        use abi::Primitive::*;
+
+        // When scalars are passed by value, there's no metadata recording their
+        // valid ranges. For example, `char`s are passed as just `i32`, with no
+        // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
+        // the range of the input value too, not just the output range.
+        self.assume_scalar_range(bx, imm, from_scalar, from_backend_ty);
+
+        imm = match (from_scalar.primitive(), to_scalar.primitive()) {
+            (Int(_, is_signed), Int(..)) => bx.intcast(imm, to_backend_ty, is_signed),
+            (Float(_), Float(_)) => {
+                let srcsz = bx.cx().float_width(from_backend_ty);
+                let dstsz = bx.cx().float_width(to_backend_ty);
+                if dstsz > srcsz {
+                    bx.fpext(imm, to_backend_ty)
+                } else if srcsz > dstsz {
+                    bx.fptrunc(imm, to_backend_ty)
+                } else {
+                    imm
+                }
+            }
+            (Int(_, is_signed), Float(_)) => {
+                if is_signed {
+                    bx.sitofp(imm, to_backend_ty)
+                } else {
+                    bx.uitofp(imm, to_backend_ty)
+                }
+            }
+            (Pointer(..), Pointer(..)) => bx.pointercast(imm, to_backend_ty),
+            (Int(_, is_signed), Pointer(..)) => {
+                let usize_imm = bx.intcast(imm, bx.cx().type_isize(), is_signed);
+                bx.inttoptr(usize_imm, to_backend_ty)
+            }
+            (Float(_), Int(_, is_signed)) => bx.cast_float_to_int(is_signed, imm, to_backend_ty),
+            _ => return None,
+        };
+        Some(imm)
+    }
+
     /// Transmutes one of the immediates from an [`OperandValue::Immediate`]
     /// or an [`OperandValue::Pair`] to an immediate of the target type.
     ///
@@ -487,62 +538,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     | mir::CastKind::IntToFloat
                     | mir::CastKind::PtrToPtr
                     | mir::CastKind::FnPtrToPtr
-
                     // Since int2ptr can have arbitrary integer types as input (so we have to do
                     // sign extension and all that), it is currently best handled in the same code
                     // path as the other integer-to-X casts.
                     | mir::CastKind::PointerWithExposedProvenance => {
+                        let imm = operand.immediate();
+                        let operand_kind = self.value_kind(operand.layout);
+                        let OperandValueKind::Immediate(from_scalar) = operand_kind else {
+                            bug!("Found {operand_kind:?} for operand {operand:?}");
+                        };
+                        let from_backend_ty = bx.cx().immediate_backend_type(operand.layout);
+
                         assert!(bx.cx().is_backend_immediate(cast));
-                        let ll_t_out = bx.cx().immediate_backend_type(cast);
+                        let to_backend_ty = bx.cx().immediate_backend_type(cast);
                         if operand.layout.abi.is_uninhabited() {
-                            let val = OperandValue::Immediate(bx.cx().const_poison(ll_t_out));
+                            let val = OperandValue::Immediate(bx.cx().const_poison(to_backend_ty));
                             return OperandRef { val, layout: cast };
                         }
-                        let r_t_in =
-                            CastTy::from_ty(operand.layout.ty).expect("bad input type for cast");
-                        let r_t_out = CastTy::from_ty(cast.ty).expect("bad output type for cast");
-                        let ll_t_in = bx.cx().immediate_backend_type(operand.layout);
-                        let llval = operand.immediate();
-
-                        let newval = match (r_t_in, r_t_out) {
-                            (CastTy::Int(i), CastTy::Int(_)) => {
-                                bx.intcast(llval, ll_t_out, i.is_signed())
-                            }
-                            (CastTy::Float, CastTy::Float) => {
-                                let srcsz = bx.cx().float_width(ll_t_in);
-                                let dstsz = bx.cx().float_width(ll_t_out);
-                                if dstsz > srcsz {
-                                    bx.fpext(llval, ll_t_out)
-                                } else if srcsz > dstsz {
-                                    bx.fptrunc(llval, ll_t_out)
-                                } else {
-                                    llval
-                                }
-                            }
-                            (CastTy::Int(i), CastTy::Float) => {
-                                if i.is_signed() {
-                                    bx.sitofp(llval, ll_t_out)
-                                } else {
-                                    bx.uitofp(llval, ll_t_out)
-                                }
-                            }
-                            (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Ptr(_)) => {
-                                bx.pointercast(llval, ll_t_out)
-                            }
-                            (CastTy::Int(i), CastTy::Ptr(_)) => {
-                                let usize_llval =
-                                    bx.intcast(llval, bx.cx().type_isize(), i.is_signed());
-                                bx.inttoptr(usize_llval, ll_t_out)
-                            }
-                            (CastTy::Float, CastTy::Int(IntTy::I)) => {
-                                bx.cast_float_to_int(true, llval, ll_t_out)
-                            }
-                            (CastTy::Float, CastTy::Int(_)) => {
-                                bx.cast_float_to_int(false, llval, ll_t_out)
-                            }
-                            _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty),
+                        let cast_kind = self.value_kind(cast);
+                        let OperandValueKind::Immediate(to_scalar) = cast_kind else {
+                            bug!("Found {cast_kind:?} for operand {cast:?}");
                         };
-                        OperandValue::Immediate(newval)
+
+                        self.cast_immediate(bx, imm, from_scalar, from_backend_ty, to_scalar, to_backend_ty)
+                            .map(OperandValue::Immediate)
+                            .unwrap_or_else(|| {
+                                bug!("Unsupported cast of {operand:?} to {cast:?}");
+                            })
                     }
                     mir::CastKind::Transmute => {
                         self.codegen_transmute_operand(bx, operand, cast).unwrap_or_else(|| {
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index cc0b110d2bc..18d95a398fd 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -105,6 +105,11 @@ expand_meta_var_dif_seq_matchers = {$msg}
 expand_meta_var_expr_unrecognized_var =
     variable `{$key}` is not recognized in meta-variable expression
 
+expand_missing_fragment_specifier = missing fragment specifier
+    .note = fragment specifiers must be specified in the 2024 edition
+    .suggestion_add_fragspec = try adding a specifier here
+    .valid = {$valid}
+
 expand_module_circular =
     circular modules: {$modules}
 
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 0be7403f25b..6f1a0f16c49 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -417,6 +417,23 @@ pub struct DuplicateMatcherBinding {
 }
 
 #[derive(Diagnostic)]
+#[diag(expand_missing_fragment_specifier)]
+#[note]
+#[help(expand_valid)]
+pub struct MissingFragmentSpecifier {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(
+        expand_suggestion_add_fragspec,
+        style = "verbose",
+        code = ":spec",
+        applicability = "maybe-incorrect"
+    )]
+    pub add_span: Span,
+    pub valid: &'static str,
+}
+
+#[derive(Diagnostic)]
 #[diag(expand_invalid_fragment_specifier)]
 #[help]
 pub struct InvalidFragmentSpecifier {
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 4b730d307fd..161e27fe02c 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -115,6 +115,7 @@ use rustc_errors::MultiSpan;
 use rustc_lint_defs::BuiltinLintDiag;
 use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
 use rustc_session::parse::ParseSess;
+use rustc_span::edition::Edition;
 use rustc_span::symbol::kw;
 use rustc_span::{symbol::MacroRulesNormalizedIdent, ErrorGuaranteed, Span};
 
@@ -122,6 +123,8 @@ use smallvec::SmallVec;
 
 use std::iter;
 
+use super::quoted::VALID_FRAGMENT_NAMES_MSG_2021;
+
 /// Stack represented as linked list.
 ///
 /// Those are used for environments because they grow incrementally and are not mutable.
@@ -269,12 +272,20 @@ fn check_binders(
                 // FIXME: Report this as a hard error eventually and remove equivalent errors from
                 // `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once
                 // as a hard error and then once as a buffered lint.
-                psess.buffer_lint(
-                    MISSING_FRAGMENT_SPECIFIER,
-                    span,
-                    node_id,
-                    BuiltinLintDiag::MissingFragmentSpecifier,
-                );
+                if span.edition() >= Edition::Edition2024 {
+                    psess.dcx().emit_err(errors::MissingFragmentSpecifier {
+                        span,
+                        add_span: span.shrink_to_hi(),
+                        valid: VALID_FRAGMENT_NAMES_MSG_2021,
+                    });
+                } else {
+                    psess.buffer_lint(
+                        MISSING_FRAGMENT_SPECIFIER,
+                        span,
+                        node_id,
+                        BuiltinLintDiag::MissingFragmentSpecifier,
+                    );
+                }
             }
             if !macros.is_empty() {
                 psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs");
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 9c480f17b42..57b6947316d 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -16,7 +16,7 @@ use rustc_span::Span;
 const VALID_FRAGMENT_NAMES_MSG: &str = "valid fragment specifiers are \
                                         `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, \
                                         `literal`, `path`, `meta`, `tt`, `item` and `vis`";
-const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \
+pub const VALID_FRAGMENT_NAMES_MSG_2021: &str = "valid fragment specifiers are \
                                              `ident`, `block`, `stmt`, `expr`, `expr_2021`, `pat`, \
                                              `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, \
                                              `item` and `vis`";
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 2100f4b4a1a..96c52845a4a 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -509,6 +509,13 @@ impl<'tcx, 'a> TOFinder<'tcx, 'a> {
                     BinOp::Ne => ScalarInt::FALSE,
                     _ => return None,
                 };
+                if value.const_.ty().is_floating_point() {
+                    // Floating point equality does not follow bit-patterns.
+                    // -0.0 and NaN both have special rules for equality,
+                    // and therefore we cannot use integer comparisons for them.
+                    // Avoid handling them, though this could be extended in the future.
+                    return None;
+                }
                 let value = value.const_.normalize(self.tcx, self.param_env).try_to_scalar_int()?;
                 let conds = conditions.map(self.arena, |c| Condition {
                     value,
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 7326b9ec51f..e7240869a39 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -599,7 +599,7 @@ impl<'a> Parser<'a> {
 
     /// If the next token is the given keyword, eats it and returns `true`.
     /// Otherwise, returns `false`. An expectation is also added for diagnostics purposes.
-    // Public for rustfmt usage.
+    // Public for rustc_builtin_macros and rustfmt usage.
     #[inline]
     pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
         if self.check_keyword(kw) {
@@ -631,8 +631,11 @@ impl<'a> Parser<'a> {
         false
     }
 
+    /// If the next token is the given keyword, eats it and returns `true`.
+    /// Otherwise, returns `false`. No expectation is added.
+    // Public for rustc_builtin_macros usage.
     #[inline]
-    fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
+    pub fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
         if self.token.is_keyword(kw) {
             self.bump();
             true
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index dbbf802c920..4c5089b8676 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -244,10 +244,7 @@ impl<'tcx> CheckInlineAssembly<'tcx> {
             self.tcx.dcx().emit_err(NakedFunctionsOperands { unsupported_operands });
         }
 
-        let supported_options =
-            InlineAsmOptions::RAW | InlineAsmOptions::NORETURN | InlineAsmOptions::ATT_SYNTAX;
-        let unsupported_options = asm.options.difference(supported_options);
-
+        let unsupported_options = asm.options.difference(InlineAsmOptions::NAKED_OPTIONS);
         if !unsupported_options.is_empty() {
             self.tcx.dcx().emit_err(NakedFunctionsAsmOptions {
                 span,