It is possible for optimizations to modify attributes on exact
definitions. In particular, DeadArgumentElimination may find that a
certain argument is dead, and replace arguments in calls with `poison`.
This requires dropping the `noundef` attribute on the argument.
When ThinLTO import is performed, the destination module already has a
declaration for the function, and the definition is not imported (e.g.
because it is noinline), we currently simply retain the original
declaration. This is incorrect if call with poison arguments were
imported, as the calls become immediate UB.
There was a previous attempt to address this in
https://reviews.llvm.org/D139209. What that patch did was to fix up the
attributes of the declaration after the fact, dropping UB implying
attributes that are not present on the definition. It was reverted
because it made an incorrect assumption that the signature between the
declaration and definition must match.
In this PR, I propose to fix the issue in a different way: If the source
module holds an exact definition (which are the ones that can be, in
limited ways, modified by optimizations), then even if we don't import
the definition, we should still import a declaration based on it. This
ensures that we respect any dropped attributes. (It's probably also
useful for optimization purposes, because we also see more inferred
attributes.)
Fixes https://github.com/llvm/llvm-project/issues/58976.