Bug 702437 - Implement MOZ_OVERRIDE to encapsulate support for the contextual override keyword on virtual member functions. r=cjones
authorJeff Walden <jwalden@mit.edu>
Mon, 14 Nov 2011 10:31:46 -0800
changeset 81977 d88e310d57815fb3312432e2fe0876ec78668008
parent 81976 cdf1844ffd59de32a87c25b67676f941e3ca0344
child 81978 67d6b8636246f6c20014194484edccbd9901f58f
push idunknown
push userunknown
push dateunknown
reviewerscjones
bugs702437
milestone11.0a1
Bug 702437 - Implement MOZ_OVERRIDE to encapsulate support for the contextual override keyword on virtual member functions. r=cjones
gfx/layers/basic/BasicLayers.cpp
js/src/jswrapper.h
mfbt/Types.h
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -38,16 +38,18 @@
 
 #include "gfxSharedImageSurface.h"
 
 #include "mozilla/layers/PLayerChild.h"
 #include "mozilla/layers/PLayersChild.h"
 #include "mozilla/layers/PLayersParent.h"
 #include "mozilla/gfx/2D.h"
 
+#include "mozilla/Types.h"
+
 #include "ipc/ShadowLayerChild.h"
 
 #include "BasicLayers.h"
 #include "ImageLayers.h"
 
 #include "nsTArray.h"
 #include "nsGUIEvent.h"
 #include "gfxContext.h"
@@ -2204,27 +2206,27 @@ public:
   virtual void SyncFrontBufferToBackBuffer();
 
 private:
   BasicShadowLayerManager* BasicManager()
   {
     return static_cast<BasicShadowLayerManager*>(mManager);
   }
 
-  NS_OVERRIDE virtual void
+  virtual void
   PaintBuffer(gfxContext* aContext,
               const nsIntRegion& aRegionToDraw,
               const nsIntRegion& aExtendedRegionToDraw,
               const nsIntRegion& aRegionToInvalidate,
               bool aDidSelfCopy,
               LayerManager::DrawThebesLayerCallback aCallback,
-              void* aCallbackData);
-
-  NS_OVERRIDE virtual already_AddRefed<gfxASurface>
-  CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize);
+              void* aCallbackData) MOZ_OVERRIDE;
+
+  virtual already_AddRefed<gfxASurface>
+  CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize) MOZ_OVERRIDE;
 
   void DestroyBackBuffer()
   {
     if (IsSurfaceDescriptorValid(mBackBuffer)) {
       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(&mBackBuffer);
     }
   }
 
--- a/js/src/jswrapper.h
+++ b/js/src/jswrapper.h
@@ -37,16 +37,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef jswrapper_h___
 #define jswrapper_h___
 
+#include "mozilla/Types.h"
+
 #include "jsapi.h"
 #include "jsproxy.h"
 
 namespace js {
 
 /* No-op wrapper handler base class. */
 class JS_FRIEND_API(Wrapper) : public ProxyHandler
 {
@@ -57,47 +59,47 @@ class JS_FRIEND_API(Wrapper) : public Pr
     explicit Wrapper(uintN flags);
 
     typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission;
 
     virtual ~Wrapper();
 
     /* ES5 Harmony fundamental wrapper traps. */
     virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
-                                       PropertyDescriptor *desc);
+                                       PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
-                                          PropertyDescriptor *desc);
+                                          PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
-                                PropertyDescriptor *desc);
-    virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
-    virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
-    virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp);
+                                PropertyDescriptor *desc) MOZ_OVERRIDE;
+    virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
+    virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
+    virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
 
     /* ES5 Harmony derived wrapper traps. */
-    virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp);
+    virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
     virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
-                     Value *vp);
-    virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
-    virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp);
+                     Value *vp) MOZ_OVERRIDE;
+    virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
+    virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp) MOZ_OVERRIDE;
 
     /* Spidermonkey extensions. */
