use rustc_abi::{Align, ExternAbi};
use rustc_hir::attrs::{
    AttributeKind, EiiImplResolution, InlineAttr, InstrumentFnAttr as HirInstrumentFnAttr, Linkage,
    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::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::errors::feature_err;
use rustc_session::lint;
use rustc_span::{Span, sym};
use rustc_target::spec::Os;

use crate::errors;
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()) {
                        let mut diag = tcx.dcx().struct_span_err(
                            *span,
                            "extern mutable statics are not allowed with `#[linkage]`",
                        );
                        diag.note(
                            "marking the extern static mutable would allow changing which \
                            symbol the static references rather than make the target of the \
                            symbol mutable",
                        );
                        diag.emit();
                    }
                } 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::EiiImpls(impls) => {
                for i in impls {
                    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(decl) => decl.foreign_item,
                        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.
                        && tcx.externally_implementable_items(LOCAL_CRATE).get(&foreign_item).expect("at least one").1.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;
                }
            }
            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 } => {
                codegen_fn_attrs.patchable_function_entry =
                    Some(PatchableFunctionEntry::from_prefix_and_entry(*prefix, *entry));
            }
            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());
        }
    }

    // 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(errors::TargetFeatureDisableOrEnable {
                features,
                span: Some(span),
                missing_features: Some(errors::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
    };
}
