This commit is a bit ugly at the moment since I'm gathering feedback.
The APFloats we use to implement the Floating type might heap-allocate stuff to represent large values. When we then later write those to bytecode (via BytecodeEmitter, not EvalEmitter), that heap allocation is dangling.
So, for code like
constexpr long double f() { const long double L = __LDBL_MAX__; return L; }; static_assert(f() == __LDBL_MAX__);
asan would complain:
READ of size 8 at 0x602000001610 thread T0 #0 0x7f525300b911 in llvm::APInt::tcAssign(unsigned long*, unsigned long const*, unsigned int) /home/tbaeder/code/llvm-project/llvm/lib/Support/APInt.cpp:2331:14 #1 0x7f5252f3f640 in llvm::detail::IEEEFloat::copySignificand(llvm::detail::IEEEFloat const&) /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:878:3 #2 0x7f5252f3f42c in llvm::detail::IEEEFloat::assign(llvm::detail::IEEEFloat const&) /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:871:5 #3 0x7f5252f46828 in llvm::detail::IEEEFloat::IEEEFloat(llvm::detail::IEEEFloat const&) /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1143:3 #4 0x7f5295e12913 in llvm::APFloat::Storage::Storage(llvm::APFloat::Storage const&) /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:805:20 #5 0x7f5295e01d3a in llvm::APFloat::APFloat(llvm::APFloat const&) /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:928:3 #6 0x7f5297d56584 in clang::interp::Floating::Floating(clang::interp::Floating const&) /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7 #7 0x7f5297ea1fa0 in clang::interp::Floating llvm::support::endian::read<clang::interp::Floating, 1ul>(void const*, llvm::support::endianness) /home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:70:32 #8 0x7f5297ea1e14 in clang::interp::Floating llvm::support::endian::read<clang::interp::Floating, (llvm::support::endianness)2, 1ul>(void const*) /home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:77:10 #9 0x7f5297ea1d06 in std::enable_if<!std::is_pointer<clang::interp::Floating>::value, clang::interp::Floating>::type clang::interp::CodePtr::read<clang::interp::Floating>() /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Source.h:53:15 #10 0x7f52981e7601 in clang::interp::Floating clang::interp::ReadArg<clang::interp::Floating>(clang::interp::InterpState&, clang::interp::CodePtr&) /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Interp.h:1894:17 [...] freed by thread T0 here: #0 0x3d2511 in operator delete[](void*) (/home/tbaeder/code/llvm-project/build/bin/clang-17+0x3d2511) (BuildId: 88c1d01099b49a9ebf7bd913e201002fedf14f9b) #1 0x7f5252f3eff9 in llvm::detail::IEEEFloat::freeSignificand() /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:861:5 #2 0x7f5252f46968 in llvm::detail::IEEEFloat::~IEEEFloat() /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1150:27 #3 0x7f5295e11ad1 in llvm::APFloat::Storage::~Storage() /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:793:14 #4 0x7f5295e01d9c in llvm::APFloat::~APFloat() /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:931:22 #5 0x7f5297d5ddb8 in clang::interp::Floating::~Floating() /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7 #6 0x7f5297ea1fe7 in clang::interp::Floating llvm::support::endian::read<clang::interp::Floating, 1ul>(void const*, llvm::support::endianness) /home/tbaeder/code/llvm-project/llvm/include/llvm/Support/Endian.h:71:1 [...] previously allocated by thread T0 here: #0 0x3d1cb1 in operator new[](unsigned long) (/home/tbaeder/code/llvm-project/build/bin/clang-17+0x3d1cb1) (BuildId: 88c1d01099b49a9ebf7bd913e201002fedf14f9b) #1 0x7f5252f3ed6a in llvm::detail::IEEEFloat::initialize(llvm::fltSemantics const*) /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:856:25 #2 0x7f5252f467e7 in llvm::detail::IEEEFloat::IEEEFloat(llvm::detail::IEEEFloat const&) /home/tbaeder/code/llvm-project/llvm/lib/Support/APFloat.cpp:1142:3 #3 0x7f5295e12913 in llvm::APFloat::Storage::Storage(llvm::APFloat::Storage const&) /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:805:20 #4 0x7f5295e01d3a in llvm::APFloat::APFloat(llvm::APFloat const&) /home/tbaeder/code/llvm-project/llvm/include/llvm/ADT/APFloat.h:928:3 #5 0x7f5297d56584 in clang::interp::Floating::Floating(clang::interp::Floating const&) /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/Floating.h:27:7 #6 0x7f5297d17f93 in void emit<clang::interp::Floating>(clang::interp::Program&, std::__debug::vector<std::byte, std::allocator<std::byte>>&, clang::interp::Floating const&, bool&) /home/tbaeder/code/llvm-project/clang/lib/AST/Interp/ByteCodeEmitter.cpp:202:32
So, this patch adds specialized readArg() and emit() versions for Floating that serializes the APFloat.
I'm not really sure if this is the best way to go though.
Any chance we can use friendship here as well, rather than exposing the data member directly?