Fix ClassIDs for DLL usage
If ClassID::Of<T>() is used inside tint and used outside tint for the same type, and tint is built as a DLL, then the address of the Unique<T>::token can resolve to different addresses, entirely breaking Castable. Replace address-of for a unique symbol with a single static counter that's incremented for each use of TINT_INSTANTIATE_CLASS_ID(). Change-Id: I40dc81b1273110291d90a1d5ec05428f7e703c6a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/42460 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
72260e44ae
commit
80cb20de7c
|
@ -22,28 +22,36 @@
|
|||
|
||||
namespace tint {
|
||||
|
||||
/// Helper macro to instantiate the ClassID for `CLASS`.
|
||||
class ClassID;
|
||||
|
||||
/// Helper macro to instantiate the TypeInfo<T> template for `CLASS`.
|
||||
#define TINT_INSTANTIATE_CLASS_ID(CLASS) \
|
||||
template <> \
|
||||
const char ::tint::ClassID::Unique<CLASS>::token = 0
|
||||
const tint::ClassID tint::TypeInfo<CLASS>::class_id { \
|
||||
tint::ClassID::New() \
|
||||
}
|
||||
|
||||
/// TypeInfo holds type information for the type T.
|
||||
/// TINT_INSTANTIATE_CLASS_ID() must be defined in a .cpp file for each type
|
||||
/// `T`.
|
||||
template <typename T>
|
||||
struct TypeInfo {
|
||||
static const ClassID class_id;
|
||||
};
|
||||
|
||||
/// ClassID represents a unique, comparable identifier for a C++ type.
|
||||
class ClassID {
|
||||
private:
|
||||
/// Helper template that holds a single static field, which is used by Of()
|
||||
/// to obtain a unique identifier by taking the field's address.
|
||||
template <typename T>
|
||||
struct Unique {
|
||||
static const char token;
|
||||
};
|
||||
|
||||
public:
|
||||
/// @returns a new and unique ClassID
|
||||
static inline ClassID New() {
|
||||
static uintptr_t next(0);
|
||||
return ClassID(next++);
|
||||
}
|
||||
|
||||
/// @returns the unique ClassID for the type T.
|
||||
template <typename T>
|
||||
static ClassID Of() {
|
||||
// Take the address of a static variable to produce a unique identifier for
|
||||
// the type T.
|
||||
return ClassID{reinterpret_cast<uintptr_t>(&Unique<T>::token)};
|
||||
static inline ClassID Of() {
|
||||
return TypeInfo<T>::class_id;
|
||||
}
|
||||
|
||||
/// Equality operator
|
||||
|
@ -81,7 +89,7 @@ class CastableBase {
|
|||
|
||||
/// @returns true if this object is of, or derives from the class `TO`
|
||||
template <typename TO>
|
||||
bool Is() const {
|
||||
inline bool Is() const {
|
||||
using FROM = CastableBase;
|
||||
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
|
||||
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
|
||||
|
@ -146,13 +154,13 @@ class Castable : public BASE {
|
|||
/// @returns true if this object is of, or derives from a class with the
|
||||
/// ClassID `id`.
|
||||
/// @param id the ClassID to test for
|
||||
bool Is(ClassID id) const override {
|
||||
inline bool Is(ClassID id) const override {
|
||||
return ClassID::Of<CLASS>() == id || BASE::Is(id);
|
||||
}
|
||||
|
||||
/// @returns true if this object is of, or derives from the class `TO`
|
||||
template <typename TO>
|
||||
bool Is() const {
|
||||
inline bool Is() const {
|
||||
using FROM = Castable;
|
||||
constexpr const bool downcast = std::is_base_of<FROM, TO>::value;
|
||||
constexpr const bool upcast = std::is_base_of<TO, FROM>::value;
|
||||
|
|
Loading…
Reference in New Issue