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 80865 f2184dfdda31eaa12898adffbbe10af1361f56b2
parent 80862 c3f33adc6080a1bbbd4b00b96cc5f1a3af50b9aa
child 80866 63e4de2dc4bb7c817cc4f02989a6b83b8ddc1582
push id628
push userclegnitto@mozilla.com
push dateWed, 21 Dec 2011 14:41:57 +0000
treeherdermozilla-aurora@24a61ad789e8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs700910
milestone11.0a1
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_ */