Bug 1028588 - Fix dangerous public destructors in xpcom/ - r=bsmedberg,khuey,nfroyd
authorBenoit Jacob <bjacob@mozilla.com>
Mon, 30 Jun 2014 18:11:53 -0400
changeset 191794 bb961917a75cb2bd6e1547a952beca8c588c7414
parent 191793 80a31ed2b9754d0e07153567c562508dec3c2e3b
child 191795 9a39c61d24033e288992e8163b51a6009abeb621
push id27063
push usercbook@mozilla.com
push dateWed, 02 Jul 2014 12:51:47 +0000
treeherdermozilla-central@49e7fc49dd4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, khuey, nfroyd
bugs1028588
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1028588 - Fix dangerous public destructors in xpcom/ - r=bsmedberg,khuey,nfroyd
xpcom/base/AvailableMemoryTracker.cpp
xpcom/base/SystemMemoryReporter.cpp
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsDumpUtils.h
xpcom/base/nsGZFileWriter.h
xpcom/base/nsIStatusReporter.idl
xpcom/base/nsInterfaceRequestorAgg.cpp
xpcom/base/nsMemoryInfoDumper.cpp
xpcom/base/nsMemoryInfoDumper.h
xpcom/base/nsMemoryReporterManager.cpp
xpcom/base/nsMemoryReporterManager.h
xpcom/base/nsMessageLoop.cpp
xpcom/base/nsMessageLoop.h
xpcom/base/nsStatusReporterManager.h
xpcom/base/nsVersionComparatorImpl.h
xpcom/build/nsXPComInit.cpp
xpcom/components/ModuleUtils.h
xpcom/components/nsNativeComponentLoader.h
xpcom/ds/nsArray.h
xpcom/ds/nsHashPropertyBag.cpp
xpcom/ds/nsHashPropertyBag.h
xpcom/ds/nsINIParserImpl.cpp
xpcom/ds/nsINIParserImpl.h
xpcom/ds/nsSupportsArray.h
xpcom/glue/GenericFactory.h
xpcom/glue/nsCategoryCache.h
xpcom/glue/nsThreadUtils.cpp
xpcom/io/nsAppFileLocationProvider.cpp
xpcom/io/nsBinaryStream.h
xpcom/io/nsDirectoryService.h
xpcom/io/nsIOUtil.h
xpcom/io/nsStreamUtils.cpp
xpcom/reflect/xptinfo/ShimInterfaceInfo.h
xpcom/tests/TestCOMArray.cpp
xpcom/tests/TestCallTemplates.cpp
xpcom/tests/TestRacingServiceManager.cpp
xpcom/tests/TestThreadPoolListener.cpp
xpcom/tests/TestThreadUtils.cpp
xpcom/tests/TestTimers.cpp
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -391,16 +391,18 @@ NS_IMPL_ISUPPORTS(LowEventsReporter, nsI
 /**
  * This runnable is executed in response to a memory-pressure event; we spin
  * the event-loop when receiving the memory-pressure event in the hope that
  * other observers will synchronously free some memory that we'll be able to
  * purge here.
  */
 class nsJemallocFreeDirtyPagesRunnable MOZ_FINAL : public nsIRunnable
 {
+  ~nsJemallocFreeDirtyPagesRunnable() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 };
 
 NS_IMPL_ISUPPORTS(nsJemallocFreeDirtyPagesRunnable, nsIRunnable)
 
 NS_IMETHODIMP
@@ -417,16 +419,18 @@ nsJemallocFreeDirtyPagesRunnable::Run()
 
 /**
  * The memory pressure watcher is used for listening to memory-pressure events
  * and reacting upon them. We use one instance per process currently only for
  * cleaning up dirty unused pages held by jemalloc.
  */
 class nsMemoryPressureWatcher MOZ_FINAL : public nsIObserver
 {
+  ~nsMemoryPressureWatcher() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   void Init();
 
 private:
   static bool sFreeDirtyPages;
--- a/xpcom/base/SystemMemoryReporter.cpp
+++ b/xpcom/base/SystemMemoryReporter.cpp
@@ -109,16 +109,18 @@ IsAnonymous(const nsACString& aName)
   // as regular anonymous memory.  However, see below about tagged anonymous
   // memory.
   return aName.IsEmpty() ||
          StringBeginsWith(aName, NS_LITERAL_CSTRING("[stack:"));
 }
 
 class SystemReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~SystemReporter() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
 #define REPORT_WITH_CLEANUP(_path, _units, _amount, _desc, _cleanup)          \
   do {                                                                        \
     size_t amount = _amount;  /* evaluate _amount only once */                \
     if (amount > 0) {                                                         \
       nsresult rv;                                                            \
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -1274,19 +1274,21 @@ class nsCycleCollector : public nsIMemor
 
   nsPurpleBuffer mPurpleBuf;
 
   uint32_t mUnmergedNeeded;
   uint32_t mMergedInARow;
 
   JSPurpleBuffer* mJSPurpleBuffer;
 
+private:
+  virtual ~nsCycleCollector();
+
 public:
   nsCycleCollector();
-  virtual ~nsCycleCollector();
 
   void RegisterJSRuntime(CycleCollectedJSRuntime* aJSRuntime);
   void ForgetJSRuntime();
 
   void SetBeforeUnlinkCallback(CC_BeforeUnlinkCallback aBeforeUnlinkCB)
   {
     CheckThreadSafety();
     mBeforeUnlinkCB = aBeforeUnlinkCB;
@@ -1706,31 +1708,31 @@ private:
   FileInfo mCCLog;
 };
 
 NS_IMPL_ISUPPORTS(nsCycleCollectorLogSinkToFile, nsICycleCollectorLogSink)
 
 
 class nsCycleCollectorLogger MOZ_FINAL : public nsICycleCollectorListener
 {
+  ~nsCycleCollectorLogger()
+  {
+    ClearDescribers();
+  }
+
 public:
   nsCycleCollectorLogger()
     : mLogSink(nsCycleCollector_createLogSink())
     , mWantAllTraces(false)
     , mDisableLog(false)
     , mWantAfterProcessing(false)
     , mCCLog(nullptr)
   {
   }
 
-  ~nsCycleCollectorLogger()
-  {
-    ClearDescribers();
-  }
-
   NS_DECL_ISUPPORTS
 
   void SetAllTraces()
   {
     mWantAllTraces = true;
   }
 
   NS_IMETHOD AllTraces(nsICycleCollectorListener** aListener)
@@ -2510,32 +2512,32 @@ private:
 
 // JSPurpleBuffer keeps references to GCThings which might affect the
 // next cycle collection. It is owned only by itself and during unlink its
 // self reference is broken down and the object ends up killing itself.
 // If GC happens before CC, references to GCthings and the self reference are
 // removed.
 class JSPurpleBuffer
 {
+  ~JSPurpleBuffer()
+  {
+    MOZ_ASSERT(mValues.IsEmpty());
+    MOZ_ASSERT(mObjects.IsEmpty());
+    MOZ_ASSERT(mTenuredObjects.IsEmpty());
+  }
+
 public:
   JSPurpleBuffer(JSPurpleBuffer*& aReferenceToThis)
     : mReferenceToThis(aReferenceToThis)
   {
     mReferenceToThis = this;
     NS_ADDREF_THIS();
     mozilla::HoldJSObjects(this);
   }
 
-  ~JSPurpleBuffer()
-  {
-    MOZ_ASSERT(mValues.IsEmpty());
-    MOZ_ASSERT(mObjects.IsEmpty());
-    MOZ_ASSERT(mTenuredObjects.IsEmpty());
-  }
-
   void Destroy()
   {
     mReferenceToThis = nullptr;
     mValues.Clear();
     mObjects.Clear();
     mTenuredObjects.Clear();
     mozilla::DropJSObjects(this);
     NS_RELEASE_THIS();
--- a/xpcom/base/nsDumpUtils.h
+++ b/xpcom/base/nsDumpUtils.h
@@ -35,29 +35,29 @@
 class FdWatcher
   : public MessageLoopForIO::Watcher
   , public nsIObserver
 {
 protected:
   MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
   int mFd;
 
+  virtual ~FdWatcher()
+  {
+    // StopWatching should have run.
+    MOZ_ASSERT(mFd == -1);
+  }
+
 public:
   FdWatcher()
     : mFd(-1)
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
-  virtual ~FdWatcher()
-  {
-    // StopWatching should have run.
-    MOZ_ASSERT(mFd == -1);
-  }
-
   /**
    * Open the fd to watch.  If we encounter an error, return -1.
    */
   virtual int OpenFd() = 0;
 
   /**
    * Called when you can read() from the fd without blocking.  Note that this
    * function is also called when you're at eof (read() returns 0 in this case).
--- a/xpcom/base/nsGZFileWriter.h
+++ b/xpcom/base/nsGZFileWriter.h
@@ -10,19 +10,20 @@
 #include "nsIGZFileWriter.h"
 #include "zlib.h"
 
 /**
  * A simple class for writing .gz files.
  */
 class nsGZFileWriter : public nsIGZFileWriter
 {
+  virtual ~nsGZFileWriter();
+
 public:
   nsGZFileWriter();
-  virtual ~nsGZFileWriter();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIGZFILEWRITER
 
   /**
    * nsIGZFileWriter exposes two non-virtual overloads of Write().  We
    * duplicate them here so that you can call these overloads on a pointer to
    * the concrete nsGZFileWriter class.
--- a/xpcom/base/nsIStatusReporter.idl
+++ b/xpcom/base/nsIStatusReporter.idl
@@ -61,16 +61,17 @@ interface nsIStatusReporterManager : nsI
 
 %{C++
 
 /*
  * Note that this defaults 'process' to "", which is usually what's desired.
  */
 #define NS_STATUS_REPORTER_IMPLEMENT(_classname, _name, _desc_Function)       \
     class StatusReporter_##_classname MOZ_FINAL : public nsIStatusReporter {  \
+      ~StatusReporter_##_classname() {}                                       \
     public:                                                                   \
       NS_DECL_ISUPPORTS                                                       \
       NS_IMETHOD GetName(nsACString &name)                                    \
         { name.AssignLiteral(_name); return NS_OK; }                          \
       NS_IMETHOD GetProcess(nsACString &process)                              \
         { process.Truncate(); return NS_OK; }                                 \
       NS_IMETHOD GetDescription(nsACString &desc)                             \
         { _desc_Function(desc); return NS_OK; }                               \
--- a/xpcom/base/nsInterfaceRequestorAgg.cpp
+++ b/xpcom/base/nsInterfaceRequestorAgg.cpp
@@ -24,19 +24,20 @@ public:
     : mFirst(aFirst)
     , mSecond(aSecond)
     , mConsumerTarget(aConsumerTarget)
   {
     if (!mConsumerTarget) {
       mConsumerTarget = NS_GetCurrentThread();
     }
   }
+
+private:
   ~nsInterfaceRequestorAgg();
 
-private:
   nsCOMPtr<nsIInterfaceRequestor> mFirst, mSecond;
   nsCOMPtr<nsIEventTarget> mConsumerTarget;
 };
 
 NS_IMPL_ISUPPORTS(nsInterfaceRequestorAgg, nsIInterfaceRequestor)
 
 NS_IMETHODIMP
 nsInterfaceRequestorAgg::GetInterface(const nsIID& aIID, void** aResult)
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -491,16 +491,18 @@ public:
     DUMP(mWriter, ", \"description\": \"");
     DUMP(mWriter, description);
     DUMP(mWriter, "\"}");
 
     return NS_OK;
   }
 
 private:
+  ~DumpReportCallback() {}
+
   bool mIsFirst;
   nsRefPtr<nsGZFileWriter> mWriter;
 };
 
 NS_IMPL_ISUPPORTS(DumpReportCallback, nsIHandleReportCallback)
 
 } // namespace mozilla
 
@@ -583,16 +585,18 @@ public:
     , mrFilename(aFilename)
     , mIdentifier(aIdentifier)
   {
   }
 
   NS_IMETHOD Callback(nsISupports* aData);
 
 private:
+  ~TempDirMemoryFinishCallback() {}
+
   nsRefPtr<nsGZFileWriter> mrWriter;
   nsCOMPtr<nsIFile> mrTmpFile;
   nsCString mrFilename;
   nsString mIdentifier;
 };
 
 NS_IMPL_ISUPPORTS(TempDirMemoryFinishCallback, nsIFinishReportingCallback)
 
@@ -818,16 +822,18 @@ public:
     if (!mFinishDumping) {
       return NS_OK;
     }
 
     return mFinishDumping->Callback(mFinishDumpingData);
   }
 
 private:
+  ~FinishReportingCallback() {}
+
   nsCOMPtr<nsIFinishDumpingCallback> mFinishDumping;
   nsCOMPtr<nsISupports> mFinishDumpingData;
 };
 
 NS_IMPL_ISUPPORTS(FinishReportingCallback, nsIFinishReportingCallback)
 
 NS_IMETHODIMP
 nsMemoryInfoDumper::DumpMemoryReportsToNamedFile(
--- a/xpcom/base/nsMemoryInfoDumper.h
+++ b/xpcom/base/nsMemoryInfoDumper.h
@@ -15,24 +15,24 @@ class nsACString;
  * This class facilitates dumping information about our memory usage to disk.
  *
  * Its cpp file also has Linux-only code which watches various OS signals and
  * dumps memory info upon receiving a signal.  You can activate these listeners
  * by calling Initialize().
  */
 class nsMemoryInfoDumper : public nsIMemoryInfoDumper
 {
+  virtual ~nsMemoryInfoDumper();
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMEMORYINFODUMPER
 
   nsMemoryInfoDumper();
-  virtual ~nsMemoryInfoDumper();
 
-public:
   static void Initialize();
 
 #ifdef MOZ_DMD
   static nsresult DumpDMD(const nsAString& aIdentifier);
 #endif
 };
 
 #define NS_MEMORY_INFO_DUMPER_CID \
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -113,16 +113,18 @@ ResidentFastDistinguishedAmount(int64_t*
 static nsresult
 ResidentUniqueDistinguishedAmount(int64_t* aN)
 {
   return GetProcSelfSmapsPrivate(aN);
 }
 
 class ResidentUniqueReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~ResidentUniqueReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     int64_t amount = 0;
     nsresult rv = ResidentUniqueDistinguishedAmount(&amount);
@@ -553,16 +555,18 @@ public:
   }
 };
 NS_IMPL_ISUPPORTS(PrivateReporter, nsIMemoryReporter)
 #endif
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
 class VsizeReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~VsizeReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     int64_t amount;
     nsresult rv = VsizeDistinguishedAmount(&amount);
@@ -578,16 +582,18 @@ public:
 "operating systems, 'resident' is a much better measure of the memory "
 "resources used by the process.");
   }
 };
 NS_IMPL_ISUPPORTS(VsizeReporter, nsIMemoryReporter)
 
 class ResidentReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~ResidentReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     int64_t amount;
     nsresult rv = ResidentDistinguishedAmount(&amount);
