use rustc_abi::{Align, ExternAbi};
use rustc_hir::attrs::{
    AttributeKind, EiiImplResolution, InlineAttr, InstrumentFnAttr as HirInstrumentFnAttr, Linkage,
    OptimizeAttr, RtsanSetting, UsedBy,
};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{self as hir, Attribute, find_attr};
use rustc_macros::Diagnostic;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::{
    CodegenFnAttrFlags, CodegenFnAttrs, InstrumentFnAttr, PatchableFunctionEntry, SanitizerFnAttrs,
};
use rustc_middle::mono::Visibility;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self as ty, TyCtxt};
use rustc_session::diagnostics::feature_err;
use rustc_session::lint;
use rustc_span::{Span, sym};
use rustc_target::spec::Os;

use crate::diagnostics;
use crate::target_features::{
    check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
};

/// In some cases, attributes are only valid on functions, but it's the `check_attr`
/// pass that checks that they aren't used anywhere else, rather than this module.
/// In these cases, we bail from performing further checks that are only meaningful for
/// functions (such as calling `fn_sig`, which ICEs if given a non-function). We also
/// report a delayed bug, just in case `check_attr` isn't doing its job.
fn try_fn_sig<'tcx>(
    tcx: TyCtxt<'tcx>,
    did: LocalDefId,
    attr_span: Span,
) -> Option<ty::EarlyBinder<'tcx, ty::PolyFnSig<'tcx>>> {
    use DefKind::*;

    let def_kind = tcx.def_kind(did);
    if let Fn | AssocFn | Variant | Ctor(..) = def_kind {
        Some(tcx.fn_sig(did))
    } else {
        tcx.dcx().span_delayed_bug(attr_span, "this attribute can only be applied to functions");
        None
    }
}

/// Spans that are collected when processing built-in attributes,
/// that are useful for emitting diagnostics later.
#[derive(Default)]
struct InterestingAttributeDiagnosticSpans {
    link_ordinal: Option<Span>,
    sanitize: Option<Span>,
    inline: Option<Span>,
    no_mangle: Option<Span>,
}

