From 8f98ecc84c9af2c7fe3a2ecf10995fb3e17cbc13 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Wed, 30 Jan 2013 15:32:44 -0800 Subject: [PATCH] Bug 836438 - Always implement nsresult using an unsigned 32-bit integer type. r=ehsan --HG-- extra : rebase_source : f9d9d7772decee36a27ef09eb018b9912bf7bf6b --- mfbt/TypedEnum.h | 4 +++ xpcom/base/Makefile.in | 4 +++ xpcom/base/nsError.h | 57 ++++++++++++++++++++++------------- xpcom/base/nsErrorAsserts.cpp | 5 ++- xpcom/base/nsErrorAssertsC.c | 12 ++++++++ xpcom/base/nscore.h | 2 -- 6 files changed, 60 insertions(+), 24 deletions(-) create mode 100644 xpcom/base/nsErrorAssertsC.c diff --git a/mfbt/TypedEnum.h b/mfbt/TypedEnum.h index 22f59decf2a..56ada45d609 100644 --- a/mfbt/TypedEnum.h +++ b/mfbt/TypedEnum.h @@ -10,6 +10,8 @@ #include "mozilla/Attributes.h" +#if defined(__cplusplus) + #if defined(__clang__) /* * Per Clang documentation, "Note that marketing version numbers should not @@ -211,4 +213,6 @@ inline int& operator>>=(int&, const Name::Enum&) MOZ_DELETE; #endif +#endif /* __cplusplus */ + #endif /* mozilla_TypedEnum_h_ */ diff --git a/xpcom/base/Makefile.in b/xpcom/base/Makefile.in index 51de8df8758..359ac08b8a6 100644 --- a/xpcom/base/Makefile.in +++ b/xpcom/base/Makefile.in @@ -54,6 +54,10 @@ ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) CPPSRCS += nsMacUtilsImpl.cpp endif +CSRCS = \ + nsErrorAssertsC.c \ + $(NULL) + EXPORTS = \ nsAgg.h \ nsAutoRef.h \ diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index b9310af9c7d..fa89a810243 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -7,12 +7,9 @@ #define nsError_h__ #include "mozilla/Likely.h" +#include "mozilla/StandardInteger.h" #include "mozilla/TypedEnum.h" -#ifndef nscore_h___ -#include "nscore.h" /* needed for nsresult */ -#endif - /* * To add error code to your module, you need to do the following: * @@ -120,16 +117,8 @@ * either can be converted to the other, so it's ambiguous. So we have to fall * back to a regular enum. */ -#if defined(__cplusplus) #if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) typedef enum class tag_nsresult : uint32_t -#elif defined(MOZ_HAVE_CXX11_ENUM_TYPE) - /* Need underlying type for workaround of Microsoft compiler (Bug 794734) */ - typedef enum tag_nsresult : uint32_t -#else - /* no strong enums */ - typedef enum tag_nsresult -#endif { #undef ERROR #define ERROR(key, val) key = val @@ -137,18 +126,44 @@ #undef ERROR } nsresult; -#if defined(MOZ_HAVE_CXX11_STRONG_ENUMS) - /* We're using enum classes, so we need #define's to put the constants in - * global scope for compatibility with old code. */ + /* + * enum classes don't place their initializers in the global scope, so we need + * #define's for compatibility with old code. + */ #include "ErrorListCxxDefines.h" -#endif -#else /* defined(__cplusplus) */ - /* C enum can't have a value outside the range of 'int'. - * C const can't initialize with an expression involving other variables - * even if it is const. So we have to fall back to bad old #defines. */ +#elif defined(MOZ_HAVE_CXX11_ENUM_TYPE) + typedef enum tag_nsresult : uint32_t + { + #undef ERROR + #define ERROR(key, val) key = val + #include "ErrorList.h" + #undef ERROR + } nsresult; +#elif defined(__cplusplus) + /* + * We're C++ in an old compiler lacking enum classes *and* typed enums (likely + * gcc < 4.5.1 as clang/MSVC have long supported one or both), or compiler + * support is unknown. Yet nsresult must have unsigned 32-bit representation. + * So just make it a typedef, and implement the constants with global consts. + */ + typedef uint32_t nsresult; + + const nsresult + #undef ERROR + #define ERROR(key, val) key = val + #include "ErrorList.h" + #undef ERROR + ; +#else + /* + * C doesn't have any way to fix the type underlying an enum, and enum + * initializers can't have values outside the range of 'int'. So typedef + * nsresult to the correct unsigned type, and fall back to using #defines for + * all error constants. + */ typedef uint32_t nsresult; #include "ErrorListCDefines.h" -#endif /* defined(__cplusplus) */ +#endif #undef SUCCESS_OR_FAILURE #undef SUCCESS diff --git a/xpcom/base/nsErrorAsserts.cpp b/xpcom/base/nsErrorAsserts.cpp index 1a7b38a6944..b987a7960e8 100644 --- a/xpcom/base/nsErrorAsserts.cpp +++ b/xpcom/base/nsErrorAsserts.cpp @@ -1,7 +1,10 @@ -#include "nsError.h" #include "mozilla/Assertions.h" +#include "nsError.h" + // No reason to pull in Assertions.h for every single file that includes // nsError.h, so let's put this in its own .cpp file instead of in the .h. +MOZ_STATIC_ASSERT(((nsresult)0) < ((nsresult)-1), + "nsresult must be an unsigned type"); MOZ_STATIC_ASSERT(sizeof(nsresult) == sizeof(uint32_t), "nsresult must be 32 bits"); diff --git a/xpcom/base/nsErrorAssertsC.c b/xpcom/base/nsErrorAssertsC.c new file mode 100644 index 00000000000..de73978f88b --- /dev/null +++ b/xpcom/base/nsErrorAssertsC.c @@ -0,0 +1,12 @@ +#include "mozilla/Assertions.h" + +#include "nsError.h" + +/* + * No reason to pull in Assertions.h for every single file that includes + * nsError.h, so let's put this in its own .c file instead of in the .h. + */ +MOZ_STATIC_ASSERT(((nsresult)0) < ((nsresult)-1), + "nsresult must be an unsigned type"); +MOZ_STATIC_ASSERT(sizeof(nsresult) == sizeof(uint32_t), + "nsresult must be 32 bits"); diff --git a/xpcom/base/nscore.h b/xpcom/base/nscore.h index 8ea5031c79b..e1e8f533d46 100644 --- a/xpcom/base/nscore.h +++ b/xpcom/base/nscore.h @@ -325,8 +325,6 @@ typedef unsigned long nsrefcnt; typedef uint32_t nsrefcnt; #endif -#include "nsError.h" - /* ------------------------------------------------------------------------ */ /* Casting macros for hiding C++ features from older compilers */