@@ -610,16 +616,18 @@ NS_IMPL_ISUPPORTS(ResidentReporter, nsIM
 #ifdef XP_UNIX
 
 #include <sys/resource.h>
 
 #define HAVE_PAGE_FAULT_REPORTERS 1
 
 class PageFaultsSoftReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~PageFaultsSoftReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     struct rusage usage;
     int err = getrusage(RUSAGE_SELF, &usage);
@@ -652,16 +660,18 @@ PageFaultsHardDistinguishedAmount(int64_
     return NS_ERROR_FAILURE;
   }
   *aAmount = usage.ru_majflt;
   return NS_OK;
 }
 
 class PageFaultsHardReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~PageFaultsHardReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     int64_t amount = 0;
     nsresult rv = PageFaultsHardDistinguishedAmount(&amount);
@@ -699,16 +709,18 @@ HeapOverheadRatio(jemalloc_stats_t* aSta
 {
   return (int64_t)10000 *
     (aStats->waste + aStats->bookkeeping + aStats->page_cache) /
     ((double)aStats->allocated);
 }
 
 class JemallocHeapReporter MOZ_FINAL : public nsIMemoryReporter
 {
+  ~JemallocHeapReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
@@ -803,16 +815,18 @@ NS_IMPL_ISUPPORTS(JemallocHeapReporter, 
 // registered with nsMemoryReporterManager entirely within nsAtomTable.cpp.
 // However, the obvious time to register it is when the table is initialized,
 // and that happens before XPCOM components are initialized, which means the
 // RegisterStrongMemoryReporter call fails.  So instead we do it here.
 class AtomTablesReporter MOZ_FINAL : public nsIMemoryReporter
 {
   MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
 
+  ~AtomTablesReporter() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
                            nsISupports* aData, bool aAnonymize)
   {
     return MOZ_COLLECT_REPORT(
       "explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
@@ -1438,28 +1452,32 @@ nsMemoryReporterManager::UnblockRegistra
   mIsRegistrationBlocked = false;
   return NS_OK;
 }
 
 // This is just a wrapper for int64_t that implements nsISupports, so it can be
 // passed to nsIMemoryReporter::CollectReports.
 class Int64Wrapper MOZ_FINAL : public nsISupports
 {
+  ~Int64Wrapper() {}
+
 public:
   NS_DECL_ISUPPORTS
   Int64Wrapper() : mValue(0)
   {
   }
   int64_t mValue;
 };
 
 NS_IMPL_ISUPPORTS0(Int64Wrapper)
 
 class ExplicitCallback MOZ_FINAL : public nsIHandleReportCallback
 {
+  ~ExplicitCallback() {}
+
 public:
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD Callback(const nsACString& aProcess, const nsACString& aPath,
                       int32_t aKind, int32_t aUnits, int64_t aAmount,
                       const nsACString& aDescription,
                       nsISupports* aWrappedExplicit)
   {
--- a/xpcom/base/nsMemoryReporterManager.h
+++ b/xpcom/base/nsMemoryReporterManager.h
@@ -19,22 +19,23 @@ class nsITimer;
 namespace mozilla {
 namespace dom {
 class MemoryReport;
 }
 }
 
 class nsMemoryReporterManager : public nsIMemoryReporterManager
 {
+  virtual ~nsMemoryReporterManager();
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIMEMORYREPORTERMANAGER
 
   nsMemoryReporterManager();
-  virtual ~nsMemoryReporterManager();
 
   // Gets the memory reporter manager service.
   static nsMemoryReporterManager* GetOrCreate()
   {
     nsCOMPtr<nsIMemoryReporterManager> imgr =
       do_GetService("@mozilla.org/memory-reporter-manager;1");
     return static_cast<nsMemoryReporterManager*>(imgr.get());
   }
--- a/xpcom/base/nsMessageLoop.cpp
+++ b/xpcom/base/nsMessageLoop.cpp
@@ -29,26 +29,25 @@ namespace {
  */
 class MessageLoopIdleTask
   : public Task
   , public SupportsWeakPtr<MessageLoopIdleTask>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(MessageLoopIdleTask)
   MessageLoopIdleTask(nsIRunnable* aTask, uint32_t aEnsureRunsAfterMS);
-  virtual ~MessageLoopIdleTask()
-  {
-  }
   virtual void Run();
 
 private:
   nsresult Init(uint32_t aEnsureRunsAfterMS);
 
   nsCOMPtr<nsIRunnable> mTask;
   nsCOMPtr<nsITimer> mTimer;
+
+  virtual ~MessageLoopIdleTask() {}
 };
 
 /**
  * This timer callback calls MessageLoopIdleTask::Run() when its timer fires.
  * (The timer can't call back into MessageLoopIdleTask directly since that's
  * not a refcounted object; it's owned by the MessageLoop.)
  *
  * We keep a weak reference to the MessageLoopIdleTask, although a raw pointer
@@ -56,23 +55,24 @@ private:
  * the MessageLoop deletes it), it cancels its timer.  But the weak pointer
  * saves us from worrying about an edge case somehow messing us up here.
  */
 class MessageLoopTimerCallback
   : public nsITimerCallback
 {
 public:
   MessageLoopTimerCallback(MessageLoopIdleTask* aTask);
-  virtual ~MessageLoopTimerCallback() {};
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSITIMERCALLBACK
 
 private:
   WeakPtr<MessageLoopIdleTask> mTask;
+
+  virtual ~MessageLoopTimerCallback() {}
 };
 
 MessageLoopIdleTask::MessageLoopIdleTask(nsIRunnable* aTask,
                                          uint32_t aEnsureRunsAfterMS)
   : mTask(aTask)
 {
   // Init() really shouldn't fail, but if it does, we schedule our runnable
   // immediately, because it's more important to guarantee that we run the task
--- a/xpcom/base/nsMessageLoop.h
+++ b/xpcom/base/nsMessageLoop.h
@@ -10,16 +10,17 @@
  * nsMessageLoop implements nsIMessageLoop, which wraps Chromium's MessageLoop
  * class and adds a bit of sugar.
  */
 class nsMessageLoop : public nsIMessageLoop
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMESSAGELOOP
 
+private:
   virtual ~nsMessageLoop()
   {
   }
 };
 
 #define NS_MESSAGE_LOOP_CID \
 {0x67b3ac0c, 0xd806, 0x4d48, \
 {0x93, 0x9e, 0x6a, 0x81, 0x9e, 0x6c, 0x24, 0x8f}}
--- a/xpcom/base/nsStatusReporterManager.h
+++ b/xpcom/base/nsStatusReporterManager.h
@@ -12,29 +12,30 @@
 class nsStatusReporter MOZ_FINAL : public nsIStatusReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTATUSREPORTER
 
   nsStatusReporter(nsACString& aProcess, nsACString& aDesc);
 
-  virtual ~nsStatusReporter();
-
-protected:
+private:
   nsCString sProcess;
   nsCString sName;
   nsCString sDesc;
+
+  virtual ~nsStatusReporter();
 };
 
 
 class nsStatusReporterManager : public nsIStatusReporterManager
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTATUSREPORTERMANAGER
 
   nsStatusReporterManager();
-  virtual ~nsStatusReporterManager();
 
 private:
   nsCOMArray<nsIStatusReporter> mReporters;
+
+  virtual ~nsStatusReporterManager();
 };
--- a/xpcom/base/nsVersionComparatorImpl.h
+++ b/xpcom/base/nsVersionComparatorImpl.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/Attributes.h"
 
 #include "nsIVersionComparator.h"
 
 class nsVersionComparatorImpl MOZ_FINAL : public nsIVersionComparator
 {
+  ~nsVersionComparatorImpl() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIVERSIONCOMPARATOR
 };
 
 #define NS_VERSIONCOMPARATOR_CONTRACTID "@mozilla.org/xpcom/version-comparator;1"
 
 // c6e47036-ca94-4be3-963a-9abd8705f7a8
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -375,16 +375,18 @@ private:
     NS_IMETHODIMP
     CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
                    bool aAnonymize)
     {
         return MOZ_COLLECT_REPORT(
             "explicit/icu", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
             "Memory used by ICU, a Unicode and globalization support library.");
     }
+
+    ~ICUReporter() {}
 };
 
 NS_IMPL_ISUPPORTS(ICUReporter, nsIMemoryReporter)
 
 /* static */ template<> Atomic<size_t> CountingAllocatorBase<ICUReporter>::sAmount(0);
 
 class OggReporter MOZ_FINAL : public nsIMemoryReporter,
                               public CountingAllocatorBase<OggReporter>
@@ -396,16 +398,18 @@ private:
     NS_IMETHODIMP
     CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
                    bool aAnonymize)
     {
         return MOZ_COLLECT_REPORT(
             "explicit/media/libogg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
             "Memory allocated through libogg for Ogg, Theora, and related media files.");
     }
+
+    ~OggReporter() {}
 };
 
 NS_IMPL_ISUPPORTS(OggReporter, nsIMemoryReporter)
 
 /* static */ template<> Atomic<size_t> CountingAllocatorBase<OggReporter>::sAmount(0);
 
 #ifdef MOZ_VPX
 class VPXReporter MOZ_FINAL : public nsIMemoryReporter,
@@ -418,16 +422,18 @@ private:
     NS_IMETHODIMP
     CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
                    bool aAnonymize)
     {
         return MOZ_COLLECT_REPORT(
             "explicit/media/libvpx", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
             "Memory allocated through libvpx for WebM media files.");
     }