/// Process the builtin attrs ([`hir::Attribute`]) on the item.
/// Many of them directly translate to codegen attrs.
fn process_builtin_attrs(
    tcx: TyCtxt<'_>,
    did: LocalDefId,
    attrs: &[Attribute],
    codegen_fn_attrs: &mut CodegenFnAttrs,
) -> InterestingAttributeDiagnosticSpans {
    let mut interesting_spans = InterestingAttributeDiagnosticSpans::default();
    let rust_target_features = tcx.rust_target_features(LOCAL_CRATE);

    let parsed_attrs = attrs
        .iter()
        .filter_map(|attr| if let hir::Attribute::Parsed(attr) = attr { Some(attr) } else { None });
    for attr in parsed_attrs {
        match attr {
            AttributeKind::Cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
            AttributeKind::ExportName { name, .. } => codegen_fn_attrs.symbol_name = Some(*name),
            AttributeKind::Inline(inline, span) => {
                codegen_fn_attrs.inline = *inline;
                interesting_spans.inline = Some(*span);
            }
            AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
            AttributeKind::RustcAlign { align, .. } => codegen_fn_attrs.alignment = Some(*align),
            AttributeKind::LinkName { name, .. } => {
                // FIXME Remove check for foreign functions once #[link_name] on non-foreign
                // functions is a hard error
                if tcx.is_foreign_item(did) {
                    codegen_fn_attrs.symbol_name = Some(*name);
                }
            }
            AttributeKind::LinkOrdinal { ordinal, span } => {
                codegen_fn_attrs.link_ordinal = Some(*ordinal);
                interesting_spans.link_ordinal = Some(*span);
            }
            AttributeKind::LinkSection { name } => codegen_fn_attrs.link_section = Some(*name),
            AttributeKind::NoMangle(attr_span) => {
                interesting_spans.no_mangle = Some(*attr_span);
                if tcx.opt_item_name(did.to_def_id()).is_some() {
                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
                } else {
                    tcx.dcx()
                        .span_delayed_bug(*attr_span, "no_mangle should be on a named function");
                }
            }
            AttributeKind::Optimize(optimize, _) => codegen_fn_attrs.optimize = *optimize,
            AttributeKind::TargetFeature { features, attr_span, was_forced } => {
                let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else {
                    tcx.dcx().span_delayed_bug(*attr_span, "target_feature applied to non-fn");
                    continue;
                };
                let safe_target_features =
                    matches!(sig.header.safety, hir::HeaderSafety::SafeTargetFeatures);
                codegen_fn_attrs.safe_target_features = safe_target_features;
                if safe_target_features && !was_forced {
                    if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {
                        // The `#[target_feature]` attribute is allowed on
                        // WebAssembly targets on all functions. Prior to stabilizing
                        // the `target_feature_11` feature, `#[target_feature]` was
                        // only permitted on unsafe functions because on most targets
                        // execution of instructions that are not supported is
                        // considered undefined behavior. For WebAssembly which is a
                        // 100% safe target at execution time it's not possible to
                        // execute undefined instructions, and even if a future
                        // feature was added in some form for this it would be a
                        // deterministic trap. There is no undefined behavior when
                        // executing WebAssembly so `#[target_feature]` is allowed
                        // on safe functions (but again, only for WebAssembly)
                        //
                        // Note that this is also allowed if `actually_rustdoc` so
                        // if a target is documenting some wasm-specific code then
                        // it's not spuriously denied.
                        //
                        // Now that `#[target_feature]` is permitted on safe functions,
                        // this exception must still exist for allowing the attribute on
                        // `main`, `start`, and other functions that are not usually
                        // allowed.
                    } else {
                        check_target_feature_trait_unsafe(tcx, did, *attr_span);
                    }
                }
                from_target_feature_attr(
                    tcx,
                    did,
                    features,
                    *was_forced,
                    rust_target_features,
                    &mut codegen_fn_attrs.target_features,
                );
            }
            AttributeKind::TrackCaller(attr_span) => {
                let is_closure = tcx.is_closure_like(did.to_def_id());

                if !is_closure
                    && let Some(fn_sig) = try_fn_sig(tcx, did, *attr_span)
                    && fn_sig.skip_binder().abi() != ExternAbi::Rust
                {
                    // This error is already reported in `rustc_ast_passes/src/ast_validation.rs`.
                    tcx.dcx().delayed_bug("`#[track_caller]` requires the Rust ABI");
                }
                if is_closure
                    && !tcx.features().closure_track_caller()
                    && !attr_span.allows_unstable(sym::closure_track_caller)
                {
                    feature_err(
                        &tcx.sess,
                        sym::closure_track_caller,
                        *attr_span,
                        "`#[track_caller]` on closures is currently unstable",
                    )
                    .emit();
                }
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER
            }
            AttributeKind::Used { used_by } => match used_by {
                UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER,
                UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER,
                UsedBy::Default => {
                    let used_form = if tcx.sess.target.os == Os::Illumos {
                        // illumos' `ld` doesn't support a section header that would represent
                        // `#[used(linker)]`, see
                        // https://github.com/rust-lang/rust/issues/146169. For that target,
                        // downgrade as if `#[used(compiler)]` was requested and hope for the
                        // best.
                        CodegenFnAttrFlags::USED_COMPILER
                    } else {
                        CodegenFnAttrFlags::USED_LINKER
                    };
                    codegen_fn_attrs.flags |= used_form;
                }
            },
            AttributeKind::FfiConst => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST,
            AttributeKind::FfiPure(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE,
            AttributeKind::RustcStdInternalSymbol => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
            }
            AttributeKind::Linkage(linkage, span) => {
                let linkage = Some(*linkage);

                if tcx.is_foreign_item(did) {
                    codegen_fn_attrs.import_linkage = linkage;

                    if tcx.is_mutable_static(did.into()) {
                        tcx.dcx().span_delayed_bug(
                            *span,
                            "`extern { #[linkage] static mut ...` is checked in check_attr}",
                        );
                    }
                } else {
                    codegen_fn_attrs.linkage = linkage;
                }
            }
            AttributeKind::Sanitize { span, .. } => {
                interesting_spans.sanitize = Some(*span);
            }
            AttributeKind::RustcObjcClass { classname } => {
                codegen_fn_attrs.objc_class = Some(*classname);
            }
            AttributeKind::RustcObjcSelector { methname } => {
                codegen_fn_attrs.objc_selector = Some(*methname);
            }
            AttributeKind::RustcEiiForeignItem => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;
            }
            AttributeKind::EiiImpl(i) => {
                let foreign_item = match i.resolution {
                    EiiImplResolution::Macro(def_id) => {
                        let Some(extern_item) = find_attr!(tcx, def_id, EiiDeclaration(target) => target.foreign_item
                        ) else {
                            tcx.dcx().span_delayed_bug(
                                i.span,
                                "resolved to something that's not an EII",
                            );
                            continue;
                        };
                        extern_item
                    }
                    EiiImplResolution::Known(def_id) => def_id,
                    EiiImplResolution::Error(_eg) => continue,
                };

                // this is to prevent a bug where a single crate defines both the default and explicit implementation
                // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
                // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent.
                // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that
                // the default implementation is used while an explicit implementation is given.
                if
                // if this is a default impl
                i.is_default
                        // iterate over all implementations *in the current crate*
                        // (this is ok since we generate codegen fn attrs in the local crate)
                        // if any of them is *not default* then don't emit the alias.
                        && {
                            let (_, impls) = tcx.externally_implementable_items(LOCAL_CRATE).get(&foreign_item).unwrap_or_else(|| bug!("EII impl should have an entry"));
                            impls.iter().any(|(_, imp)| !imp.is_default)
                        }
                {
                    continue;
                }

                codegen_fn_attrs.foreign_item_symbol_aliases.push((
                    foreign_item,
                    if i.is_default { Linkage::WeakAny } else { Linkage::External },
                    Visibility::Default,
                ));
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM;

                // If the declaration is `#[track_caller]`, derive it onto the implementation
                // too. The shim that forwards to this impl (see `add_function_aliases`) takes
                // its ABI from the impl's `fn_abi`, so every impl must agree on whether the
                // caller-location argument is present, otherwise it would be silently dropped.
                if tcx
                    .codegen_fn_attrs(foreign_item)
                    .flags
                    .contains(CodegenFnAttrFlags::TRACK_CALLER)
                {
                    codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
                }
            }
            AttributeKind::ThreadLocal => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL
            }
            AttributeKind::InstructionSet(instruction_set) => {
                codegen_fn_attrs.instruction_set = Some(*instruction_set)
            }
            AttributeKind::RustcAllocator => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR
            }
            AttributeKind::RustcDeallocator => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR
            }
            AttributeKind::RustcReallocator => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR
            }
            AttributeKind::RustcAllocatorZeroed => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
            }
            AttributeKind::RustcNounwind => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND
            }
            AttributeKind::RustcOffloadKernel => {
                codegen_fn_attrs.flags |= CodegenFnAttrFlags::OFFLOAD_KERNEL
            }
            AttributeKind::PatchableFunctionEntry { prefix, entry, section } => {
                codegen_fn_attrs.patchable_function_entry =
                    Some(PatchableFunctionEntry::from_prefix_entry_and_section(
                        *prefix, *entry, *section,
                    ));
            }
            AttributeKind::InstrumentFn(instrument_fn) => {
                codegen_fn_attrs.instrument_fn = match instrument_fn {
                    HirInstrumentFnAttr::On => InstrumentFnAttr::On,
                    HirInstrumentFnAttr::Off => InstrumentFnAttr::Off,
                };
            }
            _ => {}
        }
    }

    interesting_spans
}

