Bug 1448494 - store/expose uintptr_t -- WIP I will roll this into the other patches if accepted - r?froydnj
MozReview-Commit-ID: Brv0ENajgYw
--- a/dom/media/doctor/DecoderDoctorLogger.h
+++ b/dom/media/doctor/DecoderDoctorLogger.h
@@ -286,29 +286,30 @@ public:
}
template<typename Subject>
static void LogConstruction(NonDereferenceable<const Subject> aSubject)
{
using Traits = DDLoggedTypeTraits<Subject>;
if (!Traits::HasBase::value) {
Log(DDLoggedTypeTraits<Subject>::Name(),
- aSubject.value(),
+ reinterpret_cast<const void*>(aSubject.value()),
DDLogCategory::_Construction,
"",
DDLogValue{ DDNoValue{} });
} else {
Log(DDLoggedTypeTraits<Subject>::Name(),
- aSubject.value(),
+ reinterpret_cast<const void*>(aSubject.value()),
DDLogCategory::_DerivedConstruction,
"",
DDLogValue{ DDLogObject{
DDLoggedTypeTraits<typename Traits::BaseType>::Name(),
- NonDereferenceable<const typename Traits::BaseType>(aSubject)
- .value() } });
+ reinterpret_cast<const void*>(
+ NonDereferenceable<const typename Traits::BaseType>(aSubject)
+ .value()) } });
}
}
template<typename Subject>
static void LogConstruction(const Subject* aSubject)
{
LogConstruction(NonDereferenceable<const Subject>(aSubject));
}
@@ -322,17 +323,17 @@ public:
"",
DDLogValue{ DDNoValue{} });
}
template<typename Subject>
static void LogDestruction(NonDereferenceable<const Subject> aSubject)
{
Log(DDLoggedTypeTraits<Subject>::Name(),
- aSubject.value(),
+ reinterpret_cast<const void*>(aSubject.value()),
DDLogCategory::_Destruction,
"",
DDLogValue{ DDNoValue{} });
}
template<typename Subject>
static void LogDestruction(const Subject* aSubject)
{
--- a/mfbt/NonDereferenceable.h
+++ b/mfbt/NonDereferenceable.h
@@ -7,16 +7,18 @@
#ifndef mozilla_NonDereferenceable_h
#define mozilla_NonDereferenceable_h
/* A pointer wrapper indicating that the pointer should not be dereferenced. */
#include "mozilla/Attributes.h"
#include "mozilla/TypeTraits.h"
+#include <cstdint>
+
// Macro indicating that a function manipulates a pointer that will not be
// dereferenced, and therefore there is no need to check the object.
#if defined(__clang__)
#define NO_POINTEE_CHECKS __attribute__((no_sanitize("vptr")))
#else
#define NO_POINTEE_CHECKS /* nothing */
#endif
@@ -113,22 +115,19 @@ public:
// at these lines:
T& operator*() = delete; // Cannot dereference NonDereferenceable!
T* operator->() = delete; // Cannot dereference NonDereferenceable!
// Null check.
NO_POINTEE_CHECKS
explicit operator bool() const { return !!mPtr; }
- // Extract the pointer value, untyped, but with the same constness as T.
- // Safe to use as a pure pointer value for e.g. logging purposes.
- // Please do not cast this value back to T*.
- using Void = typename Conditional<IsConst<T>::value, const void, void>::Type;
+ // Extract the pointer value, untyped.
NO_POINTEE_CHECKS
- Void* value() const { return static_cast<Void*>(mPtr); }
+ uintptr_t value() const { return reinterpret_cast<uintptr_t>(mPtr); }
private:
// Let other NonDereferenceable templates access mPtr, to permit construction/
// assignment from compatible pointer types.
template<typename> friend class NonDereferenceable;
T* MOZ_NON_OWNING_REF mPtr;
};
--- a/mfbt/tests/TestNonDereferenceable.cpp
+++ b/mfbt/tests/TestNonDereferenceable.cpp
@@ -23,41 +23,41 @@ TestNonDereferenceableSimple()
CHECK(!nd0.value());
int i = 1;
int i2 = 2;
// Construction with pointer.
NonDereferenceable<int> nd1(&i);
CHECK(!!nd1);
- CHECK(nd1.value() == static_cast<void*>(&i));
+ CHECK(nd1.value() == reinterpret_cast<uintptr_t>(&i));
// Assignment with pointer.
nd1 = &i2;
- CHECK(nd1.value() == static_cast<void*>(&i2));
+ CHECK(nd1.value() == reinterpret_cast<uintptr_t>(&i2));
// Copy-construction.
NonDereferenceable<int> nd2(nd1);
- CHECK(nd2.value() == static_cast<void*>(&i2));
+ CHECK(nd2.value() == reinterpret_cast<uintptr_t>(&i2));
// Copy-assignment.
nd2 = nd0;
CHECK(!nd2.value());
// Move-construction.
NonDereferenceable<int> nd3{ NonDereferenceable<int>(&i) };
- CHECK(nd3.value() == static_cast<void*>(&i));
+ CHECK(nd3.value() == reinterpret_cast<uintptr_t>(&i));
// Move-assignment.
nd3 = Move(nd1);
- CHECK(nd3.value() == static_cast<void*>(&i2));
+ CHECK(nd3.value() == reinterpret_cast<uintptr_t>(&i2));
// Note: Not testing nd1's value because we don't want to assume what state
// it is left in after move. But at least it should be reusable:
nd1 = &i;
- CHECK(nd1.value() == static_cast<void*>(&i));
+ CHECK(nd1.value() == reinterpret_cast<uintptr_t>(&i));
}
void
TestNonDereferenceableHierarchy()
{
struct Base1
{
// Member variable, to make sure Base1 is not empty.
@@ -73,43 +73,43 @@ TestNonDereferenceableHierarchy()
{
};
Derived d;
// Construct NonDereferenceable from raw pointer.
NonDereferenceable<Derived> ndd = NonDereferenceable<Derived>(&d);
CHECK(ndd);
- CHECK(ndd.value() == static_cast<void*>(&d));
+ CHECK(ndd.value() == reinterpret_cast<uintptr_t>(&d));
// Cast Derived to Base1.
NonDereferenceable<Base1> ndb1 = ndd;
CHECK(ndb1);
- CHECK(ndb1.value() == static_cast<void*>(static_cast<Base1*>(&d)));
+ CHECK(ndb1.value() == reinterpret_cast<uintptr_t>(static_cast<Base1*>(&d)));
// Cast Base1 back to Derived.
NonDereferenceable<Derived> nddb1 = ndb1;
- CHECK(nddb1.value() == static_cast<void*>(&d));
+ CHECK(nddb1.value() == reinterpret_cast<uintptr_t>(&d));
// Cast Derived to Base2.
NonDereferenceable<Base2> ndb2 = ndd;
CHECK(ndb2);
- CHECK(ndb2.value() == static_cast<void*>(static_cast<Base2*>(&d)));
+ CHECK(ndb2.value() == reinterpret_cast<uintptr_t>(static_cast<Base2*>(&d)));
// Sanity check that Base2 should be offset from the start of Derived.
CHECK(ndb2.value() != ndd.value());
// Cast Base2 back to Derived.
NonDereferenceable<Derived> nddb2 = ndb2;
- CHECK(nddb2.value() == static_cast<void*>(&d));
+ CHECK(nddb2.value() == reinterpret_cast<uintptr_t>(&d));
// Note that it's not possible to jump between bases, as they're not obviously
// related, i.e.: `NonDereferenceable<Base2> ndb22 = ndb1;` doesn't compile.
// However it's possible to explicitly navigate through the derived object:
NonDereferenceable<Base2> ndb22 = NonDereferenceable<Derived>(ndb1);
- CHECK(ndb22.value() == static_cast<void*>(static_cast<Base2*>(&d)));
+ CHECK(ndb22.value() == reinterpret_cast<uintptr_t>(static_cast<Base2*>(&d)));
// Handling nullptr; should stay nullptr even for offset bases.
ndd = nullptr;
CHECK(!ndd);
CHECK(!ndd.value());
ndb1 = ndd;
CHECK(!ndb1);
CHECK(!ndb1.value());
@@ -143,49 +143,49 @@ TestNonDereferenceableCRTP()
{
};
using Base1 = Derived::CRTPBase<Derived, 1>;
using Base2 = Derived::CRTPBase<Derived, 2>;
Derived d;
// Verify that base constructors have correctly captured the address of the
// (at the time still incomplete) derived object.
- CHECK(d.Base1::mDerived.value() == static_cast<void*>(&d));
- CHECK(d.Base2::mDerived.value() == static_cast<void*>(&d));
+ CHECK(d.Base1::mDerived.value() == reinterpret_cast<uintptr_t>(&d));
+ CHECK(d.Base2::mDerived.value() == reinterpret_cast<uintptr_t>(&d));
// Construct NonDereferenceable from raw pointer.
NonDereferenceable<Derived> ndd = NonDereferenceable<Derived>(&d);
CHECK(ndd);
- CHECK(ndd.value() == static_cast<void*>(&d));
+ CHECK(ndd.value() == reinterpret_cast<uintptr_t>(&d));
// Cast Derived to Base1.
NonDereferenceable<Base1> ndb1 = ndd;
CHECK(ndb1);
- CHECK(ndb1.value() == static_cast<void*>(static_cast<Base1*>(&d)));
+ CHECK(ndb1.value() == reinterpret_cast<uintptr_t>(static_cast<Base1*>(&d)));
// Cast Base1 back to Derived.
NonDereferenceable<Derived> nddb1 = ndb1;
- CHECK(nddb1.value() == static_cast<void*>(&d));
+ CHECK(nddb1.value() == reinterpret_cast<uintptr_t>(&d));
// Cast Derived to Base2.
NonDereferenceable<Base2> ndb2 = ndd;
CHECK(ndb2);
- CHECK(ndb2.value() == static_cast<void*>(static_cast<Base2*>(&d)));
+ CHECK(ndb2.value() == reinterpret_cast<uintptr_t>(static_cast<Base2*>(&d)));
// Sanity check that Base2 should be offset from the start of Derived.
CHECK(ndb2.value() != ndd.value());
// Cast Base2 back to Derived.
NonDereferenceable<Derived> nddb2 = ndb2;
- CHECK(nddb2.value() == static_cast<void*>(&d));
+ CHECK(nddb2.value() == reinterpret_cast<uintptr_t>(&d));
// Note that it's not possible to jump between bases, as they're not obviously
// related, i.e.: `NonDereferenceable<Base2> ndb22 = ndb1;` doesn't compile.
// However it's possible to explicitly navigate through the derived object:
NonDereferenceable<Base2> ndb22 = NonDereferenceable<Derived>(ndb1);
- CHECK(ndb22.value() == static_cast<void*>(static_cast<Base2*>(&d)));
+ CHECK(ndb22.value() == reinterpret_cast<uintptr_t>(static_cast<Base2*>(&d)));
}
int
main()
{
TestNonDereferenceableSimple();
TestNonDereferenceableHierarchy();
TestNonDereferenceableCRTP();