-    virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, Value *vp);
-    virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, Value *rval);
-    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args);
-    virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp);
-    virtual JSType typeOf(JSContext *cx, JSObject *proxy);
-    virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
-    virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper);
-    virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
-    virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp);
+    virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, Value *vp) MOZ_OVERRIDE;
+    virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, Value *rval) MOZ_OVERRIDE;
+    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
+    virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
+    virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
+    virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
+    virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
+    virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent) MOZ_OVERRIDE;
+    virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
 
-    virtual void trace(JSTracer *trc, JSObject *wrapper);
+    virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
 
     /* Policy enforcement traps. */
     enum Action { GET, SET, CALL };
     virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
     virtual void leave(JSContext *cx, JSObject *wrapper);
 
     static Wrapper singleton;
 
@@ -120,44 +122,44 @@ class JS_FRIEND_API(CrossCompartmentWrap
 {
   public:
     CrossCompartmentWrapper(uintN flags);
 
     virtual ~CrossCompartmentWrapper();
 
     /* ES5 Harmony fundamental wrapper traps. */
     virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
-                                       PropertyDescriptor *desc);
+                                       PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
-                                          PropertyDescriptor *desc);
+                                          PropertyDescriptor *desc) MOZ_OVERRIDE;
     virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
-                                PropertyDescriptor *desc);
-    virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
-    virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
+                                PropertyDescriptor *desc) MOZ_OVERRIDE;
+    virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
+    virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
 
     /* ES5 Harmony derived wrapper traps. */
-    virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp);
-    virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp);
+    virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
+    virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
     virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
-                     Value *vp);
-    virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props);
-    virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp);
+                     Value *vp) MOZ_OVERRIDE;
+    virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
+    virtual bool iterate(JSContext *cx, JSObject *wrapper, uintN flags, Value *vp) MOZ_OVERRIDE;
 
     /* Spidermonkey extensions. */
-    virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, Value *vp);
-    virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, Value *rval);
-    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args);
-    virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp);
-    virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper);
-    virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
-    virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp);
+    virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, Value *vp) MOZ_OVERRIDE;
+    virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, Value *rval) MOZ_OVERRIDE;
+    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
+    virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
+    virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
+    virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent) MOZ_OVERRIDE;
+    virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
 
-    virtual void trace(JSTracer *trc, JSObject *wrapper);
+    virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
 
     static CrossCompartmentWrapper singleton;
 };
 
 /*
  * Base class for security wrappers. A security wrapper is potentially hiding
  * all or part of some wrapped object thus SecurityWrapper defaults to denying
  * access to the wrappee. This is the opposite of Wrapper which tries to be
@@ -167,18 +169,18 @@ class JS_FRIEND_API(CrossCompartmentWrap
  * access, relying on derived SecurityWrapper to block access when necessary.
  */
 template <class Base>
 class JS_FRIEND_API(SecurityWrapper) : public Base
 {
   public:
     SecurityWrapper(uintN flags);
 
-    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args);
-    virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
+    virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
+    virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
 };
 
 typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
 typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
 
 /*
  * A hacky class that lets a friend force a fake frame. We must already be
  * in the compartment of |target| when we enter the forced frame.
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -86,16 +86,53 @@
 
 
 #define MOZ_BEGIN_EXTERN_C     JS_BEGIN_EXTERN_C
 #define MOZ_END_EXTERN_C       JS_END_EXTERN_C
 
 #ifdef __cplusplus
 
 /*
+ * g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
+ * without warnings (functionality used by the macros below).  These modes are
+ * detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more
+ * standardly, by checking whether __cplusplus has a C++11 or greater value.
+ * Current versions of g++ do not correctly set __cplusplus, so we check both
+ * for forward compatibility.
+ */
+#if defined(__clang__)
+# if __clang_major__ >= 3
+#  define MOZ_HAVE_CXX11_DELETE
+#  define MOZ_HAVE_CXX11_OVERRIDE
+# elif __clang_major__ == 2
+#  if __clang_minor__ >= 9
+#   define MOZ_HAVE_CXX11_DELETE
+#  endif
+# endif
+#elif defined(__GNUC__)
+# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
+#  if __GNUC__ > 4
+#   define MOZ_HAVE_CXX11_DELETE
+#   define MOZ_HAVE_CXX11_OVERRIDE
+#  elif __GNUC__ == 4
+#   if __GNUC_MINOR__ >= 7
+#    define MOZ_HAVE_CXX11_OVERRIDE
+#   endif
+#   if __GNUC_MINOR__ >= 4
+#    define MOZ_HAVE_CXX11_DELETE
+#   endif
+#  endif
+# endif
+#elif defined(_MSC_VER)
+# if _MSC_VER >= 1400
+#  define MOZ_HAVE_CXX11_OVERRIDE
+# endif
+#endif
+
+/*
  * MOZ_DELETE, specified immediately prior to the ';' terminating an undefined-
  * method declaration, attempts to delete that method from the corresponding
  * class.  An attempt to use the method will always produce an error *at compile
  * time* (instead of sometimes as late as link time) when this macro can be
  * implemented.  For example, you can use MOZ_DELETE to produce classes with no
  * implicit copy constructor or assignment operator:
  *
  *   struct NonCopyable
@@ -107,30 +144,58 @@
  *
  * If MOZ_DELETE can't be implemented for the current compiler, use of the
  * annotated method will still cause an error, but the error might occur at link
  * time in some cases rather than at compile time.
  *
  * MOZ_DELETE relies on C++11 functionality not universally implemented.  As a
  * backstop, method declarations using MOZ_DELETE should be private.
  */