/// Applies overrides for codegen fn attrs. These often have a specific reason why they're necessary.
/// Please comment why when adding a new one!
fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut CodegenFnAttrs) {
    // Apply the minimum function alignment here. This ensures that a function's alignment is
    // determined by the `-C` flags of the crate it is defined in, not the `-C` flags of the crate
    // it happens to be codegen'd (or const-eval'd) in.
    codegen_fn_attrs.alignment =
        Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment);

    // Passed in sanitizer settings are always the default.
    assert!(codegen_fn_attrs.sanitizers == SanitizerFnAttrs::default());
    // Replace with #[sanitize] value
    codegen_fn_attrs.sanitizers = tcx.sanitizer_settings_for(did);
    // On trait methods, inherit the `#[align]` of the trait's method prototype.
    codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.inherited_align(did));

    // naked function MUST NOT be inlined! This attribute is required for the rust compiler itself,
    // but not for the code generation backend because at that point the naked function will just be
    // a declaration, with a definition provided in global assembly.
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
        codegen_fn_attrs.inline = InlineAttr::Never;
    }

    // #73631: closures inherit `#[target_feature]` annotations
    //
    // If this closure is marked `#[inline(always)]`, simply skip adding `#[target_feature]`.
    //
    // At this point, `unsafe` has already been checked and `#[target_feature]` only affects codegen.
    // Due to LLVM limitations, emitting both `#[inline(always)]` and `#[target_feature]` is *unsound*:
    // the function may be inlined into a caller with fewer target features. Also see
    // <https://github.com/rust-lang/rust/issues/116573>.
    //
    // Using `#[inline(always)]` implies that this closure will most likely be inlined into
    // its parent function, which effectively inherits the features anyway. Boxing this closure
    // would result in this closure being compiled without the inherited target features, but this
    // is probably a poor usage of `#[inline(always)]` and easily avoided by not using the attribute.
    if tcx.is_closure_like(did.to_def_id()) && codegen_fn_attrs.inline != InlineAttr::Always {
        let owner_id = tcx.parent(did.to_def_id());
        if tcx.def_kind(owner_id).has_codegen_attrs() {
            codegen_fn_attrs
                .target_features
                .extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());
        }
    }

    // Closures inherit `#[optimize]` annotations.
    if tcx.is_closure_like(did.to_def_id()) {
        let owner_id = tcx.parent(did.to_def_id());
        if tcx.def_kind(owner_id).has_codegen_attrs() {
            let owner_attrs = tcx.codegen_fn_attrs(owner_id);
            if codegen_fn_attrs.optimize == OptimizeAttr::Default {
                codegen_fn_attrs.optimize = owner_attrs.optimize;
            }
        }
    }

    // When `no_builtins` is applied at the crate level, we should add the
    // `no-builtins` attribute to each function to ensure it takes effect in LTO.
    let no_builtins = find_attr!(tcx, crate, NoBuiltins);
    if no_builtins {
        codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_BUILTINS;
    }

    // inherit track-caller properly
    if tcx.should_inherit_track_caller(did) {
        codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER;
    }

    // Foreign items by default use no mangling for their symbol name.
    if tcx.is_foreign_item(did) {
        codegen_fn_attrs.flags |= CodegenFnAttrFlags::FOREIGN_ITEM;

        // There's a few exceptions to this rule though:
        if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
            // * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
            //   both for exports and imports through foreign items. This is handled further,
            //   during symbol mangling logic.
        } else if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::EXTERNALLY_IMPLEMENTABLE_ITEM)
        {
            // * externally implementable items keep their mangled symbol name.
            //   multiple EIIs can have the same name, so not mangling them would be a bug.
            //   Implementing an EII does the appropriate name resolution to make sure the implementations
            //   get the same symbol name as the *mangled* foreign item they refer to so that's all good.
        } else if codegen_fn_attrs.symbol_name.is_some() {
            // * This can be overridden with the `#[link_name]` attribute
        } else {
            // NOTE: there's one more exception that we cannot apply here. On wasm,
            // some items cannot be `no_mangle`.
            // However, we don't have enough information here to determine that.
            // As such, no_mangle foreign items on wasm that have the same defid as some
            // import will *still* be mangled despite this.
            //
            // if none of the exceptions apply; apply no_mangle
            codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE;
        }
    }
}

