Bug 700910 - Implement MOZ_DELETE to encapsulate C++11 = delete syntax. r=cjones
authorJeff Walden <jwalden@mit.edu>
Tue, 08 Nov 2011 19:19:44 -0800
changeset 81705 f2184dfdda31eaa12898adffbbe10af1361f56b2
parent 81702 c3f33adc6080a1bbbd4b00b96cc5f1a3af50b9aa
child 81706 63e4de2dc4bb7c817cc4f02989a6b83b8ddc1582
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs700910
milestone11.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 700910 - Implement MOZ_DELETE to encapsulate C++11 = delete syntax. r=cjones
configure.in
js/src/configure.in
js/src/vm/String.h
layout/generic/nsFloatManager.h
mfbt/Types.h
--- a/configure.in
+++ b/configure.in
@@ -1839,16 +1839,26 @@ if test "$GNU_CXX"; then
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/mozilla-config.h'
     _USE_CPP_INCLUDE_FLAG=1
 
+    # Recent clang and gcc support C++11 deleted functions without warnings if
+    # compiling with -std=c++0x or -std=gnu++0x (or c++11 or gnu++11 in very new
+    # versions).  We can't use -std=c++0x yet, so gcc's support must remain
+    # unused.  But clang's warning can be disabled, so when compiling with clang
+    # we use it to opt out of the warning, enabling (macro-encapsulated) use of
+    # deleted function syntax.
+    if test "$CLANG_CXX"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions"
+    fi
+
     AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
                    ac_has_wno_invalid_offsetof,
         [
             AC_LANG_SAVE
             AC_LANG_CPLUSPLUS
             _SAVE_CXXFLAGS="$CXXFLAGS"
             CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
             AC_TRY_COMPILE([],
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1770,16 +1770,26 @@ if test "$GNU_CXX"; then
         _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wcast-align"
            ;;
        esac
     fi
 
     _DEFINES_CXXFLAGS='-DMOZILLA_CLIENT -include $(DEPTH)/js-confdefs.h'
     _USE_CPP_INCLUDE_FLAG=1
 
+    # Recent clang and gcc support C++11 deleted functions without warnings if
+    # compiling with -std=c++0x or -std=gnu++0x (or c++11 or gnu++11 in very new
+    # versions).  We can't use -std=c++0x yet, so gcc's support must remain
+    # unused.  But clang's warning can be disabled, so when compiling with clang
+    # we use it to opt out of the warning, enabling (macro-encapsulated) use of
+    # deleted function syntax.
+    if test "$CLANG_CXX"; then
+        _WARNINGS_CXXFLAGS="${_WARNINGS_CXXFLAGS} -Wno-c++0x-extensions"
+    fi
+
     AC_CACHE_CHECK(whether the compiler supports -Wno-invalid-offsetof,
                    ac_has_wno_invalid_offsetof,
         [
             AC_LANG_SAVE
             AC_LANG_CPLUSPLUS
             _SAVE_CXXFLAGS="$CXXFLAGS"
             CXXFLAGS="$CXXFLAGS ${_COMPILER_PREFIX}-Wno-invalid-offsetof"
             AC_TRY_COMPILE([],
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -445,19 +445,19 @@ class JSRope : public JSString
 
 JS_STATIC_ASSERT(sizeof(JSRope) == sizeof(JSString));
 
 class JSLinearString : public JSString
 {
     friend class JSString;
 
     /* Vacuous and therefore unimplemented. */
-    JSLinearString *ensureLinear(JSContext *cx);
-    bool isLinear() const;
-    JSLinearString &asLinear() const;
+    JSLinearString *ensureLinear(JSContext *cx) MOZ_DELETE;
+    bool isLinear() const MOZ_DELETE;
+    JSLinearString &asLinear() const MOZ_DELETE;
 
   public:
     void mark(JSTracer *trc);
 
     JS_ALWAYS_INLINE
     const jschar *chars() const {
         JS_ASSERT(JSString::isLinear());
         return d.u1.chars;
@@ -469,18 +469,18 @@ JS_STATIC_ASSERT(sizeof(JSLinearString) 
 class JSDependentString : public JSLinearString
 {
     friend class JSString;
     JSFixedString *undepend(JSContext *cx);
 
     void init(JSLinearString *base, const jschar *chars, size_t length);
 
     /* Vacuous and therefore unimplemented. */
-    bool isDependent() const;
-    JSDependentString &asDependent() const;
+    bool isDependent() const MOZ_DELETE;
+    JSDependentString &asDependent() const MOZ_DELETE;
 
   public:
     static inline JSDependentString *new_(JSContext *cx, JSLinearString *base,
                                           const jschar *chars, size_t length);
 
     JSLinearString *base() const {
         JS_ASSERT(JSString::isDependent());
         return d.s.u2.base;
@@ -493,19 +493,19 @@ class JSFlatString : public JSLinearStri
 {
     friend class JSRope;
     void morphExtensibleIntoDependent(JSLinearString *base) {
         d.lengthAndFlags = buildLengthAndFlags(length(), DEPENDENT_BIT);
         d.s.u2.base = base;
     }
 
     /* Vacuous and therefore unimplemented. */
-    JSFlatString *ensureFlat(JSContext *cx);
-    bool isFlat() const;
-    JSFlatString &asFlat() const;
+    JSFlatString *ensureFlat(JSContext *cx) MOZ_DELETE;
+    bool isFlat() const MOZ_DELETE;
+    JSFlatString &asFlat() const MOZ_DELETE;
 
   public:
     JS_ALWAYS_INLINE
     const jschar *charsZ() const {
         JS_ASSERT(JSString::isFlat());
         return chars();
     }
 
@@ -529,37 +529,37 @@ class JSFlatString : public JSLinearStri
     inline void finalize(JSRuntime *rt);
 };
 
 JS_STATIC_ASSERT(sizeof(JSFlatString) == sizeof(JSString));
 
 class JSExtensibleString : public JSFlatString
 {
     /* Vacuous and therefore unimplemented. */
-    bool isExtensible() const;
-    JSExtensibleString &asExtensible() const;
+    bool isExtensible() const MOZ_DELETE;
+    JSExtensibleString &asExtensible() const MOZ_DELETE;
 
   public:
     JS_ALWAYS_INLINE
     size_t capacity() const {
         JS_ASSERT(JSString::isExtensible());
         return d.s.u2.capacity;
     }
 };
 
 JS_STATIC_ASSERT(sizeof(JSExtensibleString) == sizeof(JSString));
 
 class JSFixedString : public JSFlatString
 {
     void init(const jschar *chars, size_t length);
 
     /* Vacuous and therefore unimplemented. */
-    JSFlatString *ensureFixed(JSContext *cx);
-    bool isFixed() const;
-    JSFixedString &asFixed() const;
+    JSFlatString *ensureFixed(JSContext *cx) MOZ_DELETE;
+    bool isFixed() const MOZ_DELETE;
+    JSFixedString &asFixed() const MOZ_DELETE;
 
   public:
     static inline JSFixedString *new_(JSContext *cx, const jschar *chars, size_t length);
 
     /*
      * Once a JSFixedString has been added to the atom state, this operation
      * changes the type (in place, as reflected by the flag bits) of the
      * JSFixedString into a JSAtom.
@@ -634,18 +634,18 @@ class JSExternalString : public JSFixedS
 {
     static void staticAsserts() {
         JS_STATIC_ASSERT(TYPE_LIMIT == 8);
     }
 
     void init(const jschar *chars, size_t length, intN type, void *closure);
 
     /* Vacuous and therefore unimplemented. */
-    bool isExternal() const;
-    JSExternalString &asExternal() const;
+    bool isExternal() const MOZ_DELETE;
+    JSExternalString &asExternal() const MOZ_DELETE;
 
   public:
     static inline JSExternalString *new_(JSContext *cx, const jschar *chars,
                                          size_t length, intN type, void *closure);
 
     intN externalType() const {
         JS_ASSERT(JSString::isExternal());
         JS_ASSERT(d.s.u2.externalType < TYPE_LIMIT);
@@ -677,18 +677,18 @@ class JSExternalString : public JSFixedS
     void finalize();
 };
 
 JS_STATIC_ASSERT(sizeof(JSExternalString) == sizeof(JSString));
 
 class JSAtom : public JSFixedString
 {
     /* Vacuous and therefore unimplemented. */
-    bool isAtom() const;
-    JSAtom &asAtom() const;
+    bool isAtom() const MOZ_DELETE;
+    JSAtom &asAtom() const MOZ_DELETE;
 
   public:
     /* Returns the PropertyName for this.  isIndex() must be false. */
     inline js::PropertyName *asPropertyName();
 
     inline void finalize(JSRuntime *rt);
 };
 
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -37,16 +37,18 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* class that manages rules for positioning floats */
 
 #ifndef nsFloatManager_h_
 #define nsFloatManager_h_
 
+#include "mozilla/Types.h"
+
 #include "nsIntervalSet.h"
 #include "nsCoord.h"
 #include "nsRect.h"
 #include "nsTArray.h"
 
 class nsIPresShell;
 class nsIFrame;
 struct nsHTMLReflowState;
@@ -339,18 +341,18 @@ private:
   // next page/column.  This means that any 'clear' needs to continue to
   // the next page/column.
   bool mSplitLeftFloatAcrossBreak;
   bool mSplitRightFloatAcrossBreak;
 
   static PRInt32 sCachedFloatManagerCount;
   static void* sCachedFloatManagers[NS_FLOAT_MANAGER_CACHE_SIZE];
 
-  nsFloatManager(const nsFloatManager&);  // no implementation
-  void operator=(const nsFloatManager&);  // no implementation
+  nsFloatManager(const nsFloatManager&) MOZ_DELETE;
+  void operator=(const nsFloatManager&) MOZ_DELETE;
 };
 
 /**
  * A helper class to manage maintenance of the float manager during
  * nsBlockFrame::Reflow. It automatically restores the old float
  * manager in the reflow state when the object goes out of scope.
  */
 class nsAutoFloatManager {
--- a/mfbt/Types.h
+++ b/mfbt/Types.h
@@ -83,9 +83,45 @@
 #else
 # define MFBT_API(type_)       MOZ_IMPORT_API(type_)
 #endif
 
 
 #define MOZ_BEGIN_EXTERN_C     JS_BEGIN_EXTERN_C
 #define MOZ_END_EXTERN_C       JS_END_EXTERN_C
 
+#ifdef __cplusplus
+
+/*
+ * 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 produce an error *at link time*,
+ * not at compile time, in compilers for which this macro can be implemented.
+ * For example, you can use this macro to produce classes with no implicit copy
+ * constructor or assignment operator:
+ *
+ *   struct NonCopyable {
+ *     private:
+ *       NonCopyable(const NonCopyable& other) MOZ_DELETE;
+ *       void operator=(const NonCopyable& other) MOZ_DELETE;
+ *   };
+ *
+ * If MOZ_DELETE can't be implemented for the current compiler, it will still
+ * cause an error, but at link time rather than 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))
+# define MOZ_DELETE            = delete
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))
+/*
+ * g++ >= 4.4 supports deleted functions, but it requires -std=c++0x or
+ * -std=gnu++0x, and for various reasons we can't use these yet.
+ */
+# define MOZ_DELETE            /* = delete */
+#else
+# define MOZ_DELETE            /* unknown C++11 deleted function support */
+#endif
+
+#endif /* __cplusplus */
+
 #endif  /* mozilla_Types_h_ */