chromium/v8/src/base/macros.h

// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_BASE_MACROS_H_
#define V8_BASE_MACROS_H_

#include <limits>
#include <type_traits>

#include "include/v8config.h"
#include "src/base/compiler-specific.h"
#include "src/base/logging.h"

// No-op macro which is used to work around MSVC's funky VA_ARGS support.
#define EXPAND(X)

// This macro does nothing. That's all.
#define NOTHING(...)

#define CONCAT_(a, ...)
#define CONCAT(a, ...)
// Creates an unique identifier. Useful for scopes to avoid shadowing names.
#define UNIQUE_IDENTIFIER(base)

// COUNT_MACRO_ARGS(...) returns the number of arguments passed. Currently, up
// to 8 arguments are supported.
#define COUNT_MACRO_ARGS(...)
#define COUNT_MACRO_ARGS_IMPL(_8, _7, _6, _5, _4, _3, _2, _1, N, ...)
// GET_NTH_ARG(N, ...) returns the Nth argument in the list of arguments
// following. Currently, up to N=8 is supported.
#define GET_NTH_ARG(N, ...)
#define GET_NTH_ARG_IMPL_0(_0, ...)
#define GET_NTH_ARG_IMPL_1(_0, _1, ...)
#define GET_NTH_ARG_IMPL_2(_0, _1, _2, ...)
#define GET_NTH_ARG_IMPL_3(_0, _1, _2, _3, ...)
#define GET_NTH_ARG_IMPL_4(_0, _1, _2, _3, _4, ...)
#define GET_NTH_ARG_IMPL_5(_0, _1, _2, _3, _4, _5, ...)
#define GET_NTH_ARG_IMPL_6(_0, _1, _2, _3, _4, _5, _6, ...)
#define GET_NTH_ARG_IMPL_7(_0, _1, _2, _3, _4, _5, _6, _7, ...)

// UNPAREN(x) removes a layer of nested parentheses on x, if any. This means
// that both UNPAREN(x) and UNPAREN((x)) expand to x. This is helpful for macros
// that want to support multi argument templates with commas, e.g.
//
//   #define FOO(Type, Name) UNPAREN(Type) Name;
//
// will work with both
//
//   FOO(int, x);
//   FOO((Foo<int, double, float>), x);
#define UNPAREN(X)
#define UNPAREN_(...)
#define DROP_UNPAREN_

#define OFFSET_OF(type, field)

// A comma, to be used in macro arguments where it would otherwise be
// interpreted as separator of arguments.
#define LITERAL_COMMA

// The arraysize(arr) macro returns the # of elements in an array arr.
// The expression is a compile-time constant, and therefore can be
// used in defining new arrays, for example.  If you use arraysize on
// a pointer by mistake, you will get a compile-time error.
#define arraysize(array)

// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];

#if !V8_CC_MSVC
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
template <typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif

// This is an equivalent to C++20's std::bit_cast<>(), but with additional
// warnings. It morally does what `*reinterpret_cast<Dest*>(&source)` does, but
// the cast/deref pair is undefined behavior, while bit_cast<>() isn't.
//
// This is not a magic "get out of UB free" card. This must only be used on
// values, not on references or pointers. For pointers, use
// reinterpret_cast<>(), or static_cast<>() when casting between void* and other
// pointers, and then look at https://eel.is/c++draft/basic.lval#11 as that's
// probably UB also.
namespace v8::base {

template <class Dest, class Source>
V8_INLINE Dest bit_cast(Source const& source) {}

}  // namespace v8::base

// Explicitly declare the assignment operator as deleted.
// Note: This macro is deprecated and will be removed soon. Please explicitly
// delete the assignment operator instead.
#define DISALLOW_ASSIGN(TypeName)

// Explicitly declare all implicit constructors as deleted, namely the
// default constructor, copy constructor and operator= functions.
// This is especially useful for classes containing only static methods.
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName)

// Disallow copying a type, but provide default construction, move construction
// and move assignment. Especially useful for move-only structs.
#define MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(TypeName)

// Disallow copying a type, and only provide move construction and move
// assignment. Especially useful for move-only structs.
#define MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TypeName)

// A macro to disallow the dynamic allocation.
// This should be used in the private: declarations for a class
// Declaring operator new and delete as deleted is not spec compliant.
// Extract from 3.2.2 of C++11 spec:
//  [...] A non-placement deallocation function for a class is
//  odr-used by the definition of the destructor of that class, [...]
#define DISALLOW_NEW_AND_DELETE()