#[derive(Diagnostic)]
#[diag("non-default `sanitize` will have no effect after inlining")]
struct SanitizeOnInline {
    #[note("inlining requested here")]
    inline_span: Span,
}

#[derive(Diagnostic)]
#[diag("the async executor can run blocking code, without realtime sanitizer catching it")]
struct AsyncBlocking;

fn check_result(
    tcx: TyCtxt<'_>,
    did: LocalDefId,
    interesting_spans: InterestingAttributeDiagnosticSpans,
    codegen_fn_attrs: &CodegenFnAttrs,
) {
    // If a function uses `#[target_feature]` it can't be inlined into general
    // purpose functions as they wouldn't have the right target features
    // enabled. For that reason we also forbid `#[inline(always)]` as it can't be
    // respected.
    //
    // `#[rustc_force_inline]` doesn't need to be prohibited here, only
    // `#[inline(always)]`, as forced inlining is implemented entirely within
    // rustc (and so the MIR inliner can do any necessary checks for compatible target
    // features).
    //
    // This sidesteps the LLVM blockers in enabling `target_features` +
    // `inline(always)` to be used together (see rust-lang/rust#116573 and
    // llvm/llvm-project#70563).
    if !codegen_fn_attrs.target_features.is_empty()
        && matches!(codegen_fn_attrs.inline, InlineAttr::Always)
        && let Some(span) = interesting_spans.inline
    {
        let mut diag = tcx
            .dcx()
            .struct_span_err(span, "cannot use `#[inline(always)]` with `#[target_feature]`");
        diag.note(
            "See this issue for full discussion: \
            https://github.com/rust-lang/rust/issues/145574",
        );
        diag.emit();
    }

    // warn that inline has no effect when no_sanitize is present
    if codegen_fn_attrs.sanitizers != SanitizerFnAttrs::default()
        && codegen_fn_attrs.inline.always()
        && let (Some(sanitize_span), Some(inline_span)) =
            (interesting_spans.sanitize, interesting_spans.inline)
    {
        let hir_id = tcx.local_def_id_to_hir_id(did);
        tcx.emit_node_span_lint(
            lint::builtin::INLINE_NO_SANITIZE,
            hir_id,
            sanitize_span,
            SanitizeOnInline { inline_span },
        )
    }

    // warn for nonblocking async functions, blocks and closures.
    // This doesn't behave as expected, because the executor can run blocking code without the sanitizer noticing.
    if codegen_fn_attrs.sanitizers.rtsan_setting == RtsanSetting::Nonblocking
        && let Some(sanitize_span) = interesting_spans.sanitize
        // async fn
        && (tcx.asyncness(did).is_async()
            // async block
            || tcx.is_coroutine(did.into())
            // async closure
            || (tcx.is_closure_like(did.into())
                && tcx.hir_node_by_def_id(did).expect_closure().kind
                    != rustc_hir::ClosureKind::Closure))
    {
        let hir_id = tcx.local_def_id_to_hir_id(did);
        tcx.emit_node_span_lint(
            lint::builtin::RTSAN_NONBLOCKING_ASYNC,
            hir_id,
            sanitize_span,
            AsyncBlocking,
        );
    }

    // error when specifying link_name together with link_ordinal
    if let Some(_) = codegen_fn_attrs.symbol_name
        && let Some(_) = codegen_fn_attrs.link_ordinal
    {
        let msg = "cannot use `#[link_name]` with `#[link_ordinal]`";
        if let Some(span) = interesting_spans.link_ordinal {
            tcx.dcx().span_err(span, msg);
        } else {
            tcx.dcx().err(msg);
        }
    }

    if let Some(features) = check_tied_features(
        tcx.sess,
        &codegen_fn_attrs
            .target_features
            .iter()
            .map(|features| (features.name.as_str(), true))
            .collect(),
    ) {
        let span = find_attr!(tcx, did, TargetFeature{attr_span: span, ..} => *span)
            .unwrap_or_else(|| tcx.def_span(did));

        tcx.dcx()
            .create_err(diagnostics::TargetFeatureDisableOrEnable {
                features,
                span: Some(span),
                missing_features: Some(diagnostics::MissingFeatures),
            })
            .emit();
    }
}

