mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 989460 - Part 1: Add MacroArgs.h for macros related to implementing variadic macros. r=Waldo
This also converts MOZ_RELEASE_ASSERT and MOZ_BEGIN_NESTED_ENUM_CLASS to use the new helper macros.
This commit is contained in:
parent
a33ed136f3
commit
accb4d62ef
@ -12,6 +12,7 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Compiler.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MacroArgs.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
@ -295,30 +296,13 @@ __declspec(noreturn) __inline void MOZ_NoReturn() {}
|
||||
MOZ_REALLY_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
/* And now, helper macrology up the wazoo. */
|
||||
/*
|
||||
* Count the number of arguments passed to MOZ_ASSERT, very carefully
|
||||
* tiptoeing around an MSVC bug where it improperly expands __VA_ARGS__ as a
|
||||
* single token in argument lists. See these URLs for details:
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#define MOZ_COUNT_ASSERT_ARGS_IMPL2(_1, _2, count, ...) \
|
||||
count
|
||||
#define MOZ_COUNT_ASSERT_ARGS_IMPL(args) \
|
||||
MOZ_COUNT_ASSERT_ARGS_IMPL2 args
|
||||
#define MOZ_COUNT_ASSERT_ARGS(...) \
|
||||
MOZ_COUNT_ASSERT_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
|
||||
/* Pick the right helper macro to invoke. */
|
||||
#define MOZ_ASSERT_CHOOSE_HELPER2(count) MOZ_ASSERT_HELPER##count
|
||||
#define MOZ_ASSERT_CHOOSE_HELPER1(count) MOZ_ASSERT_CHOOSE_HELPER2(count)
|
||||
#define MOZ_ASSERT_CHOOSE_HELPER(count) MOZ_ASSERT_CHOOSE_HELPER1(count)
|
||||
/* The actual macros. */
|
||||
#define MOZ_ASSERT_GLUE(x, y) x y
|
||||
|
||||
#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b
|
||||
#define MOZ_RELEASE_ASSERT(...) \
|
||||
MOZ_ASSERT_GLUE(MOZ_ASSERT_CHOOSE_HELPER(MOZ_COUNT_ASSERT_ARGS(__VA_ARGS__)), \
|
||||
(__VA_ARGS__))
|
||||
MOZ_RELEASE_ASSERT_GLUE( \
|
||||
MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_ASSERT_HELPER, __VA_ARGS__), \
|
||||
(__VA_ARGS__))
|
||||
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ASSERT(...) MOZ_RELEASE_ASSERT(__VA_ARGS__)
|
||||
#else
|
||||
|
105
mfbt/MacroArgs.h
Normal file
105
mfbt/MacroArgs.h
Normal file
@ -0,0 +1,105 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
/*
|
||||
* Implements various macros meant to ease the use of variadic macros.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_MacroArgs_h
|
||||
#define mozilla_MacroArgs_h
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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)
|
||||
*
|
||||
* (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.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#define MOZ_PASTE_PREFIX_AND_ARG_COUNT(aPrefix, ...) \
|
||||
MOZ_MACROARGS_ARG_COUNT_HELPER((__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))
|
||||
|
||||
#define MOZ_MACROARGS_ARG_COUNT_HELPER(aArgs) \
|
||||
MOZ_MACROARGS_ARG_COUNT_HELPER2 aArgs
|
||||
|
||||
#define MOZ_MACROARGS_ARG_COUNT_HELPER2( \
|
||||
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.1. If the exceeding
|
||||
* argument is not a number, a compile-time error will still occur because the
|
||||
* exceeding argument is compared to an int and a double.
|
||||
*/
|
||||
#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 && \
|
||||
MOZ_PASTE_PREFIX_AND_ARG_COUNT(0.0, __VA_ARGS__) < 0.1, \
|
||||
"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__
|
||||
|
||||
/*
|
||||
* MOZ_ARG_N expands to its |N|th argument.
|
||||
*/
|
||||
#define MOZ_ARG_1(a1, ...) a1
|
||||
#define MOZ_ARG_2(a1, a2, ...) a2
|
||||
|
||||
#endif /* mozilla_MacroArgs_h */
|
@ -10,6 +10,7 @@
|
||||
#define mozilla_TypedEnum_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/MacroArgs.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@ -290,33 +291,12 @@
|
||||
# define MOZ_TEMPLATE_ENUM_CLASS_ENUM_TYPE(Name) typename Name::Enum
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Count the number of arguments passed to MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS,
|
||||
* very carefully tiptoeing around an MSVC bug where it improperly expands
|
||||
* __VA_ARGS__ as a single token in argument lists. See these URLs for
|
||||
* details:
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
# define MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS_IMPL2(_1, _2, count, ...) \
|
||||
count
|
||||
# define MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS_IMPL(args) \
|
||||
MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS_IMPL2 args
|
||||
# define MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS(...) \
|
||||
MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
|
||||
/* Pick the right helper macro to invoke. */
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER2(count) \
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER##count
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER1(count) \
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER2(count)
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER(count) \
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER1(count)
|
||||
/* The actual macro. */
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE(x, y) x y
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE(a, b) a b
|
||||
# define MOZ_BEGIN_NESTED_ENUM_CLASS(...) \
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE(MOZ_BEGIN_NESTED_ENUM_CLASS_CHOOSE_HELPER(MOZ_COUNT_BEGIN_ENUM_CLASS_ARGS(__VA_ARGS__)), \
|
||||
(__VA_ARGS__))
|
||||
MOZ_BEGIN_NESTED_ENUM_CLASS_GLUE( \
|
||||
MOZ_PASTE_PREFIX_AND_ARG_COUNT(MOZ_BEGIN_NESTED_ENUM_CLASS_HELPER, \
|
||||
__VA_ARGS__), \
|
||||
(__VA_ARGS__))
|
||||
|
||||
# define MOZ_BEGIN_ENUM_CLASS(...) MOZ_BEGIN_NESTED_ENUM_CLASS(__VA_ARGS__)
|
||||
# define MOZ_END_ENUM_CLASS(Name) \
|
||||
|
@ -36,6 +36,7 @@ EXPORTS.mozilla = [
|
||||
'IntegerTypeTraits.h',
|
||||
'Likely.h',
|
||||
'LinkedList.h',
|
||||
'MacroArgs.h',
|
||||
'MathAlgorithms.h',
|
||||
'Maybe.h',
|
||||
'MemoryChecking.h',
|
||||
|
26
mfbt/tests/TestMacroArgs.cpp
Normal file
26
mfbt/tests/TestMacroArgs.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
/* -*- 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"
|
||||
|
||||
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,
|
||||
"MOZ_ARGS_AFTER_1(a, b, c) should expand to 'b, c'");
|
||||
static_assert(MOZ_ARGS_AFTER_2(a, b, 3) == 3,
|
||||
"MOZ_ARGS_AFTER_2(a, b, 3) should expand to '3'");
|
||||
|
||||
static_assert(MOZ_ARG_1(10, 20, 30) == 10, "");
|
||||
static_assert(MOZ_ARG_2(10, 20, 30) == 20, "");
|
||||
|
||||
int main()
|
||||
{
|
||||
}
|
@ -17,6 +17,7 @@ CPP_UNIT_TESTS += [
|
||||
'TestEnumSet.cpp',
|
||||
'TestFloatingPoint.cpp',
|
||||
'TestIntegerPrintfMacros.cpp',
|
||||
'TestMacroArgs.cpp',
|
||||
'TestRollingMean.cpp',
|
||||
'TestSHA1.cpp',
|
||||
'TestTypedEnum.cpp',
|
||||
|
Loading…
Reference in New Issue
Block a user