Skip to content

Commit

Permalink
Fix base_nocompile_tests on Windows.
Browse files Browse the repository at this point in the history
The error message when downcasting a derived class that multiply
inherited from SupportsWeakPtr differed on Windows; instead of
producing a "no matching function" message, it produced the much more
confusing "use of member 'AsWeakPtrImpl' before its declaration is a
Microsoft extension [-Wmicrosoft-template]".

Change the way we detect the SupportsWeakPtr base to something that
produces the same error on all platforms (and, hopefully, one that is
clearer about its cause).

Bug: 1442625
Change-Id: I2de8d247c528a2afb36c3e65d4c4a2bca6f35bdc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4814291
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Auto-Submit: Peter Kasting <pkasting@chromium.org>
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1188633}
  • Loading branch information
pkasting authored and Chromium LUCI CQ committed Aug 26, 2023
1 parent 7227eb7 commit fe45cc9
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 14 deletions.
34 changes: 21 additions & 13 deletions base/memory/weak_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,29 +176,37 @@ class BASE_EXPORT WeakReferenceOwner {
class SupportsWeakPtrBase {
public:
// A safe static downcast of a WeakPtr<Base> to WeakPtr<Derived>. This
// conversion will only compile if there is exists a Base which inherits
// from SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper
// function that makes calling this easier.
// conversion will only compile if Derived singly inherits from
// SupportsWeakPtr<Base>. See base::AsWeakPtr() below for a helper function
// that makes calling this easier.
//
// Precondition: t != nullptr
template<typename Derived>
static WeakPtr<Derived> StaticAsWeakPtr(Derived* t) {
static_assert(
std::is_base_of<internal::SupportsWeakPtrBase, Derived>::value,
"AsWeakPtr argument must inherit from SupportsWeakPtr");
return AsWeakPtrImpl<Derived>(t);
}

private:
// This template function uses type inference to find a Base of Derived
// which is an instance of SupportsWeakPtr<Base>. We can then safely
// static_cast the Base* to a Derived*.
template <typename Derived, typename Base>
static WeakPtr<Derived> AsWeakPtrImpl(SupportsWeakPtr<Base>* t) {
WeakPtr<Base> weak = t->AsWeakPtr();
using Base = typename decltype(ExtractSinglyInheritedBase(t))::Base;
// Ensure SupportsWeakPtr<Base>::AsWeakPtr() is called even if the subclass
// hides or overloads it.
WeakPtr<Base> weak = static_cast<SupportsWeakPtr<Base>*>(t)->AsWeakPtr();
return WeakPtr<Derived>(weak.CloneWeakReference(),
static_cast<Derived*>(weak.ptr_));
}

private:
// This class can only be instantiated if the constructor argument inherits
// from SupportsWeakPtr<T> in exactly one way.
template <typename T>
struct ExtractSinglyInheritedBase;
template <typename T>
struct ExtractSinglyInheritedBase<SupportsWeakPtr<T>> {
using Base = T;
explicit ExtractSinglyInheritedBase(SupportsWeakPtr<T>*);
};
template <typename T>
ExtractSinglyInheritedBase(SupportsWeakPtr<T>*)
-> ExtractSinglyInheritedBase<SupportsWeakPtr<T>>;
};

// Forward declaration from safe_ptr.h.
Expand Down
2 changes: 1 addition & 1 deletion base/memory/weak_ptr_unittest.nc
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ void WontCompile() {
WeakPtr<Unrelated> ptr = AsWeakPtr(&f);
}

#elif defined(NCTEST_AMBIGUOUS_ANCESTORS) // [r"fatal error: no matching function for call to 'AsWeakPtrImpl'"]
#elif defined(NCTEST_AMBIGUOUS_ANCESTORS) // [r"fatal error: no viable constructor or deduction guide for deduction of template arguments of 'ExtractSinglyInheritedBase'"]

void WontCompile() {
MultiplyDerivedProducer f;
Expand Down

0 comments on commit fe45cc9

Please sign in to comment.