2014-06-30 19:39:45 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
1998-12-17 22:12:45 +03:00
|
|
|
|
|
|
|
#ifndef nsCOMPtr_h___
|
|
|
|
#define nsCOMPtr_h___
|
|
|
|
|
1999-11-08 14:43:11 +03:00
|
|
|
/*
|
2014-08-25 23:17:20 +04:00
|
|
|
* Having problems?
|
|
|
|
*
|
|
|
|
* See the User Manual at:
|
|
|
|
* http://www.mozilla.org/projects/xpcom/nsCOMPtr.html
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* nsCOMPtr
|
|
|
|
* better than a raw pointer
|
|
|
|
* for owning objects
|
|
|
|
* -- scc
|
|
|
|
*/
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-12-31 19:42:05 +03:00
|
|
|
#include "mozilla/AlreadyAddRefed.h"
|
2013-04-04 06:33:34 +04:00
|
|
|
#include "mozilla/Assertions.h"
|
2014-07-29 22:41:45 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
2014-03-15 23:00:17 +04:00
|
|
|
#include "mozilla/Move.h"
|
2014-07-29 22:41:45 +04:00
|
|
|
#include "mozilla/TypeTraits.h"
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2015-02-10 01:34:50 +03:00
|
|
|
#include "nsDebug.h" // for |NS_ASSERTION|
|
2014-03-17 20:20:47 +04:00
|
|
|
#include "nsISupportsUtils.h" // for |nsresult|, |NS_ADDREF|, |NS_GET_TEMPLATE_IID| et al
|
2015-10-18 08:24:48 +03:00
|
|
|
#include "mozilla/RefPtr.h"
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2012-11-15 11:32:39 +04:00
|
|
|
#include "nsCycleCollectionNoteChild.h"
|
|
|
|
|
1999-02-11 04:34:07 +03:00
|
|
|
|
1998-12-18 06:45:44 +03:00
|
|
|
/*
|
2014-08-25 23:17:20 +04:00
|
|
|
* WARNING: This file defines several macros for internal use only. These
|
|
|
|
* macros begin with the prefix |NSCAP_|. Do not use these macros in your own
|
|
|
|
* code. They are for internal use only for cross-platform compatibility, and
|
|
|
|
* are subject to change without notice.
|
|
|
|
*/
|
1998-12-18 06:45:44 +03:00
|
|
|
|
|
|
|
|
1999-03-03 02:08:54 +03:00
|
|
|
#ifdef _MSC_VER
|
2014-08-25 23:17:20 +04:00
|
|
|
// Under VC++, we win by inlining StartAssignment.
|
1999-06-02 05:59:28 +04:00
|
|
|
#define NSCAP_FEATURE_INLINE_STARTASSIGNMENT
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Also under VC++, at the highest warning level, we are overwhelmed with
|
|
|
|
// warnings about (unused) inline functions being removed. This is to be
|
|
|
|
// expected with templates, so we disable the warning.
|
1999-11-05 06:31:04 +03:00
|
|
|
#pragma warning( disable: 4514 )
|
1998-12-17 22:12:45 +03:00
|
|
|
#endif
|
|
|
|
|
2003-10-23 03:29:00 +04:00
|
|
|
#define NSCAP_FEATURE_USE_BASE
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2012-06-25 23:59:42 +04:00
|
|
|
#ifdef DEBUG
|
1999-08-23 14:07:16 +04:00
|
|
|
#define NSCAP_FEATURE_TEST_DONTQUERY_CASES
|
2003-10-23 03:29:00 +04:00
|
|
|
#undef NSCAP_FEATURE_USE_BASE
|
1999-07-15 07:59:09 +04:00
|
|
|
#endif
|
|
|
|
|
2012-12-18 22:22:28 +04:00
|
|
|
#ifdef __GNUC__
|
2003-11-13 10:37:14 +03:00
|
|
|
// Our use of nsCOMPtr_base::mRawPtr violates the C++ standard's aliasing
|
|
|
|
// rules. Mark it with the may_alias attribute so that gcc 3.3 and higher
|
|
|
|
// don't reorder instructions based on aliasing assumptions for
|
|
|
|
// this variable. Fortunately, gcc versions < 3.3 do not do any
|
|
|
|
// optimizations that break nsCOMPtr.
|
|
|
|
|
|
|
|
#define NS_MAY_ALIAS_PTR(t) t* __attribute__((__may_alias__))
|
|
|
|
#else
|
|
|
|
#define NS_MAY_ALIAS_PTR(t) t*
|
2003-09-25 09:43:42 +04:00
|
|
|
#endif
|
|
|
|
|
2003-10-23 06:29:47 +04:00
|
|
|
#if defined(NSCAP_DISABLE_DEBUG_PTR_TYPES)
|
2003-10-23 03:29:00 +04:00
|
|
|
#define NSCAP_FEATURE_USE_BASE
|
1999-06-30 01:09:59 +04:00
|
|
|
#endif
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
/*
|
|
|
|
* The following three macros (NSCAP_ADDREF, NSCAP_RELEASE, and
|
|
|
|
* NSCAP_LOG_ASSIGNMENT) allow external clients the ability to add logging or
|
|
|
|
* other interesting debug facilities. In fact, if you want |nsCOMPtr| to
|
|
|
|
* participate in the standard logging facility, you provide
|
|
|
|
* (e.g., in "nsISupportsImpl.h") suitable definitions
|
|
|
|
*
|
|
|
|
* #define NSCAP_ADDREF(this, ptr) NS_ADDREF(ptr)
|
|
|
|
* #define NSCAP_RELEASE(this, ptr) NS_RELEASE(ptr)
|
|
|
|
*/
|
2000-06-08 08:52:39 +04:00
|
|
|
|
|
|
|
#ifndef NSCAP_ADDREF
|
2000-06-10 13:58:13 +04:00
|
|
|
#define NSCAP_ADDREF(this, ptr) (ptr)->AddRef()
|
2000-06-08 08:52:39 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef NSCAP_RELEASE
|
2000-06-10 13:58:13 +04:00
|
|
|
#define NSCAP_RELEASE(this, ptr) (ptr)->Release()
|
2000-06-08 08:52:39 +04:00
|
|
|
#endif
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Clients can define |NSCAP_LOG_ASSIGNMENT| to perform logging.
|
2000-06-08 08:52:39 +04:00
|
|
|
#ifdef NSCAP_LOG_ASSIGNMENT
|
2014-08-25 23:17:20 +04:00
|
|
|
// Remember that |NSCAP_LOG_ASSIGNMENT| was defined by some client so that we
|
|
|
|
// know to instantiate |~nsGetterAddRefs| in turn to note the external
|
|
|
|
// assignment into the |nsCOMPtr|.
|
2000-06-08 08:52:39 +04:00
|
|
|
#define NSCAP_LOG_EXTERNAL_ASSIGNMENT
|
1998-12-22 02:26:39 +03:00
|
|
|
#else
|
2000-06-10 13:58:13 +04:00
|
|
|
// ...otherwise, just strip it out of the code
|
2003-02-25 18:53:36 +03:00
|
|
|
#define NSCAP_LOG_ASSIGNMENT(this, ptr)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef NSCAP_LOG_RELEASE
|
|
|
|
#define NSCAP_LOG_RELEASE(this, ptr)
|
1998-12-22 02:26:39 +03:00
|
|
|
#endif
|
|
|
|
|
2014-03-15 23:00:16 +04:00
|
|
|
namespace mozilla {
|
2015-04-19 15:28:50 +03:00
|
|
|
template<class T> class OwningNonNull;
|
2014-03-15 23:00:16 +04:00
|
|
|
} // namespace mozilla
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
|
|
|
inline already_AddRefed<T>
|
|
|
|
dont_AddRef(T* aRawPtr)
|
|
|
|
{
|
|
|
|
return already_AddRefed<T>(aRawPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline already_AddRefed<T>&&
|
|
|
|
dont_AddRef(already_AddRefed<T>&& aAlreadyAddRefedPtr)
|
|
|
|
{
|
2018-05-30 22:15:35 +03:00
|
|
|
return std::move(aAlreadyAddRefedPtr);
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
|
2000-03-18 02:08:18 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
/*
|
2014-08-25 23:17:20 +04:00
|
|
|
* An nsCOMPtr_helper transforms commonly called getters into typesafe forms
|
|
|
|
* that are more convenient to call, and more efficient to use with |nsCOMPtr|s.
|
|
|
|
* Good candidates for helpers are |QueryInterface()|, |CreateInstance()|, etc.
|
|
|
|
*
|
|
|
|
* Here are the rules for a helper:
|
|
|
|
* - it implements |operator()| to produce an interface pointer
|
|
|
|
* - (except for its name) |operator()| is a valid [XP]COM `getter'
|
|
|
|
* - the interface pointer that it returns is already |AddRef()|ed (as from
|
|
|
|
* any good getter)
|
|
|
|
* - it matches the type requested with the supplied |nsIID| argument
|
|
|
|
* - its constructor provides an optional |nsresult*| that |operator()| can
|
|
|
|
* fill in with an error when it is executed
|
|
|
|
*
|
|
|
|
* See |class nsGetInterface| for an example.
|
|
|
|
*/
|
2015-01-18 23:17:26 +03:00
|
|
|
class MOZ_STACK_CLASS nsCOMPtr_helper
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
virtual nsresult NS_FASTCALL operator()(const nsIID&, void**) const = 0;
|
|
|
|
};
|
1999-10-31 03:35:48 +03:00
|
|
|
|
2004-03-05 02:04:27 +03:00
|
|
|
/*
|
2014-08-25 23:17:20 +04:00
|
|
|
* nsQueryInterface could have been implemented as an nsCOMPtr_helper to avoid
|
|
|
|
* adding specialized machinery in nsCOMPtr, but do_QueryInterface is called
|
|
|
|
* often enough that the codesize savings are big enough to warrant the
|
|
|
|
* specialcasing.
|
|
|
|
*/
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
class MOZ_STACK_CLASS nsQueryInterfaceISupports
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
nsQueryInterfaceISupports(nsISupports* aRawPtr) : mRawPtr(aRawPtr) {}
|
2004-03-05 02:04:27 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
|
2004-03-05 02:04:27 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
private:
|
2014-12-24 05:17:50 +03:00
|
|
|
nsISupports* MOZ_OWNING_REF mRawPtr;
|
2014-06-27 05:35:39 +04:00
|
|
|
};
|
2004-03-05 02:04:27 +03:00
|
|
|
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
#ifndef NSCAP_FEATURE_USE_BASE
|
|
|
|
template<typename T>
|
|
|
|
class MOZ_STACK_CLASS nsQueryInterface final : public nsQueryInterfaceISupports
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit
|
|
|
|
nsQueryInterface(T* aRawPtr) : nsQueryInterfaceISupports(aRawPtr) {}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aAnswer) const {
|
|
|
|
return nsQueryInterfaceISupports::operator()(aIID, aAnswer);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // #ifndef NSCAP_FEATURE_USE_BASE
|
|
|
|
|
2018-10-04 22:16:30 +03:00
|
|
|
class MOZ_STACK_CLASS nsQueryInterfaceISupportsWithError
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
public:
|
2018-10-04 22:16:30 +03:00
|
|
|
nsQueryInterfaceISupportsWithError(nsISupports* aRawPtr, nsresult* aError)
|
2014-06-27 05:35:39 +04:00
|
|
|
: mRawPtr(aRawPtr)
|
|
|
|
, mErrorPtr(aError)
|
1999-11-08 14:43:11 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
private:
|
2014-12-24 05:17:50 +03:00
|
|
|
nsISupports* MOZ_OWNING_REF mRawPtr;
|
2014-06-27 05:35:39 +04:00
|
|
|
nsresult* mErrorPtr;
|
|
|
|
};
|
1999-02-17 04:58:25 +03:00
|
|
|
|
2018-10-04 22:16:30 +03:00
|
|
|
#ifndef NSCAP_FEATURE_USE_BASE
|
|
|
|
template<typename T>
|
|
|
|
class MOZ_STACK_CLASS nsQueryInterfaceWithError final : public nsQueryInterfaceISupportsWithError
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit
|
|
|
|
nsQueryInterfaceWithError(T* aRawPtr, nsresult* aError)
|
|
|
|
: nsQueryInterfaceISupportsWithError(aRawPtr, aError)
|
|
|
|
{}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID& aIID, void** aAnswer) const {
|
|
|
|
return nsQueryInterfaceISupportsWithError::operator()(aIID, aAnswer);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif // #ifndef NSCAP_FEATURE_USE_BASE
|
|
|
|
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
|
|
|
|
inline nsQueryInterfaceISupports
|
2014-06-27 05:35:39 +04:00
|
|
|
do_QueryInterface(nsISupports* aRawPtr)
|
|
|
|
{
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
return nsQueryInterfaceISupports(aRawPtr);
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
2004-03-05 02:04:27 +03:00
|
|
|
|
2018-10-04 22:16:30 +03:00
|
|
|
inline nsQueryInterfaceISupportsWithError
|
|
|
|
do_QueryInterface(nsISupports* aRawPtr, nsresult* aError)
|
|
|
|
{
|
|
|
|
return nsQueryInterfaceISupportsWithError(aRawPtr, aError);
|
|
|
|
}
|
|
|
|
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
#else
|
|
|
|
|
|
|
|
namespace mozilla {
|
|
|
|
// PointedToType<> is needed so that do_QueryInterface() will work with a
|
|
|
|
// variety of smart pointer types in addition to raw pointers. These types
|
|
|
|
// include RefPtr<>, nsCOMPtr<>, and OwningNonNull<>.
|
|
|
|
template<class T>
|
|
|
|
using PointedToType = typename mozilla::RemovePointer<decltype(&*mozilla::DeclVal<T>())>::Type;
|
|
|
|
} // namespace mozilla
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline nsQueryInterface<mozilla::PointedToType<T>>
|
|
|
|
do_QueryInterface(T aPtr)
|
|
|
|
{
|
|
|
|
return nsQueryInterface<mozilla::PointedToType<T>>(aPtr);
|
|
|
|
}
|
|
|
|
|
2018-10-04 22:16:30 +03:00
|
|
|
template<class T>
|
|
|
|
inline nsQueryInterfaceWithError<mozilla::PointedToType<T>>
|
|
|
|
do_QueryInterface(T aRawPtr, nsresult* aError)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2018-10-04 22:16:30 +03:00
|
|
|
return nsQueryInterfaceWithError<mozilla::PointedToType<T>>(aRawPtr, aError);
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
2018-10-04 22:16:30 +03:00
|
|
|
#endif // ! #ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
|
1999-02-17 04:58:25 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
|
|
|
inline void
|
|
|
|
do_QueryInterface(already_AddRefed<T>&)
|
|
|
|
{
|
|
|
|
// This signature exists solely to _stop_ you from doing the bad thing.
|
2014-08-25 23:17:20 +04:00
|
|
|
// Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
|
|
|
|
// someone else is an automatic leak. See bug 8221.
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
2000-03-23 01:52:17 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
|
|
|
inline void
|
|
|
|
do_QueryInterface(already_AddRefed<T>&, nsresult*)
|
|
|
|
{
|
|
|
|
// This signature exists solely to _stop_ you from doing the bad thing.
|
2014-08-25 23:17:20 +04:00
|
|
|
// Saying |do_QueryInterface()| on a pointer that is not otherwise owned by
|
|
|
|
// someone else is an automatic leak. See bug 8221.
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
2000-03-18 02:08:18 +03:00
|
|
|
|
1999-08-03 11:21:39 +04:00
|
|
|
|
2004-11-25 01:48:45 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Using servicemanager with COMPtrs
|
2015-04-20 23:58:15 +03:00
|
|
|
class nsGetServiceByCID final
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
public:
|
|
|
|
explicit nsGetServiceByCID(const nsCID& aCID) : mCID(aCID) {}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const nsCID& mCID;
|
2004-11-25 01:48:45 +03:00
|
|
|
};
|
|
|
|
|
2015-04-20 23:58:15 +03:00
|
|
|
class nsGetServiceByCIDWithError final
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
public:
|
|
|
|
nsGetServiceByCIDWithError(const nsCID& aCID, nsresult* aErrorPtr)
|
|
|
|
: mCID(aCID)
|
|
|
|
, mErrorPtr(aErrorPtr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const nsCID& mCID;
|
|
|
|
nsresult* mErrorPtr;
|
2004-11-25 01:48:45 +03:00
|
|
|
};
|
|
|
|
|
2015-04-20 23:58:15 +03:00
|
|
|
class nsGetServiceByContractID final
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
public:
|
|
|
|
explicit nsGetServiceByContractID(const char* aContractID)
|
|
|
|
: mContractID(aContractID)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const char* mContractID;
|
2004-11-25 01:48:45 +03:00
|
|
|
};
|
|
|
|
|
2015-04-20 23:58:15 +03:00
|
|
|
class nsGetServiceByContractIDWithError final
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
public:
|
|
|
|
nsGetServiceByContractIDWithError(const char* aContractID, nsresult* aErrorPtr)
|
|
|
|
: mContractID(aContractID)
|
|
|
|
, mErrorPtr(aErrorPtr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID&, void**) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const char* mContractID;
|
|
|
|
nsresult* mErrorPtr;
|
2004-11-25 01:48:45 +03:00
|
|
|
};
|
1999-08-03 11:21:39 +04:00
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
class nsIWeakReference;
|
|
|
|
|
|
|
|
// Weak references
|
|
|
|
class MOZ_STACK_CLASS nsQueryReferent final
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
nsQueryReferent(nsIWeakReference* aWeakPtr, nsresult* aError)
|
|
|
|
: mWeakPtr(aWeakPtr)
|
|
|
|
, mErrorPtr(aError)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult NS_FASTCALL operator()(const nsIID& aIID, void**) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsIWeakReference* MOZ_NON_OWNING_REF mWeakPtr;
|
|
|
|
nsresult* mErrorPtr;
|
|
|
|
};
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
/**
|
|
|
|
* Factors implementation for all template versions of nsCOMPtr.
|
|
|
|
*
|
|
|
|
* Here's the way people normally do things like this:
|
|
|
|
*
|
|
|
|
* template<class T> class Foo { ... };
|
|
|
|
* template<> class Foo<void*> { ... };
|
|
|
|
* template<class T> class Foo<T*> : private Foo<void*> { ... };
|
|
|
|
*/
|
2014-06-27 05:35:39 +04:00
|
|
|
class nsCOMPtr_base
|
|
|
|
{
|
|
|
|
public:
|
2016-11-10 06:19:56 +03:00
|
|
|
explicit nsCOMPtr_base(nsISupports* aRawPtr = nullptr) : mRawPtr(aRawPtr) {}
|
2014-06-27 05:35:39 +04:00
|
|
|
|
2014-08-28 02:47:27 +04:00
|
|
|
NS_CONSTRUCTOR_FASTCALL ~nsCOMPtr_base()
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_RELEASE(this, mRawPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_with_AddRef(nsISupports*);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
assign_from_qi(const nsQueryInterfaceISupports, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2018-10-04 22:16:30 +03:00
|
|
|
assign_from_qi_with_error(const nsQueryInterfaceISupportsWithError&, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid_with_error(const nsGetServiceByContractIDWithError&,
|
|
|
|
const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void NS_FASTCALL
|
2017-08-25 03:04:31 +03:00
|
|
|
assign_from_query_referent(const nsQueryReferent&, const nsIID&);
|
|
|
|
void NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
|
2014-08-28 02:47:27 +04:00
|
|
|
void** NS_FASTCALL
|
2014-06-27 05:35:39 +04:00
|
|
|
begin_assignment();
|
|
|
|
|
|
|
|
protected:
|
2014-12-24 05:17:50 +03:00
|
|
|
NS_MAY_ALIAS_PTR(nsISupports) MOZ_OWNING_REF mRawPtr;
|
2014-06-27 05:35:39 +04:00
|
|
|
|
|
|
|
void assign_assuming_AddRef(nsISupports* aNewPtr)
|
1999-02-17 04:58:25 +03:00
|
|
|
{
|
2014-08-25 23:17:20 +04:00
|
|
|
// |AddRef()|ing the new value (before entering this function) before
|
|
|
|
// |Release()|ing the old lets us safely ignore the self-assignment case.
|
|
|
|
// We must, however, be careful only to |Release()| _after_ doing the
|
|
|
|
// assignment, in case the |Release()| leads to our _own_ destruction,
|
|
|
|
// which would, in turn, cause an incorrect second |Release()| of our old
|
|
|
|
// pointer. Thank <waterson@netscape.com> for discovering this.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsISupports* oldPtr = mRawPtr;
|
|
|
|
mRawPtr = aNewPtr;
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
|
|
|
|
NSCAP_LOG_RELEASE(this, oldPtr);
|
|
|
|
if (oldPtr) {
|
|
|
|
NSCAP_RELEASE(this, oldPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// template<class T> class nsGetterAddRefs;
|
|
|
|
|
2015-08-12 18:43:10 +03:00
|
|
|
// Helper for assert_validity method
|
|
|
|
template<class T>
|
|
|
|
char (&TestForIID(decltype(&NS_GET_TEMPLATE_IID(T))))[2];
|
|
|
|
template<class T>
|
|
|
|
char TestForIID(...);
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
2017-08-08 19:48:53 +03:00
|
|
|
class MOZ_IS_REFPTR nsCOMPtr final
|
2003-10-23 03:29:00 +04:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
2014-06-27 05:35:39 +04:00
|
|
|
: private nsCOMPtr_base
|
1999-07-15 07:59:09 +04:00
|
|
|
#endif
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2000-03-18 08:17:46 +03:00
|
|
|
|
2003-10-23 03:29:00 +04:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
#define NSCAP_CTOR_BASE(x) nsCOMPtr_base(x)
|
|
|
|
#else
|
|
|
|
#define NSCAP_CTOR_BASE(x) mRawPtr(x)
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
private:
|
|
|
|
void assign_with_AddRef(nsISupports*);
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
template<typename U>
|
|
|
|
void assign_from_qi(const nsQueryInterface<U>, const nsIID&);
|
2018-10-04 22:16:30 +03:00
|
|
|
template<typename U>
|
|
|
|
void assign_from_qi_with_error(const nsQueryInterfaceWithError<U>&, const nsIID&);
|
2014-06-27 05:35:39 +04:00
|
|
|
void assign_from_gs_cid(const nsGetServiceByCID, const nsIID&);
|
|
|
|
void assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError&,
|
|
|
|
const nsIID&);
|
|
|
|
void assign_from_gs_contractid(const nsGetServiceByContractID, const nsIID&);
|
|
|
|
void assign_from_gs_contractid_with_error(
|
|
|
|
const nsGetServiceByContractIDWithError&, const nsIID&);
|
2017-08-25 03:04:31 +03:00
|
|
|
void assign_from_query_referent(const nsQueryReferent&, const nsIID&);
|
2014-06-27 05:35:39 +04:00
|
|
|
void assign_from_helper(const nsCOMPtr_helper&, const nsIID&);
|
|
|
|
void** begin_assignment();
|
|
|
|
|
|
|
|
void assign_assuming_AddRef(T* aNewPtr)
|
|
|
|
{
|
|
|
|
T* oldPtr = mRawPtr;
|
|
|
|
mRawPtr = aNewPtr;
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aNewPtr);
|
|
|
|
NSCAP_LOG_RELEASE(this, oldPtr);
|
|
|
|
if (oldPtr) {
|
|
|
|
NSCAP_RELEASE(this, oldPtr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-12-24 05:17:50 +03:00
|
|
|
T* MOZ_OWNING_REF mRawPtr;
|
1999-07-15 07:59:09 +04:00
|
|
|
#endif
|
|
|
|
|
2015-08-12 18:43:10 +03:00
|
|
|
void assert_validity()
|
|
|
|
{
|
|
|
|
static_assert(1 < sizeof(TestForIID<T>(nullptr)), "nsCOMPtr only works "
|
2015-10-18 08:24:48 +03:00
|
|
|
"for types with IIDs. Either use RefPtr; add an IID to "
|
2015-08-12 18:43:10 +03:00
|
|
|
"your type with NS_DECLARE_STATIC_IID_ACCESSOR/"
|
|
|
|
"NS_DEFINE_STATIC_IID_ACCESSOR; or make the nsCOMPtr point "
|
|
|
|
"to a base class with an IID.");
|
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
public:
|
|
|
|
typedef T element_type;
|
|
|
|
|
2003-10-23 03:29:00 +04:00
|
|
|
#ifndef NSCAP_FEATURE_USE_BASE
|
2014-06-27 05:35:39 +04:00
|
|
|
~nsCOMPtr()
|
|
|
|
{
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_RELEASE(this, mRawPtr);
|
|
|
|
}
|
|
|
|
}
|
1999-05-11 00:48:43 +04:00
|
|
|
#endif
|
|
|
|
|
1999-06-30 01:09:59 +04:00
|
|
|
#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
|
2014-06-27 05:35:39 +04:00
|
|
|
void Assert_NoQueryNeeded()
|
|
|
|
{
|
|
|
|
if (mRawPtr) {
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
// This can't be defined in terms of do_QueryInterface because
|
|
|
|
// that bans casts from a class to itself.
|
|
|
|
void* out = nullptr;
|
|
|
|
mRawPtr->QueryInterface(NS_GET_TEMPLATE_IID(T), &out);
|
|
|
|
T* query_result = static_cast<T*>(out);
|
|
|
|
MOZ_ASSERT(query_result == mRawPtr, "QueryInterface needed");
|
|
|
|
NS_RELEASE(query_result);
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
}
|
1999-08-23 14:07:16 +04:00
|
|
|
|
2001-07-31 23:05:34 +04:00
|
|
|
#define NSCAP_ASSERT_NO_QUERY_NEEDED() Assert_NoQueryNeeded();
|
1999-07-15 07:59:09 +04:00
|
|
|
#else
|
2001-07-31 23:05:34 +04:00
|
|
|
#define NSCAP_ASSERT_NO_QUERY_NEEDED()
|
1999-06-30 01:09:59 +04:00
|
|
|
#endif
|
|
|
|
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// Constructors
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr()
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2016-11-10 23:57:38 +03:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
|
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
|
|
|
{
|
|
|
|
assert_validity();
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr(const nsCOMPtr<T>& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
|
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-06-27 05:35:39 +04:00
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, mRawPtr);
|
|
|
|
}
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
|
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2018-10-02 03:54:16 +03:00
|
|
|
template <class U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr<U>& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.get())
|
|
|
|
{
|
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U should be a subclass of T");
|
|
|
|
assert_validity();
|
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, mRawPtr);
|
|
|
|
}
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.get());
|
|
|
|
}
|
|
|
|
|
2016-09-17 02:49:07 +03:00
|
|
|
nsCOMPtr(nsCOMPtr<T>&& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.mRawPtr)
|
|
|
|
{
|
|
|
|
assert_validity();
|
|
|
|
aSmartPtr.mRawPtr = nullptr;
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
|
|
|
}
|
|
|
|
|
2018-10-02 03:54:16 +03:00
|
|
|
template <class U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(nsCOMPtr<U>&& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.forget().template downcast<T>().take())
|
|
|
|
{
|
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U should be a subclass of T");
|
|
|
|
assert_validity();
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(T* aRawPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aRawPtr)
|
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-06-27 05:35:39 +04:00
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, mRawPtr);
|
|
|
|
}
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.take())
|
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-06-27 05:35:39 +04:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |otherComPtr.forget()|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<T>&& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(aSmartPtr.take())
|
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-06-27 05:35:39 +04:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
2012-11-15 11:32:39 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |already_AddRefed|.
|
2014-06-27 05:35:39 +04:00
|
|
|
template<typename U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
|
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-08-25 23:17:20 +04:00
|
|
|
// But make sure that U actually inherits from T.
|
2014-06-27 05:35:39 +04:00
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U is not a subclass of T");
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
2012-11-15 11:32:39 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |otherComPtr.forget()|.
|
2014-06-27 05:35:39 +04:00
|
|
|
template<typename U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<U>&& aSmartPtr)
|
|
|
|
: NSCAP_CTOR_BASE(static_cast<T*>(aSmartPtr.take()))
|
1999-08-23 14:07:16 +04:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2014-08-25 23:17:20 +04:00
|
|
|
// But make sure that U actually inherits from T.
|
2014-06-27 05:35:39 +04:00
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U is not a subclass of T");
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, static_cast<T*>(mRawPtr));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
1999-08-23 14:07:16 +04:00
|
|
|
}
|
1999-07-15 07:59:09 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_QueryInterface(expr)|.
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceISupports aQI)
|
|
|
|
#else
|
|
|
|
template<typename U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterface<U> aQI)
|
|
|
|
#endif // ! #ifdef NSCAP_FEATURE_USE_BASE
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-03-05 02:04:27 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_qi(aQI, NS_GET_TEMPLATE_IID(T));
|
2004-03-05 02:04:27 +03:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_QueryInterface(expr, &rv)|.
|
2018-10-04 22:16:30 +03:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceISupportsWithError& aQI)
|
|
|
|
#else
|
|
|
|
template<typename U>
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceWithError<U>& aQI)
|
|
|
|
#endif // ! #ifdef NSCAP_FEATURE_USE_BASE
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-03-05 02:04:27 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_qi_with_error(aQI, NS_GET_TEMPLATE_IID(T));
|
2004-03-05 02:04:27 +03:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(cid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid(aGS, NS_GET_TEMPLATE_IID(T));
|
2004-11-25 01:48:45 +03:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(cid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
|
2004-11-25 01:48:45 +03:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(contractid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid(aGS, NS_GET_TEMPLATE_IID(T));
|
2004-11-25 01:48:45 +03:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(contractid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
2004-11-25 01:48:45 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid_with_error(aGS, NS_GET_TEMPLATE_IID(T));
|
2004-11-25 01:48:45 +03:00
|
|
|
}
|
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
// Construct from |do_QueryReferent(ptr)|
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryReferent& aQueryReferent)
|
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
|
|
|
{
|
|
|
|
assert_validity();
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
|
|
|
assign_from_query_referent(aQueryReferent, NS_GET_TEMPLATE_IID(T));
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// And finally, anything else we might need to construct from can exploit the
|
|
|
|
// nsCOMPtr_helper facility.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
|
2016-11-10 06:19:56 +03:00
|
|
|
: NSCAP_CTOR_BASE(nullptr)
|
1999-11-08 14:43:11 +03:00
|
|
|
{
|
2015-08-12 18:43:10 +03:00
|
|
|
assert_validity();
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_helper(aHelper, NS_GET_TEMPLATE_IID(T));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
1999-11-08 14:43:11 +03:00
|
|
|
}
|
1999-08-03 11:21:39 +04:00
|
|
|
|
2015-04-19 15:28:50 +03:00
|
|
|
// Defined in OwningNonNull.h
|
|
|
|
template<class U>
|
2015-08-05 15:28:27 +03:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const mozilla::OwningNonNull<U>& aOther);
|
2015-04-19 15:28:50 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
|
|
|
|
// Assignment operators
|
|
|
|
|
|
|
|
nsCOMPtr<T>& operator=(const nsCOMPtr<T>& aRhs)
|
1999-07-15 07:59:09 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_with_AddRef(aRhs.mRawPtr);
|
|
|
|
return *this;
|
2018-03-14 15:22:30 +03:00
|
|
|
}
|
|
|
|
|
2018-10-02 03:54:16 +03:00
|
|
|
template<class U>
|
|
|
|
nsCOMPtr<T>& operator=(const nsCOMPtr<U>& aRhs)
|
|
|
|
{
|
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U should be a subclass of T");
|
|
|
|
assign_with_AddRef(static_cast<T*>(aRhs.get()));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2018-03-14 15:22:30 +03:00
|
|
|
nsCOMPtr<T>& operator=(nsCOMPtr<T>&& aRhs)
|
|
|
|
{
|
|
|
|
assign_assuming_AddRef(aRhs.forget().take());
|
|
|
|
return *this;
|
2018-10-02 03:54:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class U>
|
|
|
|
nsCOMPtr<T>& operator=(nsCOMPtr<U>&& aRhs)
|
|
|
|
{
|
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U should be a subclass of T");
|
|
|
|
assign_assuming_AddRef(aRhs.forget().template downcast<T>().take());
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
return *this;
|
1999-07-15 07:59:09 +04:00
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(T* aRhs)
|
2000-12-09 07:45:43 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_with_AddRef(aRhs);
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
return *this;
|
2000-12-09 07:45:43 +03:00
|
|
|
}
|
|
|
|
|
2016-11-10 23:57:38 +03:00
|
|
|
nsCOMPtr<T>& operator=(decltype(nullptr))
|
|
|
|
{
|
|
|
|
assign_assuming_AddRef(nullptr);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |already_AddRefed|.
|
2014-06-27 05:35:39 +04:00
|
|
|
template<typename U>
|
|
|
|
nsCOMPtr<T>& operator=(already_AddRefed<U>& aRhs)
|
2000-12-09 07:45:43 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U is not a subclass of T");
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
return *this;
|
2000-12-09 07:45:43 +03:00
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |otherComPtr.forget()|.
|
2014-06-27 05:35:39 +04:00
|
|
|
template<typename U>
|
2014-08-25 23:17:20 +04:00
|
|
|
nsCOMPtr<T>& operator=(already_AddRefed<U>&& aRhs)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
// Make sure that U actually inherits from T
|
|
|
|
static_assert(mozilla::IsBaseOf<T, U>::value,
|
|
|
|
"U is not a subclass of T");
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(aRhs.take()));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_QueryInterface(expr)|.
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
nsCOMPtr<T>& operator=(const nsQueryInterfaceISupports aRhs)
|
|
|
|
#else
|
|
|
|
template<typename U>
|
|
|
|
nsCOMPtr<T>& operator=(const nsQueryInterface<U> aRhs)
|
|
|
|
#endif // ! #ifdef NSCAP_FEATURE_USE_BASE
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
assign_from_qi(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_QueryInterface(expr, &rv)|.
|
2018-10-04 22:16:30 +03:00
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
nsCOMPtr<T>& operator=(const nsQueryInterfaceISupportsWithError& aRhs)
|
|
|
|
#else
|
|
|
|
template<typename U>
|
|
|
|
nsCOMPtr<T>& operator=(const nsQueryInterfaceWithError<U>& aRhs)
|
|
|
|
#endif // ! #ifdef NSCAP_FEATURE_USE_BASE
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
assign_from_qi_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(cid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(const nsGetServiceByCID aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_cid(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(cid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(const nsGetServiceByCIDWithError& aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_cid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(contractid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(const nsGetServiceByContractID aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_contractid(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
1999-05-04 13:37:35 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(contractid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(const nsGetServiceByContractIDWithError& aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_contractid_with_error(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
1999-07-15 07:59:09 +04:00
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
// Assign from |do_QueryReferent(ptr)|.
|
|
|
|
nsCOMPtr<T>& operator=(const nsQueryReferent& aRhs)
|
|
|
|
{
|
|
|
|
assign_from_query_referent(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// And finally, anything else we might need to assign from can exploit the
|
|
|
|
// nsCOMPtr_helper facility.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<T>& operator=(const nsCOMPtr_helper& aRhs)
|
1998-12-17 22:12:45 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_helper(aRhs, NS_GET_TEMPLATE_IID(T));
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
return *this;
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2015-04-19 15:28:50 +03:00
|
|
|
// Defined in OwningNonNull.h
|
|
|
|
template<class U>
|
2015-08-05 15:28:27 +03:00
|
|
|
nsCOMPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
|
2015-04-19 15:28:50 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Exchange ownership with |aRhs|; can save a pair of refcount operations.
|
2014-06-27 05:35:39 +04:00
|
|
|
void swap(nsCOMPtr<T>& aRhs)
|
|
|
|
{
|
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
nsISupports* temp = aRhs.mRawPtr;
|
|
|
|
#else
|
|
|
|
T* temp = aRhs.mRawPtr;
|
2000-06-08 08:52:39 +04:00
|
|
|
#endif
|
2014-06-27 05:35:39 +04:00
|
|
|
NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, temp);
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
NSCAP_LOG_RELEASE(&aRhs, temp);
|
|
|
|
aRhs.mRawPtr = mRawPtr;
|
|
|
|
mRawPtr = temp;
|
|
|
|
// |aRhs| maintains the same invariants, so we don't need to |NSCAP_ASSERT_NO_QUERY_NEEDED|
|
|
|
|
}
|
2000-06-08 08:52:39 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Exchange ownership with |aRhs|; can save a pair of refcount operations.
|
2014-06-27 05:35:39 +04:00
|
|
|
void swap(T*& aRhs)
|
|
|
|
{
|
|
|
|
#ifdef NSCAP_FEATURE_USE_BASE
|
|
|
|
nsISupports* temp = aRhs;
|
|
|
|
#else
|
|
|
|
T* temp = aRhs;
|
1999-10-31 03:35:48 +03:00
|
|
|
#endif
|
2014-06-27 05:35:39 +04:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, temp);
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
aRhs = reinterpret_cast<T*>(mRawPtr);
|
|
|
|
mRawPtr = temp;
|
|
|
|
NSCAP_ASSERT_NO_QUERY_NEEDED();
|
|
|
|
}
|
1999-10-31 03:35:48 +03:00
|
|
|
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// Other pointer operators
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Return the value of mRawPtr and null out mRawPtr. Useful for
|
2014-06-27 05:35:39 +04:00
|
|
|
// already_AddRefed return values.
|
2017-02-28 22:41:25 +03:00
|
|
|
already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
T* temp = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
swap(temp);
|
|
|
|
return already_AddRefed<T>(temp);
|
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
|
|
|
|
// Useful to avoid unnecessary AddRef/Release pairs with "out" parameters
|
|
|
|
// where aRhs bay be a T** or an I** where I is a base class of T.
|
2014-06-27 05:35:39 +04:00
|
|
|
template<typename I>
|
|
|
|
void forget(I** aRhs)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aRhs, "Null pointer passed to forget!");
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
*aRhs = get();
|
2016-11-10 06:19:56 +03:00
|
|
|
mRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Prefer the implicit conversion provided automatically by
|
|
|
|
// |operator T*() const|. Use |get()| to resolve ambiguity or to get a
|
|
|
|
// castable pointer.
|
2014-06-27 05:35:39 +04:00
|
|
|
T* get() const { return reinterpret_cast<T*>(mRawPtr); }
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
|
|
|
|
// used in a context where a raw pointer is expected. It is this operator
|
|
|
|
// that makes an nsCOMPtr substitutable for a raw pointer.
|
|
|
|
//
|
|
|
|
// Prefer the implicit use of this operator to calling |get()|, except where
|
|
|
|
// necessary to resolve ambiguity.
|
2017-01-04 09:42:33 +03:00
|
|
|
operator T*() const & { return get(); }
|
2016-05-01 21:29:23 +03:00
|
|
|
|
|
|
|
// Don't allow implicit conversion of temporary nsCOMPtr to raw pointer,
|
|
|
|
// because the refcount might be one and the pointer will immediately become
|
|
|
|
// invalid.
|
|
|
|
operator T*() const && = delete;
|
|
|
|
|
|
|
|
// Needed to avoid the deleted operator above
|
|
|
|
explicit operator bool() const { return !!mRawPtr; }
|
2014-06-27 05:35:39 +04:00
|
|
|
|
2014-12-25 23:18:38 +03:00
|
|
|
T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
|
1999-11-08 14:43:11 +03:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
MOZ_ASSERT(mRawPtr != nullptr,
|
2015-02-10 01:34:50 +03:00
|
|
|
"You can't dereference a NULL nsCOMPtr with operator->().");
|
2014-06-27 05:35:39 +04:00
|
|
|
return get();
|
|
|
|
}
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// These are not intended to be used by clients. See |address_of| below.
|
|
|
|
nsCOMPtr<T>* get_address() { return this; }
|
|
|
|
const nsCOMPtr<T>* get_address() const { return this; }
|
|
|
|
|
|
|
|
public:
|
|
|
|
T& operator*() const
|
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
MOZ_ASSERT(mRawPtr != nullptr,
|
2015-02-10 01:34:50 +03:00
|
|
|
"You can't dereference a NULL nsCOMPtr with operator*().");
|
2014-06-27 05:35:39 +04:00
|
|
|
return *get();
|
|
|
|
}
|
|
|
|
|
|
|
|
T** StartAssignment()
|
|
|
|
{
|
|
|
|
#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
|
|
|
|
return reinterpret_cast<T**>(begin_assignment());
|
|
|
|
#else
|
2016-11-10 06:19:56 +03:00
|
|
|
assign_assuming_AddRef(nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
return reinterpret_cast<T**>(&mRawPtr);
|
2000-06-08 08:52:39 +04:00
|
|
|
#endif
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
};
|
2000-06-08 08:52:39 +04:00
|
|
|
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
/*
|
2014-08-25 23:17:20 +04:00
|
|
|
* Specializing nsCOMPtr for nsISupports allows us to use nsCOMPtr<nsISupports>
|
|
|
|
* the same way people use nsISupports* and void*, i.e., as a `catch-all'
|
|
|
|
* pointing to any valid [XP]COM interface. Otherwise, an nsCOMPtr<nsISupports>
|
|
|
|
* would only be able to point to the single [XP]COM-correct nsISupports
|
|
|
|
* instance within an object; extra querying ensues. Clients need to be able to
|
|
|
|
* pass around arbitrary interface pointers, without hassles, through
|
|
|
|
* intermediary code that doesn't know the exact type.
|
|
|
|
*/
|
2014-06-27 05:35:39 +04:00
|
|
|
template<>
|
|
|
|
class nsCOMPtr<nsISupports>
|
|
|
|
: private nsCOMPtr_base
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
typedef nsISupports element_type;
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// Constructors
|
1999-11-08 14:43:11 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr()
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
1998-12-17 22:12:45 +03:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
1998-12-17 22:12:45 +03:00
|
|
|
}
|
|
|
|
|
2016-11-10 23:57:38 +03:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(decltype(nullptr))
|
|
|
|
: nsCOMPtr_base(nullptr)
|
|
|
|
{
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr(const nsCOMPtr<nsISupports>& aSmartPtr)
|
|
|
|
: nsCOMPtr_base(aSmartPtr.mRawPtr)
|
|
|
|
{
|
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, mRawPtr);
|
|
|
|
}
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aSmartPtr.mRawPtr);
|
|
|
|
}
|
1998-12-17 22:12:45 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(nsISupports* aRawPtr)
|
|
|
|
: nsCOMPtr_base(aRawPtr)
|
|
|
|
{
|
|
|
|
if (mRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, mRawPtr);
|
|
|
|
}
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, aRawPtr);
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |already_AddRefed|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>& aSmartPtr)
|
|
|
|
: nsCOMPtr_base(aSmartPtr.take())
|
|
|
|
{
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
|
|
|
}
|
1999-06-30 01:09:59 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |otherComPtr.forget()|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(already_AddRefed<nsISupports>&& aSmartPtr)
|
|
|
|
: nsCOMPtr_base(aSmartPtr.take())
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, mRawPtr);
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_QueryInterface(expr)|.
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceISupports aQI)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_qi(aQI, NS_GET_IID(nsISupports));
|
|
|
|
}
|
2000-05-14 04:05:24 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_QueryInterface(expr, &rv)|.
|
2018-10-04 22:16:30 +03:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryInterfaceISupportsWithError& aQI)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_qi_with_error(aQI, NS_GET_IID(nsISupports));
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(cid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCID aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid(aGS, NS_GET_IID(nsISupports));
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(cid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByCIDWithError& aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_cid_with_error(aGS, NS_GET_IID(nsISupports));
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(contractid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractID aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid(aGS, NS_GET_IID(nsISupports));
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Construct from |do_GetService(contractid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsGetServiceByContractIDWithError& aGS)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid_with_error(aGS, NS_GET_IID(nsISupports));
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-06-02 05:29:55 +04:00
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
// Construct from |do_QueryReferent(ptr)|
|
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsQueryReferent& aQueryReferent)
|
|
|
|
: nsCOMPtr_base(nullptr)
|
|
|
|
{
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
|
|
|
assign_from_query_referent(aQueryReferent, NS_GET_TEMPLATE_IID(nsISupports));
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// And finally, anything else we might need to construct from can exploit
|
|
|
|
// the |nsCOMPtr_helper| facility
|
2014-06-27 05:35:39 +04:00
|
|
|
MOZ_IMPLICIT nsCOMPtr(const nsCOMPtr_helper& aHelper)
|
2016-11-10 06:19:56 +03:00
|
|
|
: nsCOMPtr_base(nullptr)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
NSCAP_LOG_ASSIGNMENT(this, nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_helper(aHelper, NS_GET_IID(nsISupports));
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-06-02 05:29:55 +04:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
|
|
|
|
// Assignment operators
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsCOMPtr<nsISupports>& aRhs)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_with_AddRef(aRhs.mRawPtr);
|
|
|
|
return *this;
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(nsISupports* aRhs)
|
2001-04-07 19:29:39 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_with_AddRef(aRhs);
|
|
|
|
return *this;
|
2001-04-07 19:29:39 +04:00
|
|
|
}
|
|
|
|
|
2016-11-10 23:57:38 +03:00
|
|
|
nsCOMPtr<nsISupports>& operator=(decltype(nullptr))
|
|
|
|
{
|
|
|
|
assign_assuming_AddRef(nullptr);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |already_AddRefed|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>& aRhs)
|
2001-04-07 19:29:39 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_assuming_AddRef(aRhs.take());
|
|
|
|
return *this;
|
2001-04-07 19:29:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |otherComPtr.forget()|.
|
|
|
|
nsCOMPtr<nsISupports>& operator=(already_AddRefed<nsISupports>&& aRhs)
|
2001-04-07 19:29:39 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_assuming_AddRef(aRhs.take());
|
|
|
|
return *this;
|
2001-04-07 19:29:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_QueryInterface(expr)|.
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsQueryInterfaceISupports aRhs)
|
2001-04-07 19:29:39 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_qi(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
2001-04-07 19:29:39 +04:00
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_QueryInterface(expr, &rv)|.
|
2018-10-04 22:16:30 +03:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsQueryInterfaceISupportsWithError& aRhs)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
assign_from_qi_with_error(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(cid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCID aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_cid(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(cid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsGetServiceByCIDWithError& aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_cid_with_error(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(contractid_expr)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractID aRhs)
|
|
|
|
{
|
|
|
|
assign_from_gs_contractid(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Assign from |do_GetService(contractid_expr, &rv)|.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsGetServiceByContractIDWithError& aRhs)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_gs_contractid_with_error(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
// Assign from |do_QueryReferent(ptr)|.
|
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsQueryReferent& aRhs)
|
|
|
|
{
|
|
|
|
assign_from_query_referent(aRhs, NS_GET_TEMPLATE_IID(nsISupports));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// And finally, anything else we might need to assign from can exploit the
|
|
|
|
// nsCOMPtr_helper facility
|
2014-06-27 05:35:39 +04:00
|
|
|
nsCOMPtr<nsISupports>& operator=(const nsCOMPtr_helper& aRhs)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
assign_from_helper(aRhs, NS_GET_IID(nsISupports));
|
|
|
|
return *this;
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Exchange ownership with |aRhs|; can save a pair of refcount operations.
|
2014-06-27 05:35:39 +04:00
|
|
|
void swap(nsCOMPtr<nsISupports>& aRhs)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
nsISupports* temp = aRhs.mRawPtr;
|
|
|
|
NSCAP_LOG_ASSIGNMENT(&aRhs, mRawPtr);
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, temp);
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
NSCAP_LOG_RELEASE(&aRhs, temp);
|
|
|
|
aRhs.mRawPtr = mRawPtr;
|
|
|
|
mRawPtr = temp;
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-06-02 05:29:55 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Exchange ownership with |aRhs|; can save a pair of refcount operations.
|
2014-06-27 05:35:39 +04:00
|
|
|
void swap(nsISupports*& aRhs)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
nsISupports* temp = aRhs;
|
|
|
|
NSCAP_LOG_ASSIGNMENT(this, temp);
|
|
|
|
NSCAP_LOG_RELEASE(this, mRawPtr);
|
|
|
|
aRhs = mRawPtr;
|
|
|
|
mRawPtr = temp;
|
1999-06-02 05:59:28 +04:00
|
|
|
}
|
1999-06-02 05:29:55 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Return the value of mRawPtr and null out mRawPtr. Useful for
|
2014-06-27 05:35:39 +04:00
|
|
|
// already_AddRefed return values.
|
2014-08-25 23:17:20 +04:00
|
|
|
already_AddRefed<nsISupports> forget()
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
nsISupports* temp = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
swap(temp);
|
|
|
|
return already_AddRefed<nsISupports>(temp);
|
|
|
|
}
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
|
|
|
|
// Useful to avoid unnecessary AddRef/Release pairs with "out"
|
|
|
|
// parameters.
|
2014-08-25 23:17:20 +04:00
|
|
|
void forget(nsISupports** aRhs)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aRhs, "Null pointer passed to forget!");
|
2016-11-10 06:19:56 +03:00
|
|
|
*aRhs = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
swap(*aRhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other pointer operators
|
2000-05-13 04:05:29 +04:00
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Prefer the implicit conversion provided automatically by
|
|
|
|
// |operator nsISupports*() const|. Use |get()| to resolve ambiguity or to
|
|
|
|
// get a castable pointer.
|
2014-06-27 05:35:39 +04:00
|
|
|
nsISupports* get() const { return reinterpret_cast<nsISupports*>(mRawPtr); }
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
// Makes an nsCOMPtr act like its underlying raw pointer type whenever it is
|
|
|
|
// used in a context where a raw pointer is expected. It is this operator
|
|
|
|
// that makes an nsCOMPtr substitutable for a raw pointer.
|
|
|
|
//
|
|
|
|
// Prefer the implicit use of this operator to calling |get()|, except where
|
|
|
|
// necessary to resolve ambiguity/
|
|
|
|
operator nsISupports* () const { return get(); }
|
2014-06-27 05:35:39 +04:00
|
|
|
|
2014-12-25 23:18:38 +03:00
|
|
|
nsISupports* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN
|
2000-05-13 04:05:29 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
MOZ_ASSERT(mRawPtr != nullptr,
|
2015-02-10 01:34:50 +03:00
|
|
|
"You can't dereference a NULL nsCOMPtr with operator->().");
|
2014-06-27 05:35:39 +04:00
|
|
|
return get();
|
2000-05-13 04:05:29 +04:00
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
// These are not intended to be used by clients. See |address_of| below.
|
|
|
|
nsCOMPtr<nsISupports>* get_address() { return this; }
|
|
|
|
const nsCOMPtr<nsISupports>* get_address() const { return this; }
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
nsISupports& operator*() const
|
2000-05-13 04:05:29 +04:00
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
MOZ_ASSERT(mRawPtr != nullptr,
|
2015-02-10 01:34:50 +03:00
|
|
|
"You can't dereference a NULL nsCOMPtr with operator*().");
|
2014-06-27 05:35:39 +04:00
|
|
|
return *get();
|
2000-05-13 04:05:29 +04:00
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
nsISupports** StartAssignment()
|
|
|
|
{
|
|
|
|
#ifndef NSCAP_FEATURE_INLINE_STARTASSIGNMENT
|
|
|
|
return reinterpret_cast<nsISupports**>(begin_assignment());
|
|
|
|
#else
|
2016-11-10 06:19:56 +03:00
|
|
|
assign_assuming_AddRef(nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
return reinterpret_cast<nsISupports**>(&mRawPtr);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline void
|
|
|
|
ImplCycleCollectionUnlink(nsCOMPtr<T>& aField)
|
|
|
|
{
|
|
|
|
aField = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
inline void
|
|
|
|
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
|
|
|
nsCOMPtr<T>& aField,
|
|
|
|
const char* aName,
|
|
|
|
uint32_t aFlags = 0)
|
|
|
|
{
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef NSCAP_FEATURE_USE_BASE
|
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_with_AddRef(nsISupports* aRawPtr)
|
|
|
|
{
|
|
|
|
if (aRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, aRawPtr);
|
|
|
|
}
|
|
|
|
assign_assuming_AddRef(reinterpret_cast<T*>(aRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
template<typename U>
|
2014-06-27 05:35:39 +04:00
|
|
|
void
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
nsCOMPtr<T>::assign_from_qi(const nsQueryInterface<U> aQI, const nsIID& aIID)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
Bug 1493226, part 1 - Statically prevent trivial calls to do_QueryInterface r=froydnj
This patch adds a static assert to enforce that do_QueryInterface is
not used to go from a class to a base class, because that can be done
more efficiently via a static_cast. This is done by putting the type
of the source into the nsQueryInterface type. Once that is done, it is
easy to check the source and destination type. This has to be done
carefully so that in non-DEBUG builds, where NSCAP_FEATURE_USE_BASE is
defined, we don't generate any additional code.
The first step is to rename nsQueryInterface to
nsQueryInterfaceISupports. In DEBUG builds, I then add a new subtype
nsQueryInterface<T>, where T is the type of the object we are going to
QI. This class is a thin wrapper around nsQueryInterfaceISupports that
only forwards operations to the base class.
The main bit of trickery here is PointedToType<T>, which is needed to
get the type parameter for nsQueryInterface. This dereferences the
type, gets the address of it, then does RemovePointer. This is needed
because a wide variety of pointer types are passed in to
do_QueryInterface, including RefPtr<>, nsCOMPtr<>, raw pointers, and
OwningNonNull<>. PointedToType<RefPtr<T>> is equal to T,
PointedToType<T*> is equal to T, and so on.
In NSCAP_FEATURE_USE_BASE builds (opt), we only use
nsQueryInterfaceISupports, but in debug builds we use
nsQueryInterface<> where possible. The latter is also used for the
nsCOMPtr<nsISupports> overload, because we can always QI to
nsISupports, because that is sometimes used for canonicalization.
Another gross bit is that Assert_NoQueryNeeded can no longer use
nsCOMPtr<>, because it works by QIing T to T, which is banned by the
static analysis. Instead I had to reimplement it by hand.
Depends on D7527
Differential Revision: https://phabricator.services.mozilla.com/D7553
--HG--
extra : moz-landing-system : lando
2018-10-04 22:16:28 +03:00
|
|
|
static_assert(!(mozilla::IsSame<T, U>::value ||
|
|
|
|
mozilla::IsBaseOf<T, U>::value),
|
|
|
|
"don't use do_QueryInterface for compile-time-determinable casts");
|
2014-06-27 05:35:39 +04:00
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQI(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
2018-10-04 22:16:30 +03:00
|
|
|
template<typename U>
|
2014-06-27 05:35:39 +04:00
|
|
|
void
|
2018-10-04 22:16:30 +03:00
|
|
|
nsCOMPtr<T>::assign_from_qi_with_error(const nsQueryInterfaceWithError<U>& aQI,
|
2014-06-27 05:35:39 +04:00
|
|
|
const nsIID& aIID)
|
|
|
|
{
|
2018-10-04 22:16:30 +03:00
|
|
|
static_assert(!(mozilla::IsSame<T, U>::value ||
|
|
|
|
mozilla::IsBaseOf<T, U>::value),
|
|
|
|
"don't use do_QueryInterface for compile-time-determinable casts");
|
2014-06-27 05:35:39 +04:00
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQI(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_gs_cid(const nsGetServiceByCID aGS, const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_gs_cid_with_error(const nsGetServiceByCIDWithError& aGS,
|
|
|
|
const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_gs_contractid(const nsGetServiceByContractID aGS,
|
|
|
|
const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_gs_contractid_with_error(
|
|
|
|
const nsGetServiceByContractIDWithError& aGS, const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_query_referent(
|
|
|
|
const nsQueryReferent& aQueryReferent, const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQueryReferent(aIID, &newRawPtr))) {
|
|
|
|
newRawPtr = nullptr;
|
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
|
|
|
void
|
|
|
|
nsCOMPtr<T>::assign_from_helper(const nsCOMPtr_helper& helper, const nsIID& aIID)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(helper(aIID, &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
void**
|
|
|
|
nsCOMPtr<T>::begin_assignment()
|
|
|
|
{
|
2016-11-10 06:19:56 +03:00
|
|
|
assign_assuming_AddRef(nullptr);
|
2014-06-27 05:35:39 +04:00
|
|
|
union
|
|
|
|
{
|
|
|
|
T** mT;
|
|
|
|
void** mVoid;
|
|
|
|
} result;
|
|
|
|
result.mT = &mRawPtr;
|
|
|
|
return result.mVoid;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline nsCOMPtr<T>*
|
|
|
|
address_of(nsCOMPtr<T>& aPtr)
|
|
|
|
{
|
|
|
|
return aPtr.get_address();
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline const nsCOMPtr<T>*
|
|
|
|
address_of(const nsCOMPtr<T>& aPtr)
|
|
|
|
{
|
|
|
|
return aPtr.get_address();
|
|
|
|
}
|
|
|
|
|
2014-08-25 23:17:20 +04:00
|
|
|
/**
|
|
|
|
* This class is designed to be used for anonymous temporary objects in the
|
|
|
|
* argument list of calls that return COM interface pointers, e.g.,
|
|
|
|
*
|
|
|
|
* nsCOMPtr<IFoo> fooP;
|
|
|
|
* ...->QueryInterface(iid, getter_AddRefs(fooP))
|
|
|
|
*
|
|
|
|
* DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
|
|
|
|
*
|
|
|
|
* When initialized with a |nsCOMPtr|, as in the example above, it returns
|
|
|
|
* a |void**|, a |T**|, or an |nsISupports**| as needed, that the outer call
|
|
|
|
* (|QueryInterface| in this case) can fill in.
|
|
|
|
*
|
|
|
|
* This type should be a nested class inside |nsCOMPtr<T>|.
|
|
|
|
*/
|
2014-06-27 05:35:39 +04:00
|
|
|
template<class T>
|
|
|
|
class nsGetterAddRefs
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit nsGetterAddRefs(nsCOMPtr<T>& aSmartPtr)
|
|
|
|
: mTargetSmartPtr(aSmartPtr)
|
1999-06-02 05:59:28 +04:00
|
|
|
{
|
|
|
|
}
|
1999-05-05 14:37:05 +04:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
#if defined(NSCAP_FEATURE_TEST_DONTQUERY_CASES) || defined(NSCAP_LOG_EXTERNAL_ASSIGNMENT)
|
|
|
|
~nsGetterAddRefs()
|
|
|
|
{
|
|
|
|
#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
|
|
|
|
NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
|
|
|
|
mTargetSmartPtr.get());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef NSCAP_FEATURE_TEST_DONTQUERY_CASES
|
|
|
|
mTargetSmartPtr.Assert_NoQueryNeeded();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
#endif
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
operator void**()
|
|
|
|
{
|
|
|
|
return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
|
|
|
|
}
|
|
|
|
|
|
|
|
operator T**() { return mTargetSmartPtr.StartAssignment(); }
|
|
|
|
T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsCOMPtr<T>& mTargetSmartPtr;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
template<>
|
|
|
|
class nsGetterAddRefs<nsISupports>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
explicit nsGetterAddRefs(nsCOMPtr<nsISupports>& aSmartPtr)
|
|
|
|
: mTargetSmartPtr(aSmartPtr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef NSCAP_LOG_EXTERNAL_ASSIGNMENT
|
|
|
|
~nsGetterAddRefs()
|
|
|
|
{
|
|
|
|
NSCAP_LOG_ASSIGNMENT(reinterpret_cast<void*>(address_of(mTargetSmartPtr)),
|
|
|
|
mTargetSmartPtr.get());
|
|
|
|
}
|
|
|
|
#endif
|
2000-02-13 02:30:52 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
operator void**()
|
2000-01-30 01:29:08 +03:00
|
|
|
{
|
2014-06-27 05:35:39 +04:00
|
|
|
return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
|
2000-01-30 01:29:08 +03:00
|
|
|
}
|
1999-12-07 17:09:29 +03:00
|
|
|
|
2014-06-27 05:35:39 +04:00
|
|
|
operator nsISupports**() { return mTargetSmartPtr.StartAssignment(); }
|
|
|
|
nsISupports*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsCOMPtr<nsISupports>& mTargetSmartPtr;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline nsGetterAddRefs<T>
|
|
|
|
getter_AddRefs(nsCOMPtr<T>& aSmartPtr)
|
|
|
|
{
|
|
|
|
return nsGetterAddRefs<T>(aSmartPtr);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class DestinationType>
|
|
|
|
inline nsresult
|
|
|
|
CallQueryInterface(T* aSource, nsGetterAddRefs<DestinationType> aDestination)
|
|
|
|
{
|
|
|
|
return CallQueryInterface(aSource,
|
|
|
|
static_cast<DestinationType**>(aDestination));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Comparing two |nsCOMPtr|s
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator==(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator!=(const nsCOMPtr<T>& aLhs, const nsCOMPtr<U>& aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Comparing an |nsCOMPtr| to a raw pointer
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator==(const nsCOMPtr<T>& aLhs, const U* aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) == aRhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator==(const U* aLhs, const nsCOMPtr<T>& aRhs)
|
|
|
|
{
|
|
|
|
return aLhs == static_cast<const T*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator!=(const nsCOMPtr<T>& aLhs, const U* aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) != aRhs;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator!=(const U* aLhs, const nsCOMPtr<T>& aRhs)
|
|
|
|
{
|
|
|
|
return aLhs != static_cast<const T*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator==(const nsCOMPtr<T>& aLhs, U* aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator==(U* aLhs, const nsCOMPtr<T>& aRhs)
|
|
|
|
{
|
|
|
|
return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator!=(const nsCOMPtr<T>& aLhs, U* aRhs)
|
|
|
|
{
|
|
|
|
return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<class T, class U>
|
|
|
|
inline bool
|
|
|
|
operator!=(U* aLhs, const nsCOMPtr<T>& aRhs)
|
|
|
|
{
|
|
|
|
return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-08-20 03:30:10 +03:00
|
|
|
// Comparing an |nsCOMPtr| to |nullptr|
|
2014-06-27 05:35:39 +04:00
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline bool
|
2015-08-20 03:30:10 +03:00
|
|
|
operator==(const nsCOMPtr<T>& aLhs, decltype(nullptr))
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2015-08-20 03:30:10 +03:00
|
|
|
return aLhs.get() == nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline bool
|
2015-08-20 03:30:10 +03:00
|
|
|
operator==(decltype(nullptr), const nsCOMPtr<T>& aRhs)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2015-08-20 03:30:10 +03:00
|
|
|
return nullptr == aRhs.get();
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline bool
|
2015-08-20 03:30:10 +03:00
|
|
|
operator!=(const nsCOMPtr<T>& aLhs, decltype(nullptr))
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2015-08-20 03:30:10 +03:00
|
|
|
return aLhs.get() != nullptr;
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
template<class T>
|
|
|
|
inline bool
|
2015-08-20 03:30:10 +03:00
|
|
|
operator!=(decltype(nullptr), const nsCOMPtr<T>& aRhs)
|
2014-06-27 05:35:39 +04:00
|
|
|
{
|
2015-08-20 03:30:10 +03:00
|
|
|
return nullptr != aRhs.get();
|
2014-06-27 05:35:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Comparing any two [XP]COM objects for identity
|
|
|
|
|
|
|
|
inline bool
|
|
|
|
SameCOMIdentity(nsISupports* aLhs, nsISupports* aRhs)
|
|
|
|
{
|
|
|
|
return nsCOMPtr<nsISupports>(do_QueryInterface(aLhs)) ==
|
|
|
|
nsCOMPtr<nsISupports>(do_QueryInterface(aRhs));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template<class SourceType, class DestinationType>
|
|
|
|
inline nsresult
|
|
|
|
CallQueryInterface(nsCOMPtr<SourceType>& aSourcePtr, DestinationType** aDestPtr)
|
|
|
|
{
|
|
|
|
return CallQueryInterface(aSourcePtr.get(), aDestPtr);
|
|
|
|
}
|
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
template <class T>
|
|
|
|
RefPtr<T>::RefPtr(const nsQueryReferent& aQueryReferent)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQueryReferent(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
|
|
|
|
newRawPtr = nullptr;
|
|
|
|
}
|
|
|
|
mRawPtr = static_cast<T*>(newRawPtr);
|
|
|
|
}
|
|
|
|
|
2015-07-29 03:45:58 +03:00
|
|
|
template <class T>
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<T>::RefPtr(const nsCOMPtr_helper& aHelper)
|
2015-07-29 03:45:58 +03:00
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2015-07-29 03:45:58 +03:00
|
|
|
}
|
|
|
|
mRawPtr = static_cast<T*>(newRawPtr);
|
|
|
|
}
|
|
|
|
|
2017-08-25 03:04:31 +03:00
|
|
|
template <class T>
|
|
|
|
RefPtr<T>&
|
|
|
|
RefPtr<T>::operator=(const nsQueryReferent& aQueryReferent)
|
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQueryReferent(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
|
|
|
|
newRawPtr = nullptr;
|
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-29 03:45:58 +03:00
|
|
|
template <class T>
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<T>&
|
|
|
|
RefPtr<T>::operator=(const nsCOMPtr_helper& aHelper)
|
2015-07-29 03:45:58 +03:00
|
|
|
{
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aHelper(NS_GET_TEMPLATE_IID(T), &newRawPtr))) {
|
2016-11-10 06:19:56 +03:00
|
|
|
newRawPtr = nullptr;
|
2015-07-29 03:45:58 +03:00
|
|
|
}
|
|
|
|
assign_assuming_AddRef(static_cast<T*>(newRawPtr));
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2017-10-26 05:46:50 +03:00
|
|
|
template <class T>
|
|
|
|
inline already_AddRefed<T>
|
|
|
|
do_AddRef(const nsCOMPtr<T>& aObj)
|
|
|
|
{
|
|
|
|
nsCOMPtr<T> ref(aObj);
|
|
|
|
return ref.forget();
|
|
|
|
}
|
|
|
|
|
1998-12-17 22:12:45 +03:00
|
|
|
#endif // !defined(nsCOMPtr_h___)
|