Bug 1331434 - Part 2: Add MOZ_MAY_CALL_AFTER_MUST_RETURN and MOZ_MUST_RETURN_FROM_CALLER annotations, r=ehsan
authorMichael Layzell <michael@thelayzells.com>
Tue, 28 Feb 2017 14:41:25 -0500
changeset 396961 8640e2712eef577a339d4d12b0c27af808a633ca
parent 396960 f539afe7ee0d3191d83b34034d1a7aa91e2c0a1e
child 396962 db7e54e6ee3c567218d0c9393f7dd9fa981204f7
push id1490
push usermtabara@mozilla.com
push dateMon, 31 Jul 2017 14:08:16 +0000
treeherdermozilla-release@70e32e6bf15e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1331434
milestone55.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 1331434 - Part 2: Add MOZ_MAY_CALL_AFTER_MUST_RETURN and MOZ_MUST_RETURN_FROM_CALLER annotations, r=ehsan MozReview-Commit-ID: 1o2egvdhkqT
dom/bindings/ErrorResult.h
js/public/Value.h
mfbt/RefPtr.h
xpcom/base/nsCOMPtr.h
--- a/dom/bindings/ErrorResult.h
+++ b/dom/bindings/ErrorResult.h
@@ -160,21 +160,58 @@ public:
     : TErrorResult()
   {
     AssignErrorCode(aRv);
   }
 
   operator ErrorResult&();
   operator OOMReporter&();
 
-  void Throw(nsresult rv) {
+  void MOZ_MUST_RETURN_FROM_CALLER Throw(nsresult rv) {
     MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
     AssignErrorCode(rv);
   }
 
+  // This method acts identically to the `Throw` method, however, it does not
+  // have the MOZ_MUST_RETURN_FROM_CALLER static analysis annotation. It is
+  // intended to be used in situations when additional work needs to be
+  // performed in the calling function after the Throw method is called.
+  //
+  // In general you should prefer using `Throw`, and returning after an error,
+  // for example:
+  //
+  //   if (condition) {
+  //     aRv.Throw(NS_ERROR_FAILURE);
+  //     return;
+  //   }
+  //
+  // or
+  //
+  //   if (condition) {
+  //     aRv.Throw(NS_ERROR_FAILURE);
+  //   }
+  //   return;
+  //
+  // However, if you need to do some other work after throwing, such as:
+  //
+  //   if (condition) {
+  //     aRv.ThrowWithCustomCleanup(NS_ERROR_FAILURE);
+  //   }
+  //   // Do some important clean-up work which couldn't happen earlier.
+  //   // We want to do this clean-up work in both the success and failure cases.
+  //   CleanUpImportantState();
+  //   return;
+  //
+  // Then you'll need to use ThrowWithCustomCleanup to get around the static
+  // analysis, which would complain that you are doing work after the call to
+  // `Throw()`.
+  void ThrowWithCustomCleanup(nsresult rv) {
+    Throw(rv);
+  }
+
   // Duplicate our current state on the given TErrorResult object.  Any
   // existing errors or messages on the target will be suppressed before
   // cloning.  Our own error state remains unchanged.
   void CloneTo(TErrorResult& aRv) const;
 
   // Use SuppressException when you want to suppress any exception that might be
   // on the TErrorResult.  After this call, the TErrorResult will be back a "no
   // exception thrown" state.
@@ -302,17 +339,17 @@ public:
 
   // Check whether the TErrorResult says to just throw whatever is on
   // the JSContext already.
   bool IsJSContextException() {
     return ErrorCode() == NS_ERROR_INTERNAL_ERRORRESULT_EXCEPTION_ON_JSCONTEXT;
   }
 
   // Support for uncatchable exceptions.
-  void ThrowUncatchableException() {
+  void MOZ_MUST_RETURN_FROM_CALLER ThrowUncatchableException() {
     Throw(NS_ERROR_UNCATCHABLE_EXCEPTION);
   }
   bool IsUncatchableException() const {
     return ErrorCode() == NS_ERROR_UNCATCHABLE_EXCEPTION;
   }
 
   void MOZ_ALWAYS_INLINE MightThrowJSException()
   {
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -961,17 +961,17 @@ static MOZ_ALWAYS_INLINE void
 ExposeValueToActiveJS(const Value& v)
 {
     if (v.isGCThing())
         js::gc::ExposeGCThingToActiveJS(GCCellPtr(v));
 }
 
 /************************************************************************/
 
-static inline Value
+static inline MOZ_MAY_CALL_AFTER_MUST_RETURN Value
 NullValue()
 {
     Value v;
     v.setNull();
     return v;
 }
 
 static inline constexpr Value
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -246,16 +246,17 @@ public:
   // ...exchange ownership with |aRhs|; can save a pair of refcount operations
   {
     T* temp = aRhs;
     aRhs = mRawPtr;
     mRawPtr = temp;
   }
 
   already_AddRefed<T>
+  MOZ_MAY_CALL_AFTER_MUST_RETURN
   forget()
   // return the value of mRawPtr and null out mRawPtr. Useful for
   // already_AddRefed return values.
   {
     T* temp = nullptr;
     swap(temp);
     return already_AddRefed<T>(temp);
   }
--- a/xpcom/base/nsCOMPtr.h
+++ b/xpcom/base/nsCOMPtr.h
@@ -712,17 +712,17 @@ public:
     NSCAP_ASSERT_NO_QUERY_NEEDED();
   }
 
 
   // Other pointer operators
 
   // Return the value of mRawPtr and null out mRawPtr. Useful for
   // already_AddRefed return values.
-  already_AddRefed<T> forget()
+  already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
   {
     T* temp = nullptr;
     swap(temp);
     return already_AddRefed<T>(temp);
   }
 
   // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
   // Useful to avoid unnecessary AddRef/Release pairs with "out" parameters