// Define V8_USE_ADDRESS_SANITIZER macro.
#if defined(__has_feature)
#if __has_feature(address_sanitizer)
#define V8_USE_ADDRESS_SANITIZER
#endif
#endif

// Define V8_USE_HWADDRESS_SANITIZER macro.
#if defined(__has_feature)
#if __has_feature(hwaddress_sanitizer)
#define V8_USE_HWADDRESS_SANITIZER
#endif
#endif

// Define V8_USE_MEMORY_SANITIZER macro.
#if defined(__has_feature)
#if __has_feature(memory_sanitizer)
#define V8_USE_MEMORY_SANITIZER
#endif
#endif

// Define V8_USE_UNDEFINED_BEHAVIOR_SANITIZER macro.
#if defined(__has_feature)
#if __has_feature(undefined_behavior_sanitizer)
#define V8_USE_UNDEFINED_BEHAVIOR_SANITIZER
#endif
#endif

// DISABLE_CFI_PERF -- Disable Control Flow Integrity checks for Perf reasons.
#define DISABLE_CFI_PERF

// DISABLE_CFI_ICALL -- Disable Control Flow Integrity indirect call checks,
// useful because calls into JITed code can not be CFI verified. Same for
// UBSan's function pointer type checks.
#ifdef V8_OS_WIN
// On Windows, also needs __declspec(guard(nocf)) for CFG.
#define DISABLE_CFI_ICALL
#else
#define DISABLE_CFI_ICALL
#endif

// V8_PRETTY_FUNCTION_VALUE_OR(ELSE) emits a pretty function value, if
// available for this compiler, otherwise it emits ELSE.
#if defined(V8_CC_GNU)
#define V8_PRETTY_FUNCTION_VALUE_OR(ELSE)
#elif defined(V8_CC_MSVC)
#define V8_PRETTY_FUNCTION_VALUE_OR
#else
#define V8_PRETTY_FUNCTION_VALUE_OR
#endif

namespace v8 {
namespace base {

// Note that some implementations of std::is_trivially_copyable mandate that at
// least one of the copy constructor, move constructor, copy assignment or move
// assignment is non-deleted, while others do not. Be aware that also
// base::is_trivially_copyable will differ for these cases.
template <typename T>
struct is_trivially_copyable {};
#define ASSERT_TRIVIALLY_COPYABLE(T)
#define ASSERT_NOT_TRIVIALLY_COPYABLE(T)

// The USE(x, ...) template is used to silence C++ compiler warnings
// issued for (yet) unused variables (typically parameters).
// The arguments are guaranteed to be evaluated from left to right.
struct Use {};
#define USE(...)

}  // namespace base
}  // namespace v8

// implicit_cast<A>(x) triggers an implicit cast from {x} to type {A}. This is
// useful in situations where static_cast<A>(x) would do too much.
// Only use this for cheap-to-copy types, or use move semantics explicitly.
template <class A>
V8_INLINE A implicit_cast(A x) {}

// Define our own macros for writing 64-bit constants.  This is less fragile
// than defining __STDC_CONSTANT_MACROS before including <stdint.h>, and it
// works on compilers that don't have it (like MSVC).
#if V8_CC_MSVC
# if V8_HOST_ARCH_64_BIT
#define V8_PTR_PREFIX
# else
#define V8_PTR_PREFIX
# endif  // V8_HOST_ARCH_64_BIT
#elif V8_CC_MINGW64
#define V8_PTR_PREFIX
#elif V8_HOST_ARCH_64_BIT
#define V8_PTR_PREFIX
#else
#if V8_OS_AIX
#define V8_PTR_PREFIX
#else
#define V8_PTR_PREFIX
#endif
#endif

#define V8PRIxPTR
#define V8PRIdPTR
#define V8PRIuPTR

#if V8_TARGET_ARCH_64_BIT
#define V8_PTR_HEX_DIGITS
#define V8PRIxPTR_FMT
#else
#define V8_PTR_HEX_DIGITS
#define V8PRIxPTR_FMT
#endif

// ptrdiff_t is 't' according to the standard, but MSVC uses 'I'.
#if V8_CC_MSVC
#define V8PRIxPTRDIFF
#define V8PRIdPTRDIFF
#define V8PRIuPTRDIFF
#else
#define V8PRIxPTRDIFF
#define V8PRIdPTRDIFF
#define V8PRIuPTRDIFF
#endif

// Fix for Mac OS X defining uintptr_t as "unsigned long":
#if V8_OS_DARWIN
#undef V8PRIxPTR
#define V8PRIxPTR
#undef V8PRIdPTR
#define V8PRIdPTR
#undef V8PRIuPTR
#define V8PRIuPTR
#endif

