From cfcbe45b607c1963e922fe869caf9b641855c695 Mon Sep 17 00:00:00 2001 From: Mayukha Vadari Date: Tue, 6 Oct 2026 12:12:22 +0000 Subject: [PATCH] test: Declare, not define, entry instantiations in SLEBase test (#8357) --- src/tests/libxrpl/ledger/SLEBase.cpp | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/tests/libxrpl/ledger/SLEBase.cpp b/src/tests/libxrpl/ledger/SLEBase.cpp index 231021aa12..17bf3afb8e 100644 --- a/src/tests/libxrpl/ledger/SLEBase.cpp +++ b/src/tests/libxrpl/ledger/SLEBase.cpp @@ -38,6 +38,7 @@ #include // IWYU pragma: keep #include // IWYU pragma: keep #include +#include #include #include #include @@ -55,11 +56,11 @@ namespace xrpl { -// The entry classes have no consumers yet, and an un-instantiated class -// template is barely type-checked. Instantiate every one explicitly so the -// compiler actually checks them. Keep this block even once real call sites -// exist: it is what catches a new ledger entry type being added without its -// wrapper class, or the wrapper class existing but never actually being used. +// An un-instantiated class template is barely type-checked. Name every entry +// class in a static_assert below so its class definition is instantiated and +// type-checked; the per-type suites check the member bodies. Keep this block +// even once real call sites exist: it is what catches a new ledger entry type +// being added without its wrapper class. // // Driving this off ledger_entries.macro keeps it exhaustive by construction: // adding a ledger entry type without adding its entry class stops compiling @@ -76,12 +77,22 @@ template class SLEBase; #pragma push_macro("LEDGER_ENTRY") #undef LEDGER_ENTRY +// No explicit instantiation here, neither a definition nor a declaration. +// A definition would instantiate an entry a second time once its member +// bodies live in its own .cpp (MSVC rejects that with C4661 under /WX), and a +// declaration (`extern template`) stops clang from emitting the inline +// constructors of the header-only entries at -O0, which leaves them undefined +// at link time in the debug builds. Naming the class in a static_assert is +// enough to instantiate its definition, which is all this exhaustiveness +// check needs; the per-type suites exercise the members. #define LEDGER_ENTRY(tag, value, name, ...) \ - template class name##Entry; \ - template class name##Entry; \ static_assert( \ name##Entry::kEntryType == tag && name##Entry::kEntryType == tag, \ - #name "Entry must be bound to " #tag); + #name "Entry must be bound to " #tag); \ + static_assert( \ + std::is_constructible_v, Keylet const&, ReadView const&> && \ + std::is_constructible_v, Keylet const&, ApplyView&>, \ + #name "Entry must be constructible from a Keylet and a view"); #include