--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -309,17 +309,16 @@ MOZ_CrashPrintf(const char* aFilename, i
* information is desired than a string literal can supply. The caller provides
* a printf-style format string, which must be a string literal and between
* 1 and 4 additional arguments. A regular MOZ_CRASH() is preferred wherever
* possible, as passing arbitrary strings to printf from a potentially
* compromised process is not without risk.
*/
#define MOZ_CRASH_UNSAFE_PRINTF(format, ...) \
do { \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
static_assert( \
MOZ_PASTE_PREFIX_AND_ARG_COUNT(, __VA_ARGS__) <= sPrintfMaxArgs, \
"Only up to 4 additional arguments are allowed!"); \
static_assert(sizeof(format) <= sPrintfCrashReasonSize, \
"The supplied format string is too long!"); \
MOZ_CALL_CRASH_PRINTF("" format, __VA_ARGS__); \
} while (0)
--- a/mfbt/MacroArgs.h
+++ b/mfbt/MacroArgs.h
@@ -16,87 +16,62 @@
#define MOZ_CONCAT(x, y) MOZ_CONCAT2(x, y)
/*
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) counts the number of variadic
* arguments and prefixes it with |aPrefix|. For example:
*
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(, foo, 42) expands to 2
* MOZ_PASTE_PREFIX_AND_ARG_COUNT(A, foo, 42, bar) expands to A3
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT(A) expands to A0
+ * MOZ_PASTE_PREFIX_AND_ARG_COUNT() expands to 0, but MSVC warns there
+ * aren't enough arguments given.
*
- * You must pass in between 1 and 50 (inclusive) variadic arguments, past
- * |aPrefix|. It is not legal to do
- *
- * MOZ_PASTE_PREFIX_AND_ARG_COUNT(prefix)
+ * You must pass in between 0 and 50 (inclusive) variadic arguments, past
+ * |aPrefix|.
*
- * (that is, pass in 0 variadic arguments). To ensure that a compile-time
- * error occurs when these constraints are violated, use the
- * MOZ_STATIC_ASSERT_VALID_ARG_COUNT macro with the same variaidc arguments
- * wherever this macro is used.
+ * The `##__VA_ARGS__` form is a GCC extension that removes the comma if
+ * __VA_ARGS__ is empty. It is supported by Clang too. MSVC ignores ##,
+ * and its default behavior is already to strip the comma when __VA_ARGS__
+ * is empty.
*
- * Passing (__VA_ARGS__, <rest of arguments>) rather than simply calling
- * MOZ_MACROARGS_ARG_COUNT_HELPER2(__VA_ARGS__, <rest of arguments>) very
- * carefully tiptoes around a MSVC bug where it improperly expands __VA_ARGS__
- * as a single token in argument lists. For details, see:
- *
- * http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement
- * http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/#comment-644
+ * So MOZ_MACROARGS_ARG_COUNT_HELPER(prefix) expands to
+ * (_, prefix50, prefix49, ...)
+ * MOZ_MACROARGS_ARG_COUNT_HELPER(prefix, a) expands to
+ * (_, a, prefix50, prefix49, ...)
+ * etc.
*/
#define MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) \
- MOZ_MACROARGS_ARG_COUNT_HELPER((__VA_ARGS__, \
+ MOZ_MACROARGS_ARG_COUNT_HELPER2( \
+ MOZ_MACROARGS_ARG_COUNT_HELPER(aPrefix, ##__VA_ARGS__))
+
+#define MOZ_MACROARGS_ARG_COUNT_HELPER(aPrefix, ...) (_, ##__VA_ARGS__, \
aPrefix##50, aPrefix##49, aPrefix##48, aPrefix##47, aPrefix##46, \
aPrefix##45, aPrefix##44, aPrefix##43, aPrefix##42, aPrefix##41, \
aPrefix##40, aPrefix##39, aPrefix##38, aPrefix##37, aPrefix##36, \
aPrefix##35, aPrefix##34, aPrefix##33, aPrefix##32, aPrefix##31, \
aPrefix##30, aPrefix##29, aPrefix##28, aPrefix##27, aPrefix##26, \
aPrefix##25, aPrefix##24, aPrefix##23, aPrefix##22, aPrefix##21, \
aPrefix##20, aPrefix##19, aPrefix##18, aPrefix##17, aPrefix##16, \
aPrefix##15, aPrefix##14, aPrefix##13, aPrefix##12, aPrefix##11, \
aPrefix##10, aPrefix##9, aPrefix##8, aPrefix##7, aPrefix##6, \
- aPrefix##5, aPrefix##4, aPrefix##3, aPrefix##2, aPrefix##1, aPrefix##0))
+ aPrefix##5, aPrefix##4, aPrefix##3, aPrefix##2, aPrefix##1, aPrefix##0)
-#define MOZ_MACROARGS_ARG_COUNT_HELPER(aArgs) \
- MOZ_MACROARGS_ARG_COUNT_HELPER2 aArgs
+#define MOZ_MACROARGS_ARG_COUNT_HELPER2(aArgs) \
+ MOZ_MACROARGS_ARG_COUNT_HELPER3 aArgs
-#define MOZ_MACROARGS_ARG_COUNT_HELPER2( \
+#define MOZ_MACROARGS_ARG_COUNT_HELPER3(a0, \
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, \
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, \
a21, a22, a23, a24, a25, a26, a27, a28, a29, a30, \
a31, a32, a33, a34, a35, a36, a37, a38, a39, a40, \
a41, a42, a43, a44, a45, a46, a47, a48, a49, a50, \
a51, ...) a51
/*
- * MOZ_STATIC_ASSERT_VALID_ARG_COUNT ensures that a compile-time error occurs
- * when the argument count constraints of MOZ_PASTE_PREFIX_AND_ARG_COUNT are
- * violated. Use this macro wherever MOZ_PASTE_PREFIX_AND_ARG_COUNT is used
- * and pass it the same variadic arguments.
- *
- * This macro employs a few dirty tricks to function. To detect the zero
- * argument case, |(__VA_ARGS__)| is stringified, sizeof-ed, and compared to
- * what it should be in the absence of arguments.
- *
- * Detecting too many arguments is a little trickier. With a valid argument
- * count and a prefix of 1, MOZ_PASTE_PREFIX_AND_ARG_COUNT expands to e.g. 14.
- * With a prefix of 0.0, it expands to e.g. 0.04. If there are too many
- * arguments, it expands to the first argument over the limit. If this
- * exceeding argument is a number, the assertion will fail as there is no
- * number than can simultaneously be both > 10 and == 0. If the exceeding
- * argument is not a number, a compile-time error should still occur due to
- * the operations performed on it.
- */
-#define MOZ_MACROARGS_STRINGIFY_HELPER(x) #x
-#define MOZ_STATIC_ASSERT_VALID_ARG_COUNT(...) \
- static_assert( \
- sizeof(MOZ_MACROARGS_STRINGIFY_HELPER((__VA_ARGS__))) != sizeof("()") && \
- (MOZ_PASTE_PREFIX_AND_ARG_COUNT(1, __VA_ARGS__)) > 10 && \
- (int)(MOZ_PASTE_PREFIX_AND_ARG_COUNT(0.0, __VA_ARGS__)) == 0, \
- "MOZ_STATIC_ASSERT_VALID_ARG_COUNT requires 1 to 50 arguments") /* ; */
-
-/*
* MOZ_ARGS_AFTER_N expands to its arguments excluding the first |N|
* arguments. For example:
*
* MOZ_ARGS_AFTER_2(a, b, c, d) expands to: c, d
*/
#define MOZ_ARGS_AFTER_1(a1, ...) __VA_ARGS__
#define MOZ_ARGS_AFTER_2(a1, a2, ...) __VA_ARGS__
--- a/mfbt/MacroForEach.h
+++ b/mfbt/MacroForEach.h
@@ -45,19 +45,17 @@
*
* #define MACRO_B(t, n) t n
* void test(MOZ_FOR_EACH_SEPARATED(MACRO_B, (,), (int,), (a, b)));
* // Expands to: void test(MACRO_B(int, a) , MACRO_B(int, b));
* // And further to: void test(int a , int b);
*
* If the |aFixedArgs| list is not empty, a trailing comma must be included.
*
- * The |aArgs| list must be not be empty and may be up to 50 items long. Use
- * MOZ_STATIC_ASSERT_VALID_ARG_COUNT to ensure that violating this constraint
- * results in a compile-time error.
+ * The |aArgs| list may be up to 50 items long.
*/
#define MOZ_FOR_EACH_EXPAND_HELPER(...) __VA_ARGS__
#define MOZ_FOR_EACH_GLUE(a, b) a b
#define MOZ_FOR_EACH_SEPARATED(aMacro, aSeparator, aFixedArgs, aArgs) \
MOZ_FOR_EACH_GLUE( \
MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_FOR_EACH_, \
MOZ_FOR_EACH_EXPAND_HELPER aArgs), \
(aMacro, aSeparator, aFixedArgs, aArgs))
@@ -65,16 +63,17 @@
MOZ_FOR_EACH_SEPARATED(aMacro, (), aFixedArgs, aArgs)
#define MOZ_FOR_EACH_HELPER_GLUE(a, b) a b
#define MOZ_FOR_EACH_HELPER(aMacro, aFixedArgs, aArgs) \
MOZ_FOR_EACH_HELPER_GLUE( \
aMacro, \
(MOZ_FOR_EACH_EXPAND_HELPER aFixedArgs MOZ_ARG_1 aArgs))
+#define MOZ_FOR_EACH_0(m, s, fa, a)
#define MOZ_FOR_EACH_1(m, s, fa, a) \
MOZ_FOR_EACH_HELPER(m, fa, a)
#define MOZ_FOR_EACH_2(m, s, fa, a) \
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_EXPAND_HELPER s \
MOZ_FOR_EACH_1(m, s, fa, (MOZ_ARGS_AFTER_1 a))
#define MOZ_FOR_EACH_3(m, s, fa, a) \
MOZ_FOR_EACH_HELPER(m, fa, a) MOZ_FOR_EACH_EXPAND_HELPER s \
MOZ_FOR_EACH_2(m, s, fa, (MOZ_ARGS_AFTER_1 a))
--- a/mfbt/tests/TestMacroArgs.cpp
+++ b/mfbt/tests/TestMacroArgs.cpp
@@ -1,19 +1,19 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/MacroArgs.h"
-MOZ_STATIC_ASSERT_VALID_ARG_COUNT(1);
-MOZ_STATIC_ASSERT_VALID_ARG_COUNT(1, 2);
-
+static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(100) == 1000, "");
+static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(100, a) == 1001, "");
+static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(100, a, b) == 1002, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(100, a, b, c) == 1003, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(, a, b, c) == 3, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(, a) == 1, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(, !a) == 1, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(, (a, b)) == 1, "");
static_assert(MOZ_PASTE_PREFIX_AND_ARG_COUNT(, MOZ_ARGS_AFTER_1(a, b, c)) == 2,
--- a/xpcom/base/nsCycleCollectionParticipant.h
+++ b/xpcom/base/nsCycleCollectionParticipant.h
@@ -437,17 +437,16 @@ DowncastCCParticipant(void* aPtr)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER(_field) \
ImplCycleCollectionUnlink(tmp->_field);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK(...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_UNLINK_HELPER, (), (__VA_ARGS__))
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
(void)tmp; \
}
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END_INHERITED(_base_class) \
nsISupports *s = static_cast<nsISupports*>(p); \
@@ -489,17 +488,16 @@ DowncastCCParticipant(void* aPtr)
== NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
return NS_SUCCESS_INTERRUPTED_TRAVERSE; \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER(_field) \
ImplCycleCollectionTraverse(cb, tmp->_field, #_field, 0);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE(...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
MOZ_FOR_EACH(NS_IMPL_CYCLE_COLLECTION_TRAVERSE_HELPER, (), (__VA_ARGS__))
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field) \
CycleCollectionNoteChild(cb, tmp->_field, #_field);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
(void)tmp; \
return NS_OK; \
--- a/xpcom/base/nsIClassInfoImpl.h
+++ b/xpcom/base/nsIClassInfoImpl.h
@@ -151,25 +151,23 @@ NS_CI_INTERFACE_GETTER_NAME(_class)(uint
sizeof(nsIID));
#define NS_CLASSINFO_HELPER_END \
MOZ_ASSERT(i == *count, "Incorrent number of entries"); \
return NS_OK; \
}
#define NS_IMPL_CI_INTERFACE_GETTER(aClass, ...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
NS_CLASSINFO_HELPER_BEGIN(aClass, \
MOZ_PASTE_PREFIX_AND_ARG_COUNT(/* No prefix */, \
__VA_ARGS__)) \
MOZ_FOR_EACH(NS_CLASSINFO_HELPER_ENTRY, (), (__VA_ARGS__)) \
NS_CLASSINFO_HELPER_END
#define NS_IMPL_QUERY_INTERFACE_CI(aClass, ...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
NS_INTERFACE_MAP_BEGIN(aClass) \
MOZ_FOR_EACH(NS_INTERFACE_MAP_ENTRY, (), (__VA_ARGS__)) \
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, MOZ_ARG_1(__VA_ARGS__)) \
NS_IMPL_QUERY_CLASSINFO(aClass) \
NS_INTERFACE_MAP_END
#define NS_IMPL_ISUPPORTS_CI(aClass, ...) \
NS_IMPL_ADDREF(aClass) \
--- a/xpcom/base/nsISupportsImpl.h
+++ b/xpcom/base/nsISupportsImpl.h
@@ -955,17 +955,16 @@ NS_IMETHODIMP _class::QueryInterface(REF
NS_IMPL_QUERY_TAIL_USING_AGGREGATOR(_aggregator)
#define NS_INTERFACE_TABLE0(_class) \
NS_INTERFACE_TABLE_BEGIN \
NS_INTERFACE_TABLE_ENTRY(_class, nsISupports) \
NS_INTERFACE_TABLE_END
#define NS_INTERFACE_TABLE(aClass, ...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
NS_INTERFACE_TABLE_BEGIN \
MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(aClass, nsISupports, \
MOZ_ARG_1(__VA_ARGS__)) \
NS_INTERFACE_TABLE_END
#define NS_IMPL_QUERY_INTERFACE0(_class) \
NS_INTERFACE_TABLE_HEAD(_class) \
@@ -1036,17 +1035,16 @@ NS_IMETHODIMP_(MozExternalRefCountType)
NS_IMETHODIMP_(MozExternalRefCountType) Class::Release(void) \
{ \
return Super::Release(); \
}
#define NS_INTERFACE_TABLE_INHERITED0(Class) /* Nothing to do here */
#define NS_INTERFACE_TABLE_INHERITED(aClass, ...) \
- MOZ_STATIC_ASSERT_VALID_ARG_COUNT(__VA_ARGS__); \
NS_INTERFACE_TABLE_BEGIN \
MOZ_FOR_EACH(NS_INTERFACE_TABLE_ENTRY, (aClass,), (__VA_ARGS__)) \
NS_INTERFACE_TABLE_END
#define NS_IMPL_QUERY_INTERFACE_INHERITED(aClass, aSuper, ...) \
NS_INTERFACE_TABLE_HEAD(aClass) \
NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)