+
+    ~VPXReporter() {}
 };
 
 NS_IMPL_ISUPPORTS(VPXReporter, nsIMemoryReporter)
 
 /* static */ template<> Atomic<size_t> CountingAllocatorBase<VPXReporter>::sAmount(0);
 #endif /* MOZ_VPX */
 
 #ifdef MOZ_WEBM
@@ -441,16 +447,18 @@ private:
     NS_IMETHODIMP
     CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData,
                    bool aAnonymize)
     {
         return MOZ_COLLECT_REPORT(
             "explicit/media/libnestegg", KIND_HEAP, UNITS_BYTES, MemoryAllocated(),
             "Memory allocated through libnestegg for WebM media files.");
     }
+
+    ~NesteggReporter() {}
 };
 
 NS_IMPL_ISUPPORTS(NesteggReporter, nsIMemoryReporter)
 
 /* static */ template<> Atomic<size_t> CountingAllocatorBase<NesteggReporter>::sAmount(0);
 #endif /* MOZ_WEBM */
 
 EXPORT_XPCOM_API(nsresult)
--- a/xpcom/components/ModuleUtils.h
+++ b/xpcom/components/ModuleUtils.h
@@ -99,16 +99,18 @@ static nsresult                         
 
 #include "nsIModule.h"
 #include "nsISupportsUtils.h"
 
 namespace mozilla {
 
 class GenericModule MOZ_FINAL : public nsIModule
 {
+    ~GenericModule() {}
+
 public:
     GenericModule(const mozilla::Module* aData)
         : mData(aData)
     {
     }
 
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIMODULE
--- a/xpcom/components/nsNativeComponentLoader.h
+++ b/xpcom/components/nsNativeComponentLoader.h
@@ -8,16 +8,26 @@
 
 #include "nsISupports.h"
 #include "mozilla/ModuleLoader.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "mozilla/Module.h"
 #include "prlink.h"
 
+class nsNativeModuleLoader;
+
+namespace mozilla {
+template<>
+struct HasDangerousPublicDestructor<nsNativeModuleLoader>
+{
+  static const bool value = true;
+};
+}
+
 class nsNativeModuleLoader : public mozilla::ModuleLoader
 {
  public:
     NS_DECL_ISUPPORTS_INHERITED
 
     nsNativeModuleLoader() {}
     ~nsNativeModuleLoader() {}
 
--- a/xpcom/ds/nsArray.h
+++ b/xpcom/ds/nsArray.h
@@ -59,16 +59,18 @@ private:
         : nsArrayBase()
     {
     }
     nsArray(const nsArray& other);
     nsArray(const nsCOMArray_base& aBaseArray)
         : nsArrayBase(aBaseArray)
     {
     }
+
+    ~nsArray() {}
 };
 
 class nsArrayCC MOZ_FINAL : public nsArrayBase
 {
     friend class nsArrayBase;
 
 public:
     NS_DECL_CYCLE_COLLECTING_ISUPPORTS
@@ -79,11 +81,13 @@ private:
         : nsArrayBase()
     {
     }
     nsArrayCC(const nsArrayCC& other);
     nsArrayCC(const nsCOMArray_base& aBaseArray)
         : nsArrayBase(aBaseArray)
     {
     }
+
+    ~nsArrayCC() {}
 };
 
 #endif
--- a/xpcom/ds/nsHashPropertyBag.cpp
+++ b/xpcom/ds/nsHashPropertyBag.cpp
@@ -88,17 +88,20 @@ nsHashPropertyBag::DeleteProperty(const 
     return NS_OK;
 }
 
 
 //
 // nsSimpleProperty class and impl; used for GetEnumerator
 //
 
-class nsSimpleProperty MOZ_FINAL : public nsIProperty {
+class nsSimpleProperty MOZ_FINAL : public nsIProperty
+{
+    ~nsSimpleProperty() {}
+
 public:
     nsSimpleProperty(const nsAString& aName, nsIVariant* aValue)
         : mName(aName), mValue(aValue)
     {
     }
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIPROPERTY
--- a/xpcom/ds/nsHashPropertyBag.h
+++ b/xpcom/ds/nsHashPropertyBag.h
@@ -11,31 +11,32 @@
 #include "nsIWritablePropertyBag2.h"
 #include "nsInterfaceHashtable.h"
 
 class nsHashPropertyBag : public nsIWritablePropertyBag
                                , public nsIWritablePropertyBag2
 {
 public:
     nsHashPropertyBag() { }
-    virtual ~nsHashPropertyBag() {}
 
     NS_DECL_THREADSAFE_ISUPPORTS
 
     NS_DECL_NSIPROPERTYBAG
 
     NS_DECL_NSIPROPERTYBAG2
 
     NS_DECL_NSIWRITABLEPROPERTYBAG
 
     NS_DECL_NSIWRITABLEPROPERTYBAG2
 
 protected:
     // a hash table of string -> nsIVariant
     nsInterfaceHashtable<nsStringHashKey, nsIVariant> mPropertyHash;
+
+    virtual ~nsHashPropertyBag() {}
 };
 
 // Note: NS_NewHashPropertyBag returns a HPB that
 // uses a non-thread-safe internal hash
 extern "C" nsresult
 NS_NewHashPropertyBag(nsIWritablePropertyBag* *_retval);
 
 #endif /* nsHashPropertyBag_h___ */
--- a/xpcom/ds/nsINIParserImpl.cpp
+++ b/xpcom/ds/nsINIParserImpl.cpp
@@ -7,16 +7,18 @@
 #include "nsINIParser.h"
 #include "nsStringEnumerator.h"
 #include "nsTArray.h"
 #include "mozilla/Attributes.h"
 
 class nsINIParserImpl MOZ_FINAL :
   public nsIINIParser
 {
+  ~nsINIParserImpl() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINIPARSER
 
   nsresult Init(nsIFile* aINIFile) {
     return mParser.Init(aINIFile);
   }
 
--- a/xpcom/ds/nsINIParserImpl.h
+++ b/xpcom/ds/nsINIParserImpl.h
@@ -15,15 +15,17 @@
 
 #define NS_INIPARSERFACTORY_CONTRACTID \
   "@mozilla.org/xpcom/ini-parser-factory;1"
 
 class nsINIParserFactory MOZ_FINAL :
   public nsIINIParserFactory,
   public nsIFactory
 {
+  ~nsINIParserFactory() {}
+
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIINIPARSERFACTORY
   NS_DECL_NSIFACTORY
 };
 
 #endif // nsINIParserImpl_h__
--- a/xpcom/ds/nsSupportsArray.h
+++ b/xpcom/ds/nsSupportsArray.h
@@ -8,21 +8,22 @@
 
 //#define DEBUG_SUPPORTSARRAY 1
 
 #include "nsISupportsArray.h"
 #include "mozilla/Attributes.h"
 
 static const uint32_t kAutoArraySize = 8;
 
-class nsSupportsArray MOZ_FINAL : public nsISupportsArray {
+class nsSupportsArray MOZ_FINAL : public nsISupportsArray
+{
+  ~nsSupportsArray(void); // nonvirtual since we're not subclassed
+
 public:
   nsSupportsArray(void);
-  ~nsSupportsArray(void); // nonvirtual since we're not subclassed
-
   static nsresult
   Create(nsISupports *aOuter, REFNSIID aIID, void **aResult);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   NS_DECL_NSISERIALIZABLE
 
   // nsICollection methods:
--- a/xpcom/glue/GenericFactory.h
+++ b/xpcom/glue/GenericFactory.h
@@ -15,16 +15,18 @@ namespace mozilla {
 
 /**
  * A generic factory which uses a constructor function to create instances.
  * This class is intended for use by the component manager and the generic
  * module.
  */
 class GenericFactory MOZ_FINAL : public nsIFactory
 {
+  ~GenericFactory() {}
+
 public:
   typedef Module::ConstructorProcPtr ConstructorProcPtr;
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIFACTORY
 
   GenericFactory(ConstructorProcPtr aCtor)
     : mCtor(aCtor)
--- a/xpcom/glue/nsCategoryCache.h
+++ b/xpcom/glue/nsCategoryCache.h
@@ -19,19 +19,20 @@
 #include "nsAutoPtr.h"
 #include "nsCOMArray.h"
 #include "nsInterfaceHashtable.h"
 
 #include "nsXPCOM.h"
 
 class NS_COM_GLUE nsCategoryObserver MOZ_FINAL : public nsIObserver
 {
+  ~nsCategoryObserver();
+
 public:
   nsCategoryObserver(const char* aCategory);
-  ~nsCategoryObserver();
 
   void ListenerDied();
   nsInterfaceHashtable<nsCStringHashKey, nsISupports>& GetHash()
   {
     return mHash;
   }
 
   NS_DECL_ISUPPORTS
--- a/xpcom/glue/nsThreadUtils.cpp
+++ b/xpcom/glue/nsThreadUtils.cpp
@@ -285,16 +285,18 @@ NS_ProcessNextEvent(nsIThread* aThread, 
 }
 
 #ifndef XPCOM_GLUE_AVOID_NSPR
 
 namespace {
 
 class nsNameThreadRunnable MOZ_FINAL : public nsIRunnable
 {
+  ~nsNameThreadRunnable() {}
+
 public:
   nsNameThreadRunnable(const nsACString& aName) : mName(aName) {}
 
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIRUNNABLE
 
 protected:
   const nsCString mName;
--- a/xpcom/io/nsAppFileLocationProvider.cpp
+++ b/xpcom/io/nsAppFileLocationProvider.cpp
@@ -446,42 +446,44 @@ public:
 
     *aResult = mNext;
     NS_IF_ADDREF(*aResult);
     mNext = nullptr;
 
     return *aResult ? NS_OK : NS_ERROR_FAILURE;
   }
 
-  // Virtual destructor since subclass nsPathsDirectoryEnumerator
-  // does not re-implement Release()
-
-  virtual ~nsAppDirectoryEnumerator()
-  {
-  }
-
 protected:
   nsIDirectoryServiceProvider* mProvider;
   const char** mCurrentKey;
   nsCOMPtr<nsIFile> mNext;
+
+  // Virtual destructor since subclass nsPathsDirectoryEnumerator
+  // does not re-implement Release()
+  virtual ~nsAppDirectoryEnumerator()
+  {
+  }
 };
 
 NS_IMPL_ISUPPORTS(nsAppDirectoryEnumerator, nsISimpleEnumerator)
 
 /* nsPathsDirectoryEnumerator and PATH_SEPARATOR
  * are not used on MacOS/X. */
 
 #if defined(XP_WIN) /* Win32 */
 #define PATH_SEPARATOR ';'
 #else
 #define PATH_SEPARATOR ':'
 #endif
 
-class nsPathsDirectoryEnumerator : public nsAppDirectoryEnumerator
+class nsPathsDirectoryEnumerator MOZ_FINAL
+  : public nsAppDirectoryEnumerator
 {
+  ~nsPathsDirectoryEnumerator() {}
+
 public:
   /**
    * aKeyList is a null-terminated list.
    * The first element is a path list.
    * The remainder are properties provided by aProvider.
    * They do not need to be publicly defined keys.
    */
   nsPathsDirectoryEnumerator(nsIDirectoryServiceProvider* aProvider,
--- a/xpcom/io/nsBinaryStream.h
+++ b/xpcom/io/nsBinaryStream.h
@@ -26,20 +26,16 @@
 // Derive from nsIObjectOutputStream so this class can be used as a superclass
 // by nsObjectOutputStream.
 class nsBinaryOutputStream : public nsIObjectOutputStream
 {
 public:
   nsBinaryOutputStream()
   {
   }
-  // virtual dtor since subclasses call our Release()
-  virtual ~nsBinaryOutputStream()
-  {
-  }
 
 protected:
   // nsISupports methods
   NS_DECL_ISUPPORTS
 
   // nsIOutputStream methods
   NS_DECL_NSIOUTPUTSTREAM
 
@@ -49,16 +45,22 @@ protected:
   // nsIObjectOutputStream methods
   NS_DECL_NSIOBJECTOUTPUTSTREAM
 
   // Call Write(), ensuring that all proffered data is written
   nsresult WriteFully(const char* aBuf, uint32_t aCount);
 
   nsCOMPtr<nsIOutputStream>       mOutputStream;
   nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+
+private:
+  // virtual dtor since subclasses call our Release()
+  virtual ~nsBinaryOutputStream()
+  {
+  }
 };
 
 #define NS_BINARYINPUTSTREAM_CID        \
 { /* c521a612-2aad-46db-b6ab-3b821fb150b1 */       \
    0xc521a612,                                     \
    0x2aad,                                         \
    0x46db,                                         \
   {0xb6, 0xab, 0x3b, 0x82, 0x1f, 0xb1, 0x50, 0xb1} \
@@ -69,31 +71,33 @@ protected:
 // Derive from nsIObjectInputStream so this class can be used as a superclass
 // by nsObjectInputStream.
 class nsBinaryInputStream : public nsIObjectInputStream
 {
 public:
   nsBinaryInputStream()
   {
   }
-  // virtual dtor since subclasses call our Release()
-  virtual ~nsBinaryInputStream()
-  {
-  }
 
 protected:
   // nsISupports methods
   NS_DECL_ISUPPORTS
 
   // nsIInputStream methods
   NS_DECL_NSIINPUTSTREAM
 
   // nsIBinaryInputStream methods
   NS_DECL_NSIBINARYINPUTSTREAM
 
   // nsIObjectInputStream methods
   NS_DECL_NSIOBJECTINPUTSTREAM
 
   nsCOMPtr<nsIInputStream>        mInputStream;
   nsCOMPtr<nsIStreamBufferAccess> mBufferAccess;
+
+private:
+  // virtual dtor since subclasses call our Release()
+  virtual ~nsBinaryInputStream()
+  {
+  }
 };
 
 #endif // nsBinaryStream_h___
--- a/xpcom/io/nsDirectoryService.h
+++ b/xpcom/io/nsDirectoryService.h
@@ -32,27 +32,28 @@ public:
 
   NS_DECL_NSIDIRECTORYSERVICE
 
   NS_DECL_NSIDIRECTORYSERVICEPROVIDER
 
   NS_DECL_NSIDIRECTORYSERVICEPROVIDER2
 
   nsDirectoryService();
-  ~nsDirectoryService();
 
   static void RealInit();
   void RegisterCategoryProviders();
 
   static nsresult
   Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
   static nsDirectoryService* gService;
 
 private:
+  ~nsDirectoryService();
+
   nsresult GetCurrentProcessDirectory(nsIFile** aFile);
 
   nsInterfaceHashtable<nsCStringHashKey, nsIFile> mHashtable;
   nsTArray<nsCOMPtr<nsIDirectoryServiceProvider>> mProviders;
 
 public:
 
 #define DIR_ATOM(name_, value_) static nsIAtom* name_;
--- a/xpcom/io/nsIOUtil.h
+++ b/xpcom/io/nsIOUtil.h
@@ -12,14 +12,16 @@
     { 0x84, 0x5f, 0xe5, 0x8a, 0x8e, 0x6d, 0xe4, 0xc2 } }
 
 
 #include "nsIIOUtil.h"
 #include "mozilla/Attributes.h"
 
 class nsIOUtil MOZ_FINAL : public nsIIOUtil
 {
+  ~nsIOUtil() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIIOUTIL
 };
 
 #endif /* nsIOUtil_h__ */
--- a/xpcom/io/nsStreamUtils.cpp
+++ b/xpcom/io/nsStreamUtils.cpp
@@ -228,21 +228,16 @@ public:
     , mEventIsPending(false)
     , mCloseSource(true)
     , mCloseSink(true)
     , mCanceled(false)
     , mCancelStatus(NS_OK)
   {
   }
 
-  // virtual since subclasses call superclass Release()
-  virtual ~nsAStreamCopier()
-  {
-  }
-
   // kick off the async copy...
   nsresult Start(nsIInputStream* aSource,
                  nsIOutputStream* aSink,
                  nsIEventTarget* aTarget,
                  nsAsyncCopyCallbackFun aCallback,
                  void* aClosure,
                  uint32_t aChunksize,
                  bool aCloseSource,
@@ -470,16 +465,21 @@ protected:
   void*                          mClosure;
   uint32_t                       mChunkSize;
   bool                           mEventInProcess;
   bool                           mEventIsPending;
   bool                           mCloseSource;
   bool                           mCloseSink;
   bool                           mCanceled;
   nsresult                       mCancelStatus;
+
+  // virtual since subclasses call superclass Release()
+  virtual ~nsAStreamCopier()
+  {
+  }
 };
 
 NS_IMPL_ISUPPORTS(nsAStreamCopier,
                   nsIInputStreamCallback,
                   nsIOutputStreamCallback,
                   nsIRunnable)
 
 class nsStreamCopierIB MOZ_FINAL : public nsAStreamCopier
--- a/xpcom/reflect/xptinfo/ShimInterfaceInfo.h
+++ b/xpcom/reflect/xptinfo/ShimInterfaceInfo.h
@@ -35,15 +35,17 @@ public:
     static already_AddRefed<ShimInterfaceInfo>
     MaybeConstruct(const char* aName, JSContext* cx);
 
 private:
     ShimInterfaceInfo(const nsIID& aIID,
                       const char* aName,
                       const mozilla::dom::NativePropertyHooks* aNativePropHooks);
 
+    ~ShimInterfaceInfo() {}
+
 private:
     nsIID mIID;
     nsAutoCString mName;
     const mozilla::dom::NativePropertyHooks* mNativePropHooks;
 };
 
 #endif
--- a/xpcom/tests/TestCOMArray.cpp
+++ b/xpcom/tests/TestCOMArray.cpp
@@ -20,20 +20,21 @@ public:
 
   NS_IMETHOD_(MozExternalRefCountType) RefCnt() = 0;
   NS_IMETHOD_(int32_t) ID() = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
 
 class Foo MOZ_FINAL : public IFoo {
+  ~Foo();
+
 public:
 
   Foo(int32_t aID);
-  ~Foo();
 
   // nsISupports implementation
   NS_DECL_ISUPPORTS
 
   // IFoo implementation
   NS_IMETHOD_(MozExternalRefCountType) RefCnt() { return mRefCnt; }
   NS_IMETHOD_(int32_t) ID() { return mID; }
 
@@ -73,24 +74,25 @@ public:
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(IBar, NS_IBAR_IID)
 
 class Bar MOZ_FINAL : public IBar {
 public:
 
   explicit Bar(nsCOMArray<IBar>& aArray);
-  ~Bar();
 
   // nsISupports implementation
   NS_DECL_ISUPPORTS
 
   static int32_t sReleaseCalled;
 
 private:
+  ~Bar();
+
   nsCOMArray<IBar>& mArray;
 };
 
 int32_t Bar::sReleaseCalled = 0;
 
 typedef nsCOMArray<IBar> Array2;
 
 Bar::Bar(Array2& aArray)
--- a/xpcom/tests/TestCallTemplates.cpp
+++ b/xpcom/tests/TestCallTemplates.cpp
@@ -31,16 +31,17 @@ class NS_NO_VTABLE nsITestService : publ
     NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITESTSERVICE_IID)
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsITestService, NS_ITESTSERVICE_IID)
 
 class nsTestService MOZ_FINAL : public nsITestService,
                                 public nsSupportsWeakReference
 {
+    ~nsTestService() {}
   public:
     NS_DECL_ISUPPORTS
 };
 
 NS_IMPL_ISUPPORTS(nsTestService, nsITestService, nsISupportsWeakReference)
 
 #define NS_TEST_SERVICE_CONTRACTID "@mozilla.org/test/testservice;1"
 #define NS_TEST_SERVICE_CID \
--- a/xpcom/tests/TestRacingServiceManager.cpp
+++ b/xpcom/tests/TestRacingServiceManager.cpp
@@ -82,16 +82,18 @@ public:
   }
 
 private:
   ReentrantMonitor** mReentrantMonitorPtr;
 };
 
 class Factory MOZ_FINAL : public nsIFactory
 {
+  ~Factory() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   Factory() : mFirstComponentCreated(false) { }
 
   NS_IMETHOD CreateInstance(nsISupports* aDelegate,
                             const nsIID& aIID,
                             void** aResult);
@@ -102,16 +104,18 @@ public:
 
   bool mFirstComponentCreated;
 };
 
 NS_IMPL_ISUPPORTS(Factory, nsIFactory)
 
 class Component1 MOZ_FINAL : public nsISupports
 {
+  ~Component1() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   Component1() {
     // This is the real test - make sure that only one instance is ever created.
     int32_t count = PR_AtomicIncrement(&gComponent1Count);
     TEST_ASSERTION(count == 1, "Too many components created!");
   }
@@ -121,16 +125,18 @@ NS_IMPL_ADDREF(Component1)
 NS_IMPL_RELEASE(Component1)
 
 NS_INTERFACE_MAP_BEGIN(Component1)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 class Component2 MOZ_FINAL : public nsISupports
 {
+  ~Component2() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   Component2() {
     // This is the real test - make sure that only one instance is ever created.
     int32_t count = PR_AtomicIncrement(&gComponent2Count);
     TEST_ASSERTION(count == 1, "Too many components created!");
   }
--- a/xpcom/tests/TestThreadPoolListener.cpp
+++ b/xpcom/tests/TestThreadPoolListener.cpp
@@ -42,16 +42,18 @@ static bool gAllThreadsShutDown = false;
     if (!(_test)) { \
       NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_test, __FILE__, __LINE__); \
     } \
   PR_END_MACRO
 #endif
 
 class Listener MOZ_FINAL : public nsIThreadPoolListener
 {
+  ~Listener() {}
+
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITHREADPOOLLISTENER
 };
 
 NS_IMPL_ISUPPORTS(Listener, nsIThreadPoolListener)
 
 NS_IMETHODIMP
--- a/xpcom/tests/TestThreadUtils.cpp
+++ b/xpcom/tests/TestThreadUtils.cpp
@@ -29,16 +29,24 @@ class nsFoo : public nsISupports {
   NS_DECL_ISUPPORTS
   nsresult DoFoo(bool* aBool) {
     *aBool = true;
     return NS_OK;
   }
   virtual ~nsFoo() {}
 };
 
+namespace mozilla {
+template<>
+struct HasDangerousPublicDestructor<nsFoo>
+{
+  static const bool value = true;
+};
+}
+
 NS_IMPL_ISUPPORTS0(nsFoo)
 
 class TestSuicide : public nsRunnable {
   NS_IMETHOD Run() {
     // Runs first time on thread "Suicide", then dies on MainThread
     if (!NS_IsMainThread()) {
       mThread = do_GetCurrentThread();
       NS_DispatchToMainThread(this);
@@ -50,18 +58,19 @@ class TestSuicide : public nsRunnable {
     return NS_OK;
   }
 
 private:
   nsCOMPtr<nsIThread> mThread;
 };
 
 class nsBar : public nsISupports {
+  virtual ~nsBar() {}
+public:
   NS_DECL_ISUPPORTS
-  virtual ~nsBar() {}
   void DoBar1(void) {
     gRunnableExecuted[TEST_CALL_VOID_ARG_VOID_RETURN] = true;
   }
   nsresult DoBar2(void) {
     gRunnableExecuted[TEST_CALL_VOID_ARG_NONVOID_RETURN] = true;
     return NS_OK;
   }
   void DoBar3(nsFoo* aFoo) {
--- a/xpcom/tests/TestTimers.cpp
+++ b/xpcom/tests/TestTimers.cpp
@@ -87,16 +87,18 @@ public:
     NS_ASSERTION(!*mThreadPtr, "Timer called back more than once!");
     *mThreadPtr = current;
 
     mon.Notify();
 
     return NS_OK;
   }
 private:
+  ~TimerCallback() {}
+
   nsIThread** mThreadPtr;
   ReentrantMonitor* mReentrantMonitor;
 };
 
 NS_IMPL_ISUPPORTS(TimerCallback, nsITimerCallback)
 
 nsresult
 TestTargetedTimers()