@@ -406,28 +406,49 @@ namespace detail
406406 }
407407}
408408
409- // Use make_context_info instead of INFO() to avoid MinGW GCC vtable issues
410- // (see StringContextScope above).
411- #define CHECK_BATCH_EQ (b1, b2 ) \
412- do \
413- { \
414- auto _ctx1 = ::detail::make_context_info (#b1, b1); \
415- auto _ctx2 = ::detail::make_context_info (#b2, b2); \
416- CHECK_UNARY (::detail::expect_batch_near (b1, b2)); \
409+ // We use make_context_info instead of INFO() to avoid MinGW GCC vtable issues
410+ // (see StringContextScope above). Unlike INFO(), make_context_info is eager:
411+ // it stringifies its operands at construction. To keep the happy path cheap
412+ // (these macros are called in tight loops and QEMU-emulated CI targets like
413+ // ppc64le blow past wall-clock otherwise), we first evaluate the predicate
414+ // and only build the context when it fails. On failure the predicate is
415+ // re-evaluated inside CHECK_UNARY so doctest records the expression text;
416+ // this requires the operands to be side-effect-free, which holds for all
417+ // call sites here.
418+ #define CHECK_BATCH_EQ (b1, b2 ) \
419+ do \
420+ { \
421+ const bool batches_are_near = ::detail::expect_batch_near (b1, b2); \
422+ if (!batches_are_near) \
423+ { \
424+ auto _ctx1 = ::detail::make_context_info (#b1, b1); \
425+ auto _ctx2 = ::detail::make_context_info (#b2, b2); \
426+ CHECK_UNARY (batches_are_near); \
427+ } \
417428 } while (0 )
418- #define CHECK_SCALAR_EQ (s1, s2 ) \
419- do \
420- { \
421- auto _ctx1 = ::detail::make_context_info (#s1, s1); \
422- auto _ctx2 = ::detail::make_context_info (#s2, s2); \
423- CHECK_UNARY (::detail::expect_scalar_near (s1, s2)); \
429+
430+ #define CHECK_SCALAR_EQ (s1, s2 ) \
431+ do \
432+ { \
433+ const bool scalars_are_near = ::detail::expect_scalar_near (s1, s2); \
434+ if (!scalars_are_near) \
435+ { \
436+ auto _ctx1 = ::detail::make_context_info (#s1, s1); \
437+ auto _ctx2 = ::detail::make_context_info (#s2, s2); \
438+ CHECK_UNARY (scalars_are_near); \
439+ } \
424440 } while (0 )
425- #define CHECK_VECTOR_EQ (v1, v2 ) \
426- do \
427- { \
428- auto _ctx1 = ::detail::make_context_info (#v1, v1); \
429- auto _ctx2 = ::detail::make_context_info (#v2, v2); \
430- CHECK_UNARY (::detail::expect_vector_near (v1, v2)); \
441+
442+ #define CHECK_VECTOR_EQ (v1, v2 ) \
443+ do \
444+ { \
445+ const bool vectors_are_near = ::detail::expect_vector_near (v1, v2); \
446+ if (!vectors_are_near) \
447+ { \
448+ auto _ctx1 = ::detail::make_context_info (#v1, v1); \
449+ auto _ctx2 = ::detail::make_context_info (#v2, v2); \
450+ CHECK_UNARY (vectors_are_near); \
451+ } \
431452 } while (0 )
432453
433454/* **********************
0 commit comments