Skip to content

Commit

Permalink
Add "unknown" state for unions passed to opaque functions
Browse files Browse the repository at this point in the history
  • Loading branch information
hsutter committed Jan 3, 2025
1 parent bd42f8d commit f4d4a01
Showing 1 changed file with 13 additions and 7 deletions.
20 changes: 13 additions & 7 deletions experimental/union_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,18 @@
// NN is large enough to hold the #alternatives in the union)
//
// For an object U of union type that
// has a unique address, when inject a call to this (zero-based alternative #s)
// has a unique address, when Inject a call to this (zero-based alternative #s)
//
// U is created initialized on_set_alternative(&U,0) = the first alternative# is active
//
// U is created uninitialized on_set_alternative(&U,invalid)
//
// U.A = xxx (alt #A is assigned to) on_set_alternative(&U,#A)
// U.A = xxx (alt A is assigned to) on_set_alternative(&U,#A)
//
// U.A (alt #A is otherwise mentioned) on_get_alternative(&U,#A)
// U.A is passed to a function by on_set_alternative(&U,unknown)
// pointer/reference to non-const
//
// U.A (alt A is otherwise used) on_get_alternative(&U,#A)
// and A is not a common initial
// sequence
//
Expand All @@ -44,24 +47,27 @@
// std::cout << t.b; union_registry<>::on_get_alternative(&u,1);
// } union_registry<>::on_destroy(&u);
//
// For all unions with under 256 alternatives, use union_registry<>
// For all unions with between 256 and 16k alternatives, use union_registry<uint16_t>
// If you find a union with >16k alternatives, email me the story and use union_registry<uint32_t>
// For all unions with up to 254 alternatives, use union_registry<>
// For all unions with between 255 and 16k-2 alternatives, use union_registry<uint16_t>
// If you find a union with >16k-2 alternatives, email me the story and use union_registry<uint32_t>
//
template<typename Tag = uint8_t>
class union_registry {
inline static auto tags = extrinsic_storage<Tag>{};
inline static auto log = std::ofstream{ "union-violations.log" };
public:
inline static auto invalid = std::numeric_limits<Tag>::max();
inline static auto unknown = std::numeric_limits<Tag>::max()-1;

static auto on_destroy (void* pobj) -> void { tags.erase(pobj); }
static auto on_set_alternative(void* pobj, uint32_t alt) -> void { tags[pobj] = alt; }
static auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void
{
if (auto active = tags[pobj];
active != alt
) {
&& active != unknown
)
{
log << where.file_name() << '(' << where.line() << ") " << where.function_name()
<< ": union " << pobj
<< ", active " << (active == invalid ? "invalid" : std::to_string(active))
Expand Down

0 comments on commit f4d4a01

Please sign in to comment.