-#if defined(__clang__) && (__clang_major__ >= 3 || (__clang_major__ == 2 && __clang_minor__ >= 9))
+#if defined(MOZ_HAVE_CXX11_DELETE)
 # define MOZ_DELETE            = delete
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
- /*
-  * g++ >= 4.4 requires -std=c++0x or -std=gnu++0x to support deleted functions
-  * without warnings.  These modes are detectable by the experimental macro used
-  * below or, more standardly, by checking whether __cplusplus has a C++11 or
-  * greater value.  Current versions of g++ do not correctly set __cplusplus, so
-  * we check both for forward compatibility.
-  */
-# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
-#  define MOZ_DELETE           = delete
-# else
-#  define MOZ_DELETE           /* = delete */
-# endif
 #else
-# define MOZ_DELETE            /* no = delete support, or unknown support */
+# define MOZ_DELETE            /* no support */
+#endif
+
+/*
+ * MOZ_OVERRIDE explicitly indicates that a virtual member function in a class
+ * overrides a member function of a base class, rather than potentially being a
+ * new member function.  MOZ_OVERRIDE should be placed immediately before the
+ * ';' terminating the member function's declaration, or before '= 0;' if the
+ * member function is pure.  If the member function is defined in the class
+ * definition, it should appear before the opening brace of the function body.
+ *
+ *   class Base
+ *   {
+ *     public:
+ *       virtual void f() = 0;
+ *   };
+ *   class Derived1 : public Base
+ *   {
+ *     public:
+ *       virtual void f() MOZ_OVERRIDE;
+ *   };
+ *   class Derived2 : public Base
+ *   {
+ *     public:
+ *       virtual void f() MOZ_OVERRIDE = 0;
+ *   };
+ *   class Derived3 : public Base
+ *   {
+ *     public:
+ *       virtual void f() MOZ_OVERRIDE { }
+ *   };
+ *
+ * In compilers supporting C++11 override controls, MOZ_OVERRIDE *requires* that
+ * the function marked with it override a member function of a base class: it
+ * is a compile error if it does not.  Otherwise MOZ_OVERRIDE does not affect
+ * semantics and merely documents the override relationship to the reader (but
+ * of course must still be used correctly to not break C++11 compilers).
+ */
+#if defined(MOZ_HAVE_CXX11_OVERRIDE)
+# define MOZ_OVERRIDE          override
+#else
+# define MOZ_OVERRIDE          /* no support */
 #endif
 
 #endif /* __cplusplus */
 
 #endif  /* mozilla_Types_h_ */