2014-06-30 15:39:45 +00: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 11:12:37 +00: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/. */
|
1999-02-17 01:57:07 +00:00
|
|
|
|
|
|
|
#include "nsCOMPtr.h"
|
1999-10-31 00:35:48 +00: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 19:16:28 +00:00
|
|
|
nsresult nsQueryInterfaceISupports::operator()(const nsIID& aIID,
|
|
|
|
void** aAnswer) const {
|
2014-06-27 01:35:39 +00:00
|
|
|
nsresult status;
|
|
|
|
if (mRawPtr) {
|
|
|
|
status = mRawPtr->QueryInterface(aIID, aAnswer);
|
2014-08-25 19:17:15 +00:00
|
|
|
} else {
|
2014-06-27 01:35:39 +00:00
|
|
|
status = NS_ERROR_NULL_POINTER;
|
2014-08-25 19:17:15 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
2004-03-04 23:04:27 +00:00
|
|
|
|
2018-10-04 19:16:30 +00:00
|
|
|
nsresult nsQueryInterfaceISupportsWithError::operator()(const nsIID& aIID,
|
|
|
|
void** aAnswer) const {
|
2014-06-27 01:35:39 +00:00
|
|
|
nsresult status;
|
|
|
|
if (mRawPtr) {
|
|
|
|
status = mRawPtr->QueryInterface(aIID, aAnswer);
|
2014-08-25 19:17:15 +00:00
|
|
|
} else {
|
2014-06-27 01:35:39 +00:00
|
|
|
status = NS_ERROR_NULL_POINTER;
|
2014-08-25 19:17:15 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
|
|
|
|
if (mErrorPtr) {
|
|
|
|
*mErrorPtr = status;
|
|
|
|
}
|
|
|
|
return status;
|
|
|
|
}
|
1999-02-17 01:57:07 +00:00
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_with_AddRef(nsISupports* aRawPtr) {
|
|
|
|
if (aRawPtr) {
|
|
|
|
NSCAP_ADDREF(this, aRawPtr);
|
|
|
|
}
|
|
|
|
assign_assuming_AddRef(aRawPtr);
|
|
|
|
}
|
1999-02-17 01:57:07 +00: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 19:16:28 +00:00
|
|
|
void nsCOMPtr_base::assign_from_qi(const nsQueryInterfaceISupports aQI,
|
|
|
|
const nsIID& aIID) {
|
2014-06-27 01:35:39 +00:00
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQI(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-03-04 23:04:27 +00:00
|
|
|
|
2018-10-04 19:16:30 +00:00
|
|
|
void nsCOMPtr_base::assign_from_qi_with_error(
|
|
|
|
const nsQueryInterfaceISupportsWithError& aQI, const nsIID& aIID) {
|
2014-06-27 01:35:39 +00:00
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aQI(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-03-04 23:04:27 +00:00
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_from_gs_cid(const nsGetServiceByCID aGS,
|
|
|
|
const nsIID& aIID) {
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-11-24 22:48:45 +00:00
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_from_gs_cid_with_error(
|
|
|
|
const nsGetServiceByCIDWithError& aGS, const nsIID& aIID) {
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-11-24 22:48:45 +00:00
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_from_gs_contractid(
|
|
|
|
const nsGetServiceByContractID aGS, const nsIID& aIID) {
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-11-24 22:48:45 +00:00
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_from_gs_contractid_with_error(
|
|
|
|
const nsGetServiceByContractIDWithError& aGS, const nsIID& aIID) {
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aGS(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
2004-11-24 22:48:45 +00:00
|
|
|
|
2017-08-25 00:04:31 +00:00
|
|
|
void nsCOMPtr_base::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<nsISupports*>(newRawPtr));
|
|
|
|
}
|
|
|
|
|
2014-06-27 01:35:39 +00:00
|
|
|
void nsCOMPtr_base::assign_from_helper(const nsCOMPtr_helper& aHelper,
|
|
|
|
const nsIID& aIID) {
|
|
|
|
void* newRawPtr;
|
|
|
|
if (NS_FAILED(aHelper(aIID, &newRawPtr))) {
|
2016-11-10 03:19:56 +00:00
|
|
|
newRawPtr = nullptr;
|
2006-11-23 13:21:27 +00:00
|
|
|
}
|
2014-06-27 01:35:39 +00:00
|
|
|
assign_assuming_AddRef(static_cast<nsISupports*>(newRawPtr));
|
|
|
|
}
|
1999-10-31 00:35:48 +00:00
|
|
|
|
1999-02-17 01:57:07 +00:00
|
|
|
void** nsCOMPtr_base::begin_assignment() {
|
2016-11-10 03:19:56 +00:00
|
|
|
assign_assuming_AddRef(nullptr);
|
2014-06-27 01:35:39 +00:00
|
|
|
return reinterpret_cast<void**>(&mRawPtr);
|
|
|
|
}
|