зеркало из https://github.com/mozilla/gecko-dev.git
Bug 712129 - Implement MOZ_STATIC_ASSERT and MOZ_STATIC_ASSERT_IF. r=luke
This commit is contained in:
Родитель
677b43a2b8
Коммит
a158abd5b6
|
@ -89,33 +89,8 @@ JS_BEGIN_EXTERN_C
|
||||||
# define JS_THREADSAFE_ASSERT(expr) ((void) 0)
|
# define JS_THREADSAFE_ASSERT(expr) ((void) 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
#define JS_STATIC_ASSERT(cond) MOZ_STATIC_ASSERT(cond, "JS_STATIC_ASSERT")
|
||||||
* JS_STATIC_ASSERT
|
#define JS_STATIC_ASSERT_IF(cond, expr) MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
|
||||||
*
|
|
||||||
* A compile-time assert. "cond" must be a constant expression. The macro can
|
|
||||||
* be used only in places where an "extern" declaration is allowed.
|
|
||||||
*/
|
|
||||||
#ifdef __SUNPRO_CC
|
|
||||||
/*
|
|
||||||
* Sun Studio C++ compiler has a bug
|
|
||||||
* "sizeof expression not accepted as size of array parameter"
|
|
||||||
* It happens when js_static_assert() function is declared inside functions.
|
|
||||||
* The bug number is 6688515. It is not public yet.
|
|
||||||
* Therefore, for Sun Studio, declare js_static_assert as an array instead.
|
|
||||||
*/
|
|
||||||
# define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
|
|
||||||
#else
|
|
||||||
# ifdef __COUNTER__
|
|
||||||
# define JS_STATIC_ASSERT_GLUE1(x,y) x##y
|
|
||||||
# define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
|
|
||||||
# define JS_STATIC_ASSERT(cond) \
|
|
||||||
typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
|
|
||||||
# else
|
|
||||||
# define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Abort the process in a non-graceful manner. This will cause a core file,
|
* Abort the process in a non-graceful manner. This will cause a core file,
|
||||||
|
|
|
@ -43,6 +43,87 @@
|
||||||
|
|
||||||
#include "mozilla/Types.h"
|
#include "mozilla/Types.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MOZ_STATIC_ASSERT may be used to assert a condition *at compile time*. This
|
||||||
|
* can be useful when you make certain assumptions about what must hold for
|
||||||
|
* optimal, or even correct, behavior. For example, you might assert that the
|
||||||
|
* size of a struct is a multiple of the target architecture's word size:
|
||||||
|
*
|
||||||
|
* struct S { ... };
|
||||||
|
* MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
|
||||||
|
* "S should be a multiple of word size for efficiency");
|
||||||
|
*
|
||||||
|
* This macro can be used in any location where both an extern declaration and a
|
||||||
|
* typedef could be used.
|
||||||
|
*
|
||||||
|
* Be aware of the gcc 4.2 concerns noted further down when writing patches that
|
||||||
|
* use this macro, particularly if a patch only bounces on OS X.
|
||||||
|
*/
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# if defined(__clang__)
|
||||||
|
# ifndef __has_extension
|
||||||
|
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||||
|
# endif
|
||||||
|
# if __has_extension(cxx_static_assert)
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), reason)
|
||||||
|
# endif
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && \
|
||||||
|
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), #cond)
|
||||||
|
# endif
|
||||||
|
# elif defined(_MSC_VER)
|
||||||
|
# if _MSC_VER >= 1600 /* MSVC 10 */
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), #cond)
|
||||||
|
# endif
|
||||||
|
# elif defined(__HP_aCC)
|
||||||
|
# if __HP_aCC >= 62500 && defined(_HP_CXX0x_SOURCE)
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), #cond)
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
#ifndef MOZ_STATIC_ASSERT
|
||||||
|
# define MOZ_STATIC_ASSERT_GLUE1(x, y) x##y
|
||||||
|
# define MOZ_STATIC_ASSERT_GLUE(x, y) MOZ_STATIC_ASSERT_GLUE1(x, y)
|
||||||
|
# if defined(__SUNPRO_CC)
|
||||||
|
/*
|
||||||
|
* The Sun Studio C++ compiler is buggy when declaring, inside a function,
|
||||||
|
* another extern'd function with an array argument whose length contains a
|
||||||
|
* sizeof, triggering the error message "sizeof expression not accepted as
|
||||||
|
* size of array parameter". This bug (6688515, not public yet) would hit
|
||||||
|
* defining moz_static_assert as a function, so we always define an extern
|
||||||
|
* array for Sun Studio.
|
||||||
|
*
|
||||||
|
* We include the line number in the symbol name in a best-effort attempt
|
||||||
|
* to avoid conflicts (see below).
|
||||||
|
*/
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||||
|
extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
|
||||||
|
# elif defined(__COUNTER__)
|
||||||
|
/*
|
||||||
|
* If there was no preferred alternative, use a compiler-agnostic version.
|
||||||
|
*
|
||||||
|
* Note that the non-__COUNTER__ version has a bug in C++: it can't be used
|
||||||
|
* in both |extern "C"| and normal C++ in the same translation unit. (Alas
|
||||||
|
* |extern "C"| isn't allowed in a function.) The only affected compiler
|
||||||
|
* we really care about is gcc 4.2. For that compiler and others like it,
|
||||||
|
* we include the line number in the function name to do the best we can to
|
||||||
|
* avoid conflicts. These should be rare: a conflict would require use of
|
||||||
|
* MOZ_STATIC_ASSERT on the same line in separate files in the same
|
||||||
|
* translation unit, *and* the uses would have to be in code with
|
||||||
|
* different linkage, *and* the first observed use must be in C++-linkage
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||||
|
typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1]
|
||||||
|
# else
|
||||||
|
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||||
|
extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1])
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* XXX: we're cheating here in order to avoid creating object files
|
* XXX: we're cheating here in order to avoid creating object files
|
||||||
* for mfbt /just/ to provide a function like FatalError() to be used
|
* for mfbt /just/ to provide a function like FatalError() to be used
|
||||||
|
|
|
@ -36,6 +36,8 @@
|
||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
|
||||||
#include "nsAtomTable.h"
|
#include "nsAtomTable.h"
|
||||||
#include "nsStaticAtom.h"
|
#include "nsStaticAtom.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
@ -406,16 +408,17 @@ GetAtomHashEntry(const PRUnichar* aString, PRUint32 aLength)
|
||||||
class CheckStaticAtomSizes
|
class CheckStaticAtomSizes
|
||||||
{
|
{
|
||||||
CheckStaticAtomSizes() {
|
CheckStaticAtomSizes() {
|
||||||
PR_STATIC_ASSERT((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
|
MOZ_STATIC_ASSERT((sizeof(nsFakeStringBuffer<1>().mRefCnt) ==
|
||||||
sizeof(nsStringBuffer().mRefCount)) &&
|
sizeof(nsStringBuffer().mRefCount)) &&
|
||||||
(sizeof(nsFakeStringBuffer<1>().mSize) ==
|
(sizeof(nsFakeStringBuffer<1>().mSize) ==
|
||||||
sizeof(nsStringBuffer().mStorageSize)) &&
|
sizeof(nsStringBuffer().mStorageSize)) &&
|
||||||
(offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
|
(offsetof(nsFakeStringBuffer<1>, mRefCnt) ==
|
||||||
offsetof(nsStringBuffer, mRefCount)) &&
|
offsetof(nsStringBuffer, mRefCount)) &&
|
||||||
(offsetof(nsFakeStringBuffer<1>, mSize) ==
|
(offsetof(nsFakeStringBuffer<1>, mSize) ==
|
||||||
offsetof(nsStringBuffer, mStorageSize)) &&
|
offsetof(nsStringBuffer, mStorageSize)) &&
|
||||||
(offsetof(nsFakeStringBuffer<1>, mStringData) ==
|
(offsetof(nsFakeStringBuffer<1>, mStringData) ==
|
||||||
sizeof(nsStringBuffer)));
|
sizeof(nsStringBuffer)),
|
||||||
|
"mocked-up strings' representations should be compatible");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -64,12 +64,12 @@ const nsTArrayHeader* nsTArray_base<Alloc>::GetAutoArrayBufferUnsafe(size_t elem
|
||||||
// If we're on a 32-bit system and elemAlign is 8, we need to adjust our
|
// If we're on a 32-bit system and elemAlign is 8, we need to adjust our
|
||||||
// pointer to take into account the extra alignment in the auto array.
|
// pointer to take into account the extra alignment in the auto array.
|
||||||
|
|
||||||
// Check that the auto array is padded as we expect.
|
MOZ_STATIC_ASSERT(sizeof(void*) != 4 ||
|
||||||
PR_STATIC_ASSERT(sizeof(void*) != 4 ||
|
(MOZ_ALIGNOF(mozilla::AlignedElem<8>) == 8 &&
|
||||||
(MOZ_ALIGNOF(mozilla::AlignedElem<8>) == 8 &&
|
sizeof(nsAutoTArray<mozilla::AlignedElem<8>, 1>) ==
|
||||||
sizeof(nsAutoTArray<mozilla::AlignedElem<8>, 1>) ==
|
sizeof(void*) + sizeof(nsTArrayHeader) +
|
||||||
sizeof(void*) + sizeof(nsTArrayHeader) +
|
4 + sizeof(mozilla::AlignedElem<8>)),
|
||||||
4 + sizeof(mozilla::AlignedElem<8>)));
|
"auto array padding wasn't what we expected");
|
||||||
|
|
||||||
// We don't support alignments greater than 8 bytes.
|
// We don't support alignments greater than 8 bytes.
|
||||||
NS_ABORT_IF_FALSE(elemAlign <= 4 || elemAlign == 8, "unsupported alignment.");
|
NS_ABORT_IF_FALSE(elemAlign <= 4 || elemAlign == 8, "unsupported alignment.");
|
||||||
|
@ -115,7 +115,8 @@ bool nsTArray_base<Alloc>::UsesAutoArrayBuffer() const {
|
||||||
// owned by this nsAutoTArray. We statically assert that elem_type's
|
// owned by this nsAutoTArray. We statically assert that elem_type's
|
||||||
// alignment is 8 bytes or less in nsAutoArrayBase.
|
// alignment is 8 bytes or less in nsAutoArrayBase.
|
||||||
|
|
||||||
PR_STATIC_ASSERT(sizeof(nsTArrayHeader) > 4);
|
MOZ_STATIC_ASSERT(sizeof(nsTArrayHeader) > 4,
|
||||||
|
"see comment above");
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
PRPtrdiff diff = reinterpret_cast<const char*>(GetAutoArrayBuffer(8)) -
|
PRPtrdiff diff = reinterpret_cast<const char*>(GetAutoArrayBuffer(8)) -
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#ifndef nsTArray_h__
|
#ifndef nsTArray_h__
|
||||||
#define nsTArray_h__
|
#define nsTArray_h__
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/Util.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "prtypes.h"
|
#include "prtypes.h"
|
||||||
|
@ -47,7 +50,6 @@
|
||||||
#include "nsQuickSort.h"
|
#include "nsQuickSort.h"
|
||||||
#include "nsDebug.h"
|
#include "nsDebug.h"
|
||||||
#include "nsTraceRefcnt.h"
|
#include "nsTraceRefcnt.h"
|
||||||
#include "mozilla/Util.h"
|
|
||||||
#include NEW_H
|
#include NEW_H
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1316,9 +1318,9 @@ private:
|
||||||
friend class nsTArray_base;
|
friend class nsTArray_base;
|
||||||
|
|
||||||
void Init() {
|
void Init() {
|
||||||
// We can't handle alignments greater than 8; see
|
MOZ_STATIC_ASSERT(MOZ_ALIGNOF(elem_type) <= 8,
|
||||||
// nsTArray_base::UsesAutoArrayBuffer().
|
"can't handle alignments greater than 8, "
|
||||||
PR_STATIC_ASSERT(MOZ_ALIGNOF(elem_type) <= 8);
|
"see nsTArray_base::UsesAutoArrayBuffer()");
|
||||||
|
|
||||||
*base_type::PtrToHdr() = reinterpret_cast<Header*>(&mAutoBuf);
|
*base_type::PtrToHdr() = reinterpret_cast<Header*>(&mAutoBuf);
|
||||||
base_type::Hdr()->mLength = 0;
|
base_type::Hdr()->mLength = 0;
|
||||||
|
@ -1367,8 +1369,10 @@ public:
|
||||||
// 64-bit system, where the compiler inserts 4 bytes of padding at the end of
|
// 64-bit system, where the compiler inserts 4 bytes of padding at the end of
|
||||||
// the auto array to make its size a multiple of alignof(void*) == 8 bytes.
|
// the auto array to make its size a multiple of alignof(void*) == 8 bytes.
|
||||||
|
|
||||||
PR_STATIC_ASSERT(sizeof(nsAutoTArray<PRUint32, 2>) ==
|
MOZ_STATIC_ASSERT(sizeof(nsAutoTArray<PRUint32, 2>) ==
|
||||||
sizeof(void*) + sizeof(nsTArrayHeader) + sizeof(PRUint32) * 2);
|
sizeof(void*) + sizeof(nsTArrayHeader) + sizeof(PRUint32) * 2,
|
||||||
|
"nsAutoTArray shouldn't contain any extra padding, "
|
||||||
|
"see the comment");
|
||||||
|
|
||||||
template<class E, PRUint32 N>
|
template<class E, PRUint32 N>
|
||||||
class AutoFallibleTArray : public nsAutoArrayBase<FallibleTArray<E>, N>
|
class AutoFallibleTArray : public nsAutoArrayBase<FallibleTArray<E>, N>
|
||||||
|
|
Загрузка…
Ссылка в новой задаче