[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lmi] Unit tests hygiene
From: |
Greg Chicares |
Subject: |
Re: [lmi] Unit tests hygiene |
Date: |
Mon, 13 Jun 2022 20:33:53 +0000 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.8.0 |
On 6/9/22 23:22, Vadim Zeitlin wrote:
> On Thu, 9 Jun 2022 21:37:00 +0000 Greg Chicares <gchicares@sbcglobal.net>
> wrote:
>
> GC> Here's an example that I think is UB, though UBSan doesn't flag it:
> GC>
> GC> // UBSAN doesn't complain about this; shouldn't it?
> GC> auto const b {db.query<oenum_alb_or_anb>(DB_ChildRiderMinAmt)};
> GC> LMI_TEST_EQUAL(25000, b);
> GC>
> GC> Am I missing something, or is this truly a false negative?
>
> Sorry, I know I'm tired today (because I've already made a couple of bad
> mistakes in the last hour), but what exactly is the problem here, i.e. why
> should it be UB? AFAIK comparing an enum with an int is not UB, due to the
> promotion rules. Am I missing some other reason here?
Consider the throwaway patch below, which I believe demonstrates that
this isn't mere comparison of an int to an enum, but actually entails
the assignment of an out-of-enumerated-range 'int' value into an enum.
In more detail, I manually "inlined" the implementation of
template<typename T> T product_database::query(e_database_key k) const
from 'database.hpp' as 'c' below. I believe that
- the assignment into 'c' is just like the assignment into 'a'; and
- the assignment into 'c' is just like the assignment into 'b';
and so by transitivity all three should be treated the same by UBSan.
But UBSan flags only 'a', not 'b' or 'c', whereas I believe that all
three constitute UB.
At any rate, the outdented last lines in the patch show that a variable
of this type:
enum oenum_alb_or_anb
{oe_age_last_birthday
,oe_age_nearest_birthday_ties_younger
,oe_age_nearest_birthday_ties_older
};
with lawful values {0,1,2} has acquired the value 25000 . How can that be?
If not by way of undefined behavior, then how else?
--8<----8<----8<----8<----8<----8<----8<----8<--
diff --git a/input_test.cpp b/input_test.cpp
index 9966169b8..fc6a04f5c 100644
--- a/input_test.cpp
+++ b/input_test.cpp
@@ -172,9 +172,24 @@ void input_test::test_product_database()
db.query_into(DB_ChildRiderMinAmt, a);
LMI_TEST_EQUAL(25000, a);
#endif // 0
+// If that "#endif" were moved two lines above, UBsan would complain.
// UBSAN doesn't complain about this; shouldn't it?
auto const b {db.query<oenum_alb_or_anb>(DB_ChildRiderMinAmt)};
LMI_TEST_EQUAL(25000, b);
+ auto const d {db.query<double>(DB_ChildRiderMinAmt)};
+ auto const c
+ {static_cast<oenum_alb_or_anb>
+ (bourn_cast<std::underlying_type_t<oenum_alb_or_anb>>(d))
+ };
+ static_assert(std::is_enum_v<oenum_alb_or_anb>);
+ static_assert(std::is_enum_v<decltype(c)>);
+ static_assert(std::is_same_v<decltype(c),oenum_alb_or_anb const>);
+ LMI_TEST_EQUAL(25000, c);
+
+int status = 0; // next line prints "oenum_alb_or_anb"
+std::cout << abi::__cxa_demangle(typeid(c).name(), nullptr, nullptr, &status)
<< std::endl;
+// next line prints "25000"
+std::cout << c << std::endl;
#if defined LMI_CLANG
# pragma clang diagnostic pop
--8<----8<----8<----8<----8<----8<----8<----8<--
- Re: [lmi] UBSAN flags, (continued)
- Re: [lmi] UBSAN flags, Vadim Zeitlin, 2022/06/04
- Re: [lmi] UBSAN flags, Greg Chicares, 2022/06/04
- Re: [lmi] UBSAN flags, Greg Chicares, 2022/06/06
- Re: [lmi] UBSAN flags, Vadim Zeitlin, 2022/06/06
- Re: [lmi] UBSAN flags, Greg Chicares, 2022/06/06
- Re: [lmi] UBSAN flags, Vadim Zeitlin, 2022/06/06
- Re: [lmi] UBSAN flags, Greg Chicares, 2022/06/07
Re: [lmi] Unit tests hygiene, Greg Chicares, 2022/06/09