// Make a uint64 from two uint32_t halves.
inline uint64_t make_uint64(uint32_t high, uint32_t low) {}

// Return the largest multiple of m which is <= x.
template <typename T>
inline T RoundDown(T x, intptr_t m) {}
template <intptr_t m, typename T>
constexpr inline T RoundDown(T x) {}

// Return the smallest multiple of m which is >= x.
template <typename T>
inline T RoundUp(T x, intptr_t m) {}

template <intptr_t m, typename T>
constexpr inline T RoundUp(T x) {}

template <typename T, typename U>
constexpr inline bool IsAligned(T value, U alignment) {}

inline void* AlignedAddress(void* address, size_t alignment) {}

inline void* RoundUpAddress(void* address, size_t alignment) {}

// Bounds checks for float to integer conversions, which does truncation. Hence,
// the range of legal values is (min - 1, max + 1).
template <typename int_t, typename float_t, typename biggest_int_t = int64_t>
bool is_inbounds(float_t v) {}

#ifdef V8_OS_WIN

// Setup for Windows shared library export.
#define V8_EXPORT_ENUM
#ifdef BUILDING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE
#elif USING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE
#else
#define V8_EXPORT_PRIVATE
#endif  // BUILDING_V8_SHARED

#else  // V8_OS_WIN

// Setup for Linux shared library export.
#if V8_HAS_ATTRIBUTE_VISIBILITY
#ifdef BUILDING_V8_SHARED_PRIVATE
#define V8_EXPORT_PRIVATE
#define V8_EXPORT_ENUM
#else
#define V8_EXPORT_PRIVATE
#define V8_EXPORT_ENUM
#endif
#else
#define V8_EXPORT_PRIVATE
#define V8_EXPORT_ENUM
#endif

#endif  // V8_OS_WIN

// Defines IF_WASM, to be used in macro lists for elements that should only be
// there if WebAssembly is enabled.
#if V8_ENABLE_WEBASSEMBLY
// EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion.
#define IF_WASM(V, ...)
#else
#define IF_WASM
#endif  // V8_ENABLE_WEBASSEMBLY

#ifdef V8_ENABLE_DRUMBRAKE
#define IF_WASM_DRUMBRAKE
#else
#define IF_WASM_DRUMBRAKE(V, ...)
#endif  // V8_ENABLE_DRUMBRAKE

#if defined(V8_ENABLE_DRUMBRAKE) && !defined(V8_DRUMBRAKE_BOUNDS_CHECKS)
#define IF_WASM_DRUMBRAKE_INSTR_HANDLER
#else
#define IF_WASM_DRUMBRAKE_INSTR_HANDLER(V, ...)
#endif  // V8_ENABLE_DRUMBRAKE && !V8_DRUMBRAKE_BOUNDS_CHECKS

// Defines IF_TSAN, to be used in macro lists for elements that should only be
// there if TSAN is enabled.
#ifdef V8_IS_TSAN
// EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion.
#define IF_TSAN
#else
#define IF_TSAN(V, ...)
#endif  // V8_IS_TSAN

// Defines IF_INTL, to be used in macro lists for elements that should only be
// there if INTL is enabled.
#ifdef V8_INTL_SUPPORT
// EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion.
#define IF_INTL(V, ...)
#else
#define IF_INTL
#endif  // V8_INTL_SUPPORT

// Defines IF_TARGET_ARCH_64_BIT, to be used in macro lists for elements that
// should only be there if the target architecture is a 64-bit one.
#if V8_TARGET_ARCH_64_BIT
// EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion.
#define IF_TARGET_ARCH_64_BIT(V, ...)
#else
#define IF_TARGET_ARCH_64_BIT
#endif  // V8_TARGET_ARCH_64_BIT

// Defines IF_OFFICIAL_BUILD and IF_NO_OFFICIAL_BUILD, to be used in macro lists
// for elements that should only be there in official / non-official builds.
#ifdef OFFICIAL_BUILD
// EXPAND is needed to work around MSVC's broken __VA_ARGS__ expansion.
#define IF_OFFICIAL_BUILD
#define IF_NO_OFFICIAL_BUILD
#else
#define IF_OFFICIAL_BUILD(V, ...)
#define IF_NO_OFFICIAL_BUILD(V, ...)
#endif  // OFFICIAL_BUILD

#ifdef GOOGLE3
// Disable FRIEND_TEST macro in Google3.
#define FRIEND_TEST
#endif

#endif  // V8_BASE_MACROS_H_