fn handle_lang_items(
    tcx: TyCtxt<'_>,
    did: LocalDefId,
    interesting_spans: &InterestingAttributeDiagnosticSpans,
    attrs: &[Attribute],
    codegen_fn_attrs: &mut CodegenFnAttrs,
) {
    let lang_item = find_attr!(attrs, Lang(lang) => lang);

    // Weak lang items have the same semantics as "std internal" symbols in the
    // sense that they're preserved through all our LTO passes and only
    // strippable by the linker.
    //
    // Additionally weak lang items have predetermined symbol names.
    if let Some(lang_item) = lang_item
        && let Some(link_name) = lang_item.link_name()
    {
        codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
        codegen_fn_attrs.symbol_name = Some(link_name);
    }

    // error when using no_mangle on a lang item item
    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
        && codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE)
    {
        let mut err = tcx
            .dcx()
            .struct_span_err(
                interesting_spans.no_mangle.unwrap_or_default(),
                "`#[no_mangle]` cannot be used on internal language items",
            )
            .with_note("Rustc requires this item to have a specific mangled name.")
            .with_span_label(tcx.def_span(did), "should be the internal language item");
        if let Some(lang_item) = lang_item
            && let Some(link_name) = lang_item.link_name()
        {
            err = err
                .with_note("If you are trying to prevent mangling to ease debugging, many")
                .with_note(format!("debuggers support a command such as `rbreak {link_name}` to"))
                .with_note(format!(
                    "match `.*{link_name}.*` instead of `break {link_name}` on a specific name"
                ))
        }
        err.emit();
    }
}

/// Generate the [`CodegenFnAttrs`] for an item (identified by the [`LocalDefId`]).
///
/// This happens in 4 stages:
/// - apply built-in attributes that directly translate to codegen attributes.
/// - handle lang items. These have special codegen attrs applied to them.
/// - apply overrides, like minimum requirements for alignment and other settings that don't rely directly the built-in attrs on the item.
///   overrides come after applying built-in attributes since they may only apply when certain attributes were already set in the stage before.
/// - check that the result is valid. There's various ways in which this may not be the case, such as certain combinations of attrs.
fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
    if cfg!(debug_assertions) {
        let def_kind = tcx.def_kind(did);
        assert!(
            def_kind.has_codegen_attrs(),
            "unexpected `def_kind` in `codegen_fn_attrs`: {def_kind:?}",
        );
    }

    let mut codegen_fn_attrs = CodegenFnAttrs::new();
    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(did));

    let interesting_spans = process_builtin_attrs(tcx, did, attrs, &mut codegen_fn_attrs);
    handle_lang_items(tcx, did, &interesting_spans, attrs, &mut codegen_fn_attrs);
    apply_overrides(tcx, did, &mut codegen_fn_attrs);
    check_result(tcx, did, interesting_spans, &codegen_fn_attrs);

    codegen_fn_attrs
}

fn sanitizer_settings_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerFnAttrs {
    // Backtrack to the crate root.
    let mut settings = match tcx.opt_local_parent(did) {
        // Check the parent (recursively).
        Some(parent) => tcx.sanitizer_settings_for(parent),
        // We reached the crate root without seeing an attribute, so
        // there is no sanitizers to exclude.
        None => SanitizerFnAttrs::default(),
    };

    // Check for a sanitize annotation directly on this def.
    if let Some((on_set, off_set, rtsan)) =
        find_attr!(tcx, did, Sanitize {on_set, off_set, rtsan, ..} => (on_set, off_set, rtsan))
    {
        // the on set is the set of sanitizers explicitly enabled.
        // we mask those out since we want the set of disabled sanitizers here
        settings.disabled &= !*on_set;
        // the off set is the set of sanitizers explicitly disabled.
        // we or those in here.
        settings.disabled |= *off_set;
        // the on set and off set are distjoint since there's a third option: unset.
        // a node may not set the sanitizer setting in which case it inherits from parents.
        // the code above in this function does this backtracking

        // if rtsan was specified here override the parent
        if let Some(rtsan) = rtsan {
            settings.rtsan_setting = *rtsan;
        }
    }
    settings
}

/// Checks if the provided DefId is a method in a trait impl for a trait which has track_caller
/// applied to the method prototype.
fn should_inherit_track_caller(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
    tcx.trait_item_of(def_id).is_some_and(|id| {
        tcx.codegen_fn_attrs(id).flags.intersects(CodegenFnAttrFlags::TRACK_CALLER)
    })
}

/// If the provided DefId is a method in a trait impl, return the value of the `#[align]`
/// attribute on the method prototype (if any).
fn inherited_align<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Align> {
    tcx.codegen_fn_attrs(tcx.trait_item_of(def_id)?).alignment
}

pub(crate) fn provide(providers: &mut Providers) {
    *providers = Providers {
        codegen_fn_attrs,
        should_inherit_track_caller,
        inherited_align,
        sanitizer_settings_for,
        ..*providers
    };
}
