// Copyright 2022-2024 Herb Sutter
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// Part of the Cppfront Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://github.com/hsutter/cppfront/blob/main/LICENSE for license information.
//#include "extrinsic_storage_std_locked.h"
#include "extrinsic_storage.h"
#include
#include
#include
#include
#include
#include
#include
#include
//-------------------------------------------------------------------------------
// Union instrumentation API for compiler integration
//
// Template parameters
// Tag discriminator tag to store for each object (uintNN_t where
// 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)
//
// 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 or U.A is passed to a function by on_set_alternative(&U,unknown)
// pointer/reference to non-const
// and we don't know the function
// is compiled in this mode
//
// U.A (alt A is otherwise used) on_get_alternative(&U,#A)
// and A is not a common initial
// sequence
//
// U is destroyed / goes out of scope on_destroy(&U)
//
// That's it. Here's an example:
// {
// union Test { int a; double b; };
// Test t = {42}; union_registry::on_set_alternative(&u,0);
// std::cout void { tags.erase(pobj); }
static inline auto on_set_alternative(void* pobj, uint32_t alt) noexcept -> void {
if (auto p = tags.find_or_insert(pobj)) { *p = alt; }
}
static inline auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void {
if (auto active = tags.find(pobj);
active // if we have discriminator info for this union
&& *active != alt // and the discriminator not what is expected
&& *active != unknown // and is not unknown
)
{
log