diff options
Diffstat (limited to '')
-rw-r--r-- | include/onlineupdate/mar.h | 198 | ||||
-rw-r--r-- | include/onlineupdate/mar_cmdline.h | 110 | ||||
-rw-r--r-- | include/onlineupdate/mar_private.h | 79 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/Assertions.h | 503 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/Attributes.h | 481 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/Compiler.h | 110 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/Likely.h | 23 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/MacroArgs.h | 105 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/TypeTraits.h | 1116 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/Types.h | 134 | ||||
-rw-r--r-- | include/onlineupdate/mozilla/nsTraceRefcnt.h | 67 |
11 files changed, 2926 insertions, 0 deletions
diff --git a/include/onlineupdate/mar.h b/include/onlineupdate/mar.h new file mode 100644 index 000000000..0e21efb92 --- /dev/null +++ b/include/onlineupdate/mar.h @@ -0,0 +1,198 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#ifndef MAR_H__ +#define MAR_H__ + +#include "mozilla/Assertions.h" +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* We have a MAX_SIGNATURES limit so that an invalid MAR will never + * waste too much of either updater's or signmar's time. + * It is also used at various places internally and will affect memory usage. + * If you want to increase this value above 9 then you need to adjust parsing + * code in tool/mar.c. +*/ +#define MAX_SIGNATURES 8 +#ifdef __cplusplus +static_assert(MAX_SIGNATURES <= 9, "too many signatures"); +#else +MOZ_STATIC_ASSERT(MAX_SIGNATURES <= 9, "too many signatures"); +#endif + +struct ProductInformationBlock { + const char *MARChannelID; + const char *productVersion; +}; + +/** + * The MAR item data structure. + */ +typedef struct MarItem_ { + struct MarItem_ *next; /* private field */ + uint32_t offset; /* offset into archive */ + uint32_t length; /* length of data in bytes */ + uint32_t flags; /* contains file mode bits */ + char name[1]; /* file path */ +} MarItem; + +#define TABLESIZE 256 + +struct MarFile_ { + FILE *fp; + MarItem *item_table[TABLESIZE]; +}; + +typedef struct MarFile_ MarFile; + +/** + * Signature of callback function passed to mar_enum_items. + * @param mar The MAR file being visited. + * @param item The MAR item being visited. + * @param data The data parameter passed by the caller of mar_enum_items. + * @return A non-zero value to stop enumerating. + */ +typedef int (* MarItemCallback)(MarFile *mar, const MarItem *item, void *data); + +/** + * Open a MAR file for reading. + * @param path Specifies the path to the MAR file to open. This path must + * be compatible with fopen. + * @return NULL if an error occurs. + */ +MarFile *mar_open(const char *path); + +#ifdef _WIN32 +MarFile *mar_wopen(const wchar_t *path); +#endif + +/** + * Close a MAR file that was opened using mar_open. + * @param mar The MarFile object to close. + */ +void mar_close(MarFile *mar); + +/** + * Find an item in the MAR file by name. + * @param mar The MarFile object to query. + * @param item The name of the item to query. + * @return A const reference to a MAR item or NULL if not found. + */ +const MarItem *mar_find_item(MarFile *mar, const char *item); + +/** + * Enumerate all MAR items via callback function. + * @param mar The MAR file to enumerate. + * @param callback The function to call for each MAR item. + * @param data A caller specified value that is passed along to the + * callback function. + * @return 0 if the enumeration ran to completion. Otherwise, any + * non-zero return value from the callback is returned. + */ +int mar_enum_items(MarFile *mar, MarItemCallback callback, void *data); + +/** + * Read from MAR item at given offset up to bufsize bytes. + * @param mar The MAR file to read. + * @param item The MAR item to read. + * @param offset The byte offset relative to the start of the item. + * @param buf A pointer to a buffer to copy the data into. + * @param bufsize The length of the buffer to copy the data into. + * @return The number of bytes written or a negative value if an + * error occurs. + */ +int mar_read(MarFile *mar, const MarItem *item, int offset, char *buf, + int bufsize); + +/** + * Create a MAR file from a set of files. + * @param dest The path to the file to create. This path must be + * compatible with fopen. + * @param numfiles The number of files to store in the archive. + * @param files The list of null-terminated file paths. Each file + * path must be compatible with fopen. + * @param infoBlock The information to store in the product information block. + * @return A non-zero value if an error occurs. + */ +int mar_create(const char *dest, + int numfiles, + char **files, + struct ProductInformationBlock *infoBlock); + +/** + * Extract a MAR file to the current working directory. + * @param path The path to the MAR file to extract. This path must be + * compatible with fopen. + * @return A non-zero value if an error occurs. + */ +int mar_extract(const char *path); + +#define MAR_MAX_CERT_SIZE (16*1024) // Way larger than necessary + +/* Read the entire file (not a MAR file) into a newly-allocated buffer. + * This function does not write to stderr. Instead, the caller should + * write whatever error messages it sees fit. The caller must free the returned + * buffer using free(). + * + * @param filePath The path to the file that should be read. + * @param maxSize The maximum valid file size. + * @param data On success, *data will point to a newly-allocated buffer + * with the file's contents in it. + * @param size On success, *size will be the size of the created buffer. + * + * @return 0 on success, -1 on error + */ +int mar_read_entire_file(const char * filePath, + uint32_t maxSize, + /*out*/ const uint8_t * *data, + /*out*/ uint32_t *size); + +/** + * Verifies a MAR file by verifying each signature with the corresponding + * certificate. That is, the first signature will be verified using the first + * certificate given, the second signature will be verified using the second + * certificate given, etc. The signature count must exactly match the number of + * certificates given, and all signature verifications must succeed. + * We do not check that the certificate was issued by any trusted authority. + * We assume it to be self-signed. We do not check whether the certificate + * is valid for this usage. + * + * @param mar The already opened MAR file. + * @param certData Pointer to the first element in an array of certificate + * file data. + * @param certDataSizes Pointer to the first element in an array for size of + * the cert data. + * @param certCount The number of elements in certData and certDataSizes + * @return 0 on success + * a negative number if there was an error + * a positive number if the signature does not verify + */ +int mar_verify_signatures(MarFile *mar, + const uint8_t * const *certData, + const uint32_t *certDataSizes, + uint32_t certCount); + +/** + * Reads the product info block from the MAR file's additional block section. + * The caller is responsible for freeing the fields in infoBlock + * if the return is successful. + * + * @param infoBlock Out parameter for where to store the result to + * @return 0 on success, -1 on failure +*/ +int +mar_read_product_info_block(MarFile *mar, + struct ProductInformationBlock *infoBlock); + +#ifdef __cplusplus +} +#endif + +#endif /* MAR_H__ */ diff --git a/include/onlineupdate/mar_cmdline.h b/include/onlineupdate/mar_cmdline.h new file mode 100644 index 000000000..ef6867f06 --- /dev/null +++ b/include/onlineupdate/mar_cmdline.h @@ -0,0 +1,110 @@ +/* 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/. */ + +#ifndef MAR_CMDLINE_H__ +#define MAR_CMDLINE_H__ + +/* We use NSPR here just to import the definition of uint32_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct ProductInformationBlock; + +/** + * Determines MAR file information. + * + * @param path The path of the MAR file to check. + * @param hasSignatureBlock Optional out parameter specifying if the MAR + * file has a signature block or not. + * @param numSignatures Optional out parameter for storing the number + * of signatures in the MAR file. + * @param hasAdditionalBlocks Optional out parameter specifying if the MAR + * file has additional blocks or not. + * @param offsetAdditionalBlocks Optional out parameter for the offset to the + * first additional block. Value is only valid if + * hasAdditionalBlocks is not equal to 0. + * @param numAdditionalBlocks Optional out parameter for the number of + * additional blocks. Value is only valid if + * has_additional_blocks is not equal to 0. + * @return 0 on success and non-zero on failure. + */ +int get_mar_file_info(const char *path, + int *hasSignatureBlock, + uint32_t *numSignatures, + int *hasAdditionalBlocks, + uint32_t *offsetAdditionalBlocks, + uint32_t *numAdditionalBlocks); + +/** + * Reads the product info block from the MAR file's additional block section. + * The caller is responsible for freeing the fields in infoBlock + * if the return is successful. + * + * @param infoBlock Out parameter for where to store the result to + * @return 0 on success, -1 on failure +*/ +int +read_product_info_block(char *path, + struct ProductInformationBlock *infoBlock); + +/** + * Refreshes the product information block with the new information. + * The input MAR must not be signed or the function call will fail. + * + * @param path The path to the MAR file whose product info block + * should be refreshed. + * @param infoBlock Out parameter for where to store the result to + * @return 0 on success, -1 on failure +*/ +int +refresh_product_info_block(const char *path, + struct ProductInformationBlock *infoBlock); + +/** + * Writes out a copy of the MAR at src but with the signature block stripped. + * + * @param src The path of the source MAR file + * @param dest The path of the MAR file to write out that + has no signature block + * @return 0 on success + * -1 on error +*/ +int +strip_signature_block(const char *src, const char * dest); + +/** + * Extracts a signature from a MAR file, base64 encodes it, and writes it out + * + * @param src The path of the source MAR file + * @param sigIndex The index of the signature to extract + * @param dest The path of file to write the signature to + * @return 0 on success + * -1 on error +*/ +int +extract_signature(const char *src, uint32_t sigIndex, const char * dest); + +/** + * Imports a base64 encoded signature into a MAR file + * + * @param src The path of the source MAR file + * @param sigIndex The index of the signature to import + * @param base64SigFile A file which contains the signature to import + * @param dest The path of the destination MAR file with replaced signature + * @return 0 on success + * -1 on error +*/ +int +import_signature(const char *src, + uint32_t sigIndex, + const char * base64SigFile, + const char *dest); + +#ifdef __cplusplus +} +#endif + +#endif /* MAR_CMDLINE_H__ */ diff --git a/include/onlineupdate/mar_private.h b/include/onlineupdate/mar_private.h new file mode 100644 index 000000000..319564b74 --- /dev/null +++ b/include/onlineupdate/mar_private.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim:set ts=2 sw=2 sts=2 et cindent: */ +/* 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/. */ + +#ifndef MAR_PRIVATE_H__ +#define MAR_PRIVATE_H__ + +#include "limits.h" +#include "mozilla/Assertions.h" +#include <stdint.h> + +#define BLOCKSIZE 4096 +#define ROUND_UP(n, incr) (((n) / (incr) + 1) * (incr)) + +#define MAR_ID "MAR1" +#define MAR_ID_SIZE 4 + +/* The signature block comes directly after the header block + which is 16 bytes */ +#define SIGNATURE_BLOCK_OFFSET 16 + +/* Make sure the file is less than 500MB. We do this to protect against + invalid MAR files. */ +#define MAX_SIZE_OF_MAR_FILE ((int64_t)1824288000) + +/* Existing code makes assumptions that the file size is + smaller than LONG_MAX. */ +MOZ_STATIC_ASSERT(MAX_SIZE_OF_MAR_FILE < ((int64_t)LONG_MAX), + "max mar file size is too big"); + +/* We store at most the size up to the signature block + 4 + bytes per BLOCKSIZE bytes */ +MOZ_STATIC_ASSERT(sizeof(BLOCKSIZE) < + (SIGNATURE_BLOCK_OFFSET + sizeof(uint32_t)), + "BLOCKSIZE is too big"); + +/* The maximum size of any signature supported by current and future + implementations of the signmar program. */ +#define MAX_SIGNATURE_LENGTH 2048 + +/* Each additional block has a unique ID. + The product information block has an ID of 1. */ +#define PRODUCT_INFO_BLOCK_ID 1 + +#define MAR_ITEM_SIZE(namelen) (3*sizeof(uint32_t) + (namelen) + 1) + +/* Product Information Block (PIB) constants */ +#define PIB_MAX_MAR_CHANNEL_ID_SIZE 63 +#define PIB_MAX_PRODUCT_VERSION_SIZE 31 + +/* The mar program is compiled as a host bin so we don't have access to NSPR at + runtime. For that reason we use ntohl, htonl, and define HOST_TO_NETWORK64 + instead of the NSPR equivalents. */ +#ifdef _WIN32 +#include <winsock2.h> +#define ftello _ftelli64 +#define fseeko _fseeki64 +#else +#define _FILE_OFFSET_BITS 64 +#include <netinet/in.h> +#include <unistd.h> +#endif + +#include <stdio.h> + +#define HOST_TO_NETWORK64(x) ( \ + ((((uint64_t) x) & 0xFF) << 56) | \ + ((((uint64_t) x) >> 8) & 0xFF) << 48) | \ + (((((uint64_t) x) >> 16) & 0xFF) << 40) | \ + (((((uint64_t) x) >> 24) & 0xFF) << 32) | \ + (((((uint64_t) x) >> 32) & 0xFF) << 24) | \ + (((((uint64_t) x) >> 40) & 0xFF) << 16) | \ + (((((uint64_t) x) >> 48) & 0xFF) << 8) | \ + (((uint64_t) x) >> 56) +#define NETWORK_TO_HOST64 HOST_TO_NETWORK64 + +#endif /* MAR_PRIVATE_H__ */ diff --git a/include/onlineupdate/mozilla/Assertions.h b/include/onlineupdate/mozilla/Assertions.h new file mode 100644 index 000000000..29b4588fd --- /dev/null +++ b/include/onlineupdate/mozilla/Assertions.h @@ -0,0 +1,503 @@ +/* -*- 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/. */ + +/* Implementations of runtime and static assertion macros for C and C++. */ + +#ifndef mozilla_Assertions_h +#define mozilla_Assertions_h + +#if defined(MOZILLA_INTERNAL_API) && defined(__cplusplus) +#define MOZ_DUMP_ASSERTION_STACK +#endif + +#include "Attributes.h" +#include "Compiler.h" +#include "Likely.h" +#include "MacroArgs.h" +#ifdef MOZ_DUMP_ASSERTION_STACK +#include "nsTraceRefcnt.h" +#endif + +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef _WIN32 + /* + * TerminateProcess and GetCurrentProcess are defined in <winbase.h>, which + * further depends on <windef.h>. We hardcode these few definitions manually + * because those headers clutter the global namespace with a significant + * number of undesired macros and symbols. + */ +# ifdef __cplusplus +extern "C" { +# endif +__declspec(dllimport) int __stdcall +TerminateProcess(void* hProcess, unsigned int uExitCode); +__declspec(dllimport) void* __stdcall GetCurrentProcess(void); +# ifdef __cplusplus +} +# endif +#else +# include <signal.h> +#endif +#ifdef ANDROID +# include <android/log.h> +#endif + +/* + * MOZ_STATIC_ASSERT may be used to assert a condition *at compile time* in C. + * In C++11, static_assert is provided by the compiler to the same effect. + * 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 { ... }; + * // C + * MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0, + * "S should be a multiple of word size for efficiency"); + * // C++11 + * 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. + */ +#ifndef __cplusplus + /* + * Some of the definitions below create an otherwise-unused typedef. This + * triggers compiler warnings with some versions of gcc, so mark the typedefs + * as permissibly-unused to disable the warnings. + */ +# if defined(__GNUC__) +# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused)) +# else +# define MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE /* nothing */ +# endif +# 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] MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE +# else +# define MOZ_STATIC_ASSERT(cond, reason) \ + extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1]) MOZ_STATIC_ASSERT_UNUSED_ATTRIBUTE +# endif + +#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason) +#else +#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) static_assert(!(cond) || (expr), reason) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Prints |aStr| as an assertion failure (using aFilename and aLine as the + * location of the assertion) to the standard debug-output channel. + * + * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method. This + * method is primarily for internal use in this header, and only secondarily + * for use in implementing release-build assertions. + */ +static MOZ_COLD MOZ_ALWAYS_INLINE void +MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename, int aLine) + MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS +{ +#ifdef ANDROID + __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert", + "Assertion failure: %s, at %s:%d\n", + aStr, aFilename, aLine); +#else + fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine); +#if defined (MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API) + nsTraceRefcnt::WalkTheStack(stderr); +#endif + fflush(stderr); +#endif +} + +static MOZ_COLD MOZ_ALWAYS_INLINE void +MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine) + MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS +{ +#ifdef ANDROID + __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH", + "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine); +#else + fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine); +#if defined(MOZ_DUMP_ASSERTION_STACK) && !defined(MOZILLA_XPCOMRT_API) + nsTraceRefcnt::WalkTheStack(stderr); +#endif + fflush(stderr); +#endif +} + +/** + * MOZ_REALLY_CRASH is used in the implementation of MOZ_CRASH(). You should + * call MOZ_CRASH instead. + */ +#if defined(_MSC_VER) + /* + * On MSVC use the __debugbreak compiler intrinsic, which produces an inline + * (not nested in a system function) breakpoint. This distinctively invokes + * Breakpad without requiring system library symbols on all stack-processing + * machines, as a nested breakpoint would require. + * + * We use TerminateProcess with the exit code aborting would generate + * because we don't want to invoke atexit handlers, destructors, library + * unload handlers, and so on when our process might be in a compromised + * state. + * + * We don't use abort() because it'd cause Windows to annoyingly pop up the + * process error dialog multiple times. See bug 345118 and bug 426163. + * + * We follow TerminateProcess() with a call to MOZ_NoReturn() so that the + * compiler doesn't hassle us to provide a return statement after a + * MOZ_REALLY_CRASH() call. + * + * (Technically these are Windows requirements, not MSVC requirements. But + * practically you need MSVC for debugging, and we only ship builds created + * by MSVC, so doing it this way reduces complexity.) + */ + +__declspec(noreturn) __inline void MOZ_NoReturn() {} + +# ifdef __cplusplus +# define MOZ_REALLY_CRASH() \ + do { \ + ::__debugbreak(); \ + *((volatile int*) NULL) = __LINE__; \ + ::TerminateProcess(::GetCurrentProcess(), 3); \ + ::MOZ_NoReturn(); \ + } while (0) +# else +# define MOZ_REALLY_CRASH() \ + do { \ + __debugbreak(); \ + *((volatile int*) NULL) = __LINE__; \ + TerminateProcess(GetCurrentProcess(), 3); \ + MOZ_NoReturn(); \ + } while (0) +# endif +#else +# ifdef __cplusplus +# define MOZ_REALLY_CRASH() \ + do { \ + *((volatile int*) NULL) = __LINE__; \ + ::abort(); \ + } while (0) +# else +# define MOZ_REALLY_CRASH() \ + do { \ + *((volatile int*) NULL) = __LINE__; \ + abort(); \ + } while (0) +# endif +#endif + +/* + * MOZ_CRASH([explanation-string]) crashes the program, plain and simple, in a + * Breakpad-compatible way, in both debug and release builds. + * + * MOZ_CRASH is a good solution for "handling" failure cases when you're + * unwilling or unable to handle them more cleanly -- for OOM, for likely memory + * corruption, and so on. It's also a good solution if you need safe behavior + * in release builds as well as debug builds. But if the failure is one that + * should be debugged and fixed, MOZ_ASSERT is generally preferable. + * + * The optional explanation-string, if provided, must be a string literal + * explaining why we're crashing. This argument is intended for use with + * MOZ_CRASH() calls whose rationale is non-obvious; don't use it if it's + * obvious why we're crashing. + * + * If we're a DEBUG build and we crash at a MOZ_CRASH which provides an + * explanation-string, we print the string to stderr. Otherwise, we don't + * print anything; this is because we want MOZ_CRASH to be 100% safe in release + * builds, and it's hard to print to stderr safely when memory might have been + * corrupted. + */ +#ifndef DEBUG +# define MOZ_CRASH(...) MOZ_REALLY_CRASH() +#else +# define MOZ_CRASH(...) \ + do { \ + MOZ_ReportCrash("" __VA_ARGS__, __FILE__, __LINE__); \ + MOZ_REALLY_CRASH(); \ + } while (0) +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +/* + * MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in + * debug builds. If it is, execution continues. Otherwise, an error message + * including the expression and the explanation-string (if provided) is printed, + * an attempt is made to invoke any existing debugger, and execution halts. + * MOZ_ASSERT is fatal: no recovery is possible. Do not assert a condition + * which can correctly be falsy. + * + * The optional explanation-string, if provided, must be a string literal + * explaining the assertion. It is intended for use with assertions whose + * correctness or rationale is non-obvious, and for assertions where the "real" + * condition being tested is best described prosaically. Don't provide an + * explanation if it's not actually helpful. + * + * // No explanation needed: pointer arguments often must not be NULL. + * MOZ_ASSERT(arg); + * + * // An explanation can be helpful to explain exactly how we know an + * // assertion is valid. + * MOZ_ASSERT(state == WAITING_FOR_RESPONSE, + * "given that <thingA> and <thingB>, we must have..."); + * + * // Or it might disambiguate multiple identical (save for their location) + * // assertions of the same expression. + * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(), + * "we already set [[PrimitiveThis]] for this Boolean object"); + * MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(), + * "we already set [[PrimitiveThis]] for this String object"); + * + * MOZ_ASSERT has no effect in non-debug builds. It is designed to catch bugs + * *only* during debugging, not "in the field". If you want the latter, use + * MOZ_RELEASE_ASSERT, which applies to non-debug builds as well. + * + * MOZ_DIAGNOSTIC_ASSERT works like MOZ_RELEASE_ASSERT in Nightly/Aurora and + * MOZ_ASSERT in Beta/Release - use this when a condition is potentially rare + * enough to require real user testing to hit, but is not security-sensitive. + * This can cause user pain, so use it sparingly. If a MOZ_DIAGNOSTIC_ASSERT + * is firing, it should promptly be converted to a MOZ_ASSERT while the failure + * is being investigated, rather than letting users suffer. + */ + +/* + * Implement MOZ_VALIDATE_ASSERT_CONDITION_TYPE, which is used to guard against + * accidentally passing something unintended in lieu of an assertion condition. + */ + +#ifdef __cplusplus +# include "TypeTraits.h" +namespace mozilla { +namespace detail { + +template<typename T> +struct IsFunction +{ + static const bool value = false; +}; + +template<typename R, typename... A> +struct IsFunction<R(A...)> +{ + static const bool value = true; +}; + +template<typename T> +struct AssertionConditionType +{ + typedef typename RemoveReference<T>::Type ValueT; + static_assert(!IsArray<ValueT>::value, + "Expected boolean assertion condition, got an array or a " + "string!"); + static_assert(!IsFunction<ValueT>::value, + "Expected boolean assertion condition, got a function! Did " + "you intend to call that function?"); + static_assert(!IsFloatingPoint<ValueT>::value, + "It's often a bad idea to assert that a floating-point number " + "is nonzero, because such assertions tend to intermittently " + "fail. Shouldn't your code gracefully handle this case instead " + "of asserting? Anyway, if you really want to do that, write an " + "explicit boolean condition, like !!x or x!=0."); + + static const bool isValid = true; +}; + +} // namespace detail +} // namespace mozilla +# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x) \ + static_assert(mozilla::detail::AssertionConditionType<decltype(x)>::isValid, \ + "invalid assertion condition") +#else +# define MOZ_VALIDATE_ASSERT_CONDITION_TYPE(x) +#endif + +/* First the single-argument form. */ +#define MOZ_ASSERT_HELPER1(expr) \ + do { \ + MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \ + if (MOZ_UNLIKELY(!(expr))) { \ + MOZ_ReportAssertionFailure(#expr, __FILE__, __LINE__); \ + MOZ_REALLY_CRASH(); \ + } \ + } while (0) +/* Now the two-argument form. */ +#define MOZ_ASSERT_HELPER2(expr, explain) \ + do { \ + MOZ_VALIDATE_ASSERT_CONDITION_TYPE(expr); \ + if (MOZ_UNLIKELY(!(expr))) { \ + MOZ_ReportAssertionFailure(#expr " (" explain ")", __FILE__, __LINE__); \ + MOZ_REALLY_CRASH(); \ + } \ + } while (0) + +#define MOZ_RELEASE_ASSERT_GLUE(a, b) a b +#define MOZ_RELEASE_ASSERT(...) \ + 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 +# define MOZ_ASSERT(...) do { } while (0) +#endif /* DEBUG */ + +#ifdef RELEASE_BUILD +# define MOZ_DIAGNOSTIC_ASSERT MOZ_ASSERT +#else +# define MOZ_DIAGNOSTIC_ASSERT MOZ_RELEASE_ASSERT +#endif + +/* + * MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is + * true. + * + * MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num)); + * + * As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds. It is + * designed to catch bugs during debugging, not "in the field". + */ +#ifdef DEBUG +# define MOZ_ASSERT_IF(cond, expr) \ + do { \ + if (cond) { \ + MOZ_ASSERT(expr); \ + } \ + } while (0) +#else +# define MOZ_ASSERT_IF(cond, expr) do { } while (0) +#endif + +/* + * MOZ_ASSUME_UNREACHABLE_MARKER() expands to an expression which states that + * it is undefined behavior for execution to reach this point. No guarantees + * are made about what will happen if this is reached at runtime. Most code + * should use MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE because it has extra + * asserts. + */ +#if defined(__clang__) || defined(__GNUC__) +# define MOZ_ASSUME_UNREACHABLE_MARKER() __builtin_unreachable() +#elif defined(_MSC_VER) +# define MOZ_ASSUME_UNREACHABLE_MARKER() __assume(0) +#else +# ifdef __cplusplus +# define MOZ_ASSUME_UNREACHABLE_MARKER() ::abort() +# else +# define MOZ_ASSUME_UNREACHABLE_MARKER() abort() +# endif +#endif + +/* + * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE([reason]) tells the compiler that it + * can assume that the macro call cannot be reached during execution. This lets + * the compiler generate better-optimized code under some circumstances, at the + * expense of the program's behavior being undefined if control reaches the + * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE. + * + * In Gecko, you probably should not use this macro outside of performance- or + * size-critical code, because it's unsafe. If you don't care about code size + * or performance, you should probably use MOZ_ASSERT or MOZ_CRASH. + * + * SpiderMonkey is a different beast, and there it's acceptable to use + * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE more widely. + * + * Note that MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE is noreturn, so it's valid + * not to return a value following a MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE + * call. + * + * Example usage: + * + * enum ValueType { + * VALUE_STRING, + * VALUE_INT, + * VALUE_FLOAT + * }; + * + * int ptrToInt(ValueType type, void* value) { + * { + * // We know for sure that type is either INT or FLOAT, and we want this + * // code to run as quickly as possible. + * switch (type) { + * case VALUE_INT: + * return *(int*) value; + * case VALUE_FLOAT: + * return (int) *(float*) value; + * default: + * MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Unexpected ValueType"); + * } + * } + */ + +/* + * Unconditional assert in debug builds for (assumed) unreachable code paths + * that have a safe return without crashing in release builds. + */ +#define MOZ_ASSERT_UNREACHABLE(reason) \ + MOZ_ASSERT(false, "MOZ_ASSERT_UNREACHABLE: " reason) + +#define MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE(reason) \ + do { \ + MOZ_ASSERT_UNREACHABLE(reason); \ + MOZ_ASSUME_UNREACHABLE_MARKER(); \ + } while (0) + +/* + * MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided + * expression, in debug builds and in release builds both. Then, in debug + * builds only, the value of the expression is asserted either true or false + * using MOZ_ASSERT. + */ +#ifdef DEBUG +# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr)) +# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr)) +#else +# define MOZ_ALWAYS_TRUE(expr) ((void)(expr)) +# define MOZ_ALWAYS_FALSE(expr) ((void)(expr)) +#endif + +#undef MOZ_DUMP_ASSERTION_STACK + +#endif /* mozilla_Assertions_h */ diff --git a/include/onlineupdate/mozilla/Attributes.h b/include/onlineupdate/mozilla/Attributes.h new file mode 100644 index 000000000..74b77a38d --- /dev/null +++ b/include/onlineupdate/mozilla/Attributes.h @@ -0,0 +1,481 @@ +/* -*- 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/. */ + +/* Implementations of various class and method modifier attributes. */ + +#ifndef mozilla_Attributes_h +#define mozilla_Attributes_h + +#include "Compiler.h" + +/* + * MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the + * method decorated with it must be inlined, even if the compiler thinks + * otherwise. This is only a (much) stronger version of the inline hint: + * compilers are not guaranteed to respect it (although they're much more likely + * to do so). + * + * The MOZ_ALWAYS_INLINE_EVEN_DEBUG macro is yet stronger. It tells the + * compiler to inline even in DEBUG builds. It should be used very rarely. + */ +#if defined(_MSC_VER) +# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __forceinline +#elif defined(__GNUC__) +# define MOZ_ALWAYS_INLINE_EVEN_DEBUG __attribute__((always_inline)) inline +#else +# define MOZ_ALWAYS_INLINE_EVEN_DEBUG inline +#endif + +#if !defined(DEBUG) +# define MOZ_ALWAYS_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG +#elif defined(_MSC_VER) && !defined(__cplusplus) +# define MOZ_ALWAYS_INLINE __inline +#else +# define MOZ_ALWAYS_INLINE inline +#endif + +#if defined(_MSC_VER) +/* + * g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality + * without warnings (functionality used by the macros below). These modes are + * detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more + * standardly, by checking whether __cplusplus has a C++11 or greater value. + * Current versions of g++ do not correctly set __cplusplus, so we check both + * for forward compatibility. + * + * Even though some versions of MSVC support explicit conversion operators, we + * don't indicate support for them here, due to + * http://stackoverflow.com/questions/20498142/visual-studio-2013-explicit-keyword-bug + */ +# define MOZ_HAVE_NEVER_INLINE __declspec(noinline) +# define MOZ_HAVE_NORETURN __declspec(noreturn) +# ifdef __clang__ + /* clang-cl probably supports constexpr and explicit conversions. */ +# if __has_extension(cxx_constexpr) +# define MOZ_HAVE_CXX11_CONSTEXPR +# endif +# if __has_extension(cxx_explicit_conversions) +# define MOZ_HAVE_EXPLICIT_CONVERSION +# endif +# endif +#elif defined(__clang__) + /* + * Per Clang documentation, "Note that marketing version numbers should not + * be used to check for language features, as different vendors use different + * numbering schemes. Instead, use the feature checking macros." + */ +# ifndef __has_extension +# define __has_extension __has_feature /* compatibility, for older versions of clang */ +# endif +# if __has_extension(cxx_constexpr) +# define MOZ_HAVE_CXX11_CONSTEXPR +# endif +# if __has_extension(cxx_explicit_conversions) +# define MOZ_HAVE_EXPLICIT_CONVERSION +# endif +# if __has_attribute(noinline) +# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline)) +# endif +# if __has_attribute(noreturn) +# define MOZ_HAVE_NORETURN __attribute__((noreturn)) +# endif +#elif defined(__GNUC__) +# if defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && __cplusplus >= 201103L) +# define MOZ_HAVE_CXX11_CONSTEXPR +# if MOZ_GCC_VERSION_AT_LEAST(4, 8, 0) +# define MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES +# endif +# define MOZ_HAVE_EXPLICIT_CONVERSION +# endif +# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline)) +# define MOZ_HAVE_NORETURN __attribute__((noreturn)) +#endif + +/* + * When built with clang analyzer (a.k.a scan-build), define MOZ_HAVE_NORETURN + * to mark some false positives + */ +#ifdef __clang_analyzer__ +# if __has_extension(attribute_analyzer_noreturn) +# define MOZ_HAVE_ANALYZER_NORETURN __attribute__((analyzer_noreturn)) +# endif +#endif + +/* + * The MOZ_CONSTEXPR specifier declares that a C++11 compiler can evaluate a + * function at compile time. A constexpr function cannot examine any values + * except its arguments and can have no side effects except its return value. + * The MOZ_CONSTEXPR_VAR specifier tells a C++11 compiler that a variable's + * value may be computed at compile time. It should be preferred to just + * marking variables as MOZ_CONSTEXPR because if the compiler does not support + * constexpr it will fall back to making the variable const, and some compilers + * do not accept variables being marked both const and constexpr. + */ +#ifdef MOZ_HAVE_CXX11_CONSTEXPR +# define MOZ_CONSTEXPR constexpr +# define MOZ_CONSTEXPR_VAR constexpr +# ifdef MOZ_HAVE_CXX11_CONSTEXPR_IN_TEMPLATES +# define MOZ_CONSTEXPR_TMPL constexpr +# else +# define MOZ_CONSTEXPR_TMPL +# endif +#else +# define MOZ_CONSTEXPR /* no support */ +# define MOZ_CONSTEXPR_VAR const +# define MOZ_CONSTEXPR_TMPL +#endif + +/* + * MOZ_EXPLICIT_CONVERSION is a specifier on a type conversion + * overloaded operator that declares that a C++11 compiler should restrict + * this operator to allow only explicit type conversions, disallowing + * implicit conversions. + * + * Example: + * + * template<typename T> + * class Ptr + * { + * T* mPtr; + * MOZ_EXPLICIT_CONVERSION operator bool() const + * { + * return mPtr != nullptr; + * } + * }; + * + */ +#ifdef MOZ_HAVE_EXPLICIT_CONVERSION +# define MOZ_EXPLICIT_CONVERSION explicit +#else +# define MOZ_EXPLICIT_CONVERSION /* no support */ +#endif + +/* + * MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the + * method decorated with it must never be inlined, even if the compiler would + * otherwise choose to inline the method. Compilers aren't absolutely + * guaranteed to support this, but most do. + */ +#if defined(MOZ_HAVE_NEVER_INLINE) +# define MOZ_NEVER_INLINE MOZ_HAVE_NEVER_INLINE +#else +# define MOZ_NEVER_INLINE /* no support */ +#endif + +/* + * MOZ_NORETURN, specified at the start of a function declaration, indicates + * that the given function does not return. (The function definition does not + * need to be annotated.) + * + * MOZ_NORETURN void abort(const char* msg); + * + * This modifier permits the compiler to optimize code assuming a call to such a + * function will never return. It also enables the compiler to avoid spurious + * warnings about not initializing variables, or about any other seemingly-dodgy + * operations performed after the function returns. + * + * This modifier does not affect the corresponding function's linking behavior. + */ +#if defined(MOZ_HAVE_NORETURN) +# define MOZ_NORETURN MOZ_HAVE_NORETURN +#else +# define MOZ_NORETURN /* no support */ +#endif + +/** + * MOZ_COLD tells the compiler that a function is "cold", meaning infrequently + * executed. This may lead it to optimize for size more aggressively than speed, + * or to allocate the body of the function in a distant part of the text segment + * to help keep it from taking up unnecessary icache when it isn't in use. + * + * Place this attribute at the very beginning of a function definition. For + * example, write + * + * MOZ_COLD int foo(); + * + * or + * + * MOZ_COLD int foo() { return 42; } + */ +#if defined(__GNUC__) || defined(__clang__) +# define MOZ_COLD __attribute__ ((cold)) +#else +# define MOZ_COLD +#endif + +/** + * MOZ_NONNULL tells the compiler that some of the arguments to a function are + * known to be non-null. The arguments are a list of 1-based argument indexes + * identifying arguments which are known to be non-null. + * + * Place this attribute at the very beginning of a function definition. For + * example, write + * + * MOZ_NONNULL(1, 2) int foo(char *p, char *q); + */ +#if defined(__GNUC__) || defined(__clang__) +# define MOZ_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__))) +#else +# define MOZ_NONNULL(...) +#endif + +/* + * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function + * declaration, indicates that for the purposes of static analysis, this + * function does not return. (The function definition does not need to be + * annotated.) + * + * MOZ_ReportCrash(const char* s, const char* file, int ln) + * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS + * + * Some static analyzers, like scan-build from clang, can use this information + * to eliminate false positives. From the upstream documentation of scan-build: + * "This attribute is useful for annotating assertion handlers that actually + * can return, but for the purpose of using the analyzer we want to pretend + * that such functions do not return." + * + */ +#if defined(MOZ_HAVE_ANALYZER_NORETURN) +# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS MOZ_HAVE_ANALYZER_NORETURN +#else +# define MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS /* no support */ +#endif + +/* + * MOZ_ASAN_DENYLIST is a macro to tell AddressSanitizer (a compile-time + * instrumentation shipped with Clang and GCC) to not instrument the annotated + * function. Furthermore, it will prevent the compiler from inlining the + * function because inlining currently breaks the denylisting mechanism of + * AddressSanitizer. + */ +#if defined(__has_feature) +# if __has_feature(address_sanitizer) +# define MOZ_HAVE_ASAN_DENYLIST +# endif +#elif defined(__GNUC__) +# if defined(__SANITIZE_ADDRESS__) +# define MOZ_HAVE_ASAN_DENYLIST +# endif +#endif + +#if defined(MOZ_HAVE_ASAN_DENYLIST) +# define MOZ_ASAN_DENYLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_address)) +#else +# define MOZ_ASAN_DENYLIST /* nothing */ +#endif + +/* + * MOZ_TSAN_DENYLIST is a macro to tell ThreadSanitizer (a compile-time + * instrumentation shipped with Clang) to not instrument the annotated function. + * Furthermore, it will prevent the compiler from inlining the function because + * inlining currently breaks the denylisting mechanism of ThreadSanitizer. + */ +#if defined(__has_feature) +# if __has_feature(thread_sanitizer) +# define MOZ_TSAN_DENYLIST MOZ_NEVER_INLINE __attribute__((no_sanitize_thread)) +# else +# define MOZ_TSAN_DENYLIST /* nothing */ +# endif +#else +# define MOZ_TSAN_DENYLIST /* nothing */ +#endif + +/** + * MOZ_ALLOCATOR tells the compiler that the function it marks returns either a + * "fresh", "pointer-free" block of memory, or nullptr. "Fresh" means that the + * block is not pointed to by any other reachable pointer in the program. + * "Pointer-free" means that the block contains no pointers to any valid object + * in the program. It may be initialized with other (non-pointer) values. + * + * Placing this attribute on appropriate functions helps GCC analyze pointer + * aliasing more accurately in their callers. + * + * GCC warns if a caller ignores the value returned by a function marked with + * MOZ_ALLOCATOR: it is hard to imagine cases where dropping the value returned + * by a function that meets the criteria above would be intentional. + * + * Place this attribute after the argument list and 'this' qualifiers of a + * function definition. For example, write + * + * void *my_allocator(size_t) MOZ_ALLOCATOR; + * + * or + * + * void *my_allocator(size_t bytes) MOZ_ALLOCATOR { ... } + */ +#if defined(__GNUC__) || defined(__clang__) +# define MOZ_ALLOCATOR __attribute__ ((malloc, warn_unused_result)) +#else +# define MOZ_ALLOCATOR +#endif + +/** + * MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's + * return value is not used by the caller. + * + * Place this attribute at the very beginning of a function definition. For + * example, write + * + * MOZ_WARN_UNUSED_RESULT int foo(); + * + * or + * + * MOZ_WARN_UNUSED_RESULT int foo() { return 42; } + */ +#if defined(__GNUC__) || defined(__clang__) +# define MOZ_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result)) +#else +# define MOZ_WARN_UNUSED_RESULT +#endif + +#ifdef __cplusplus + +/* + * The following macros are attributes that support the static analysis plugin + * included with Mozilla, and will be implemented (when such support is enabled) + * as C++11 attributes. Since such attributes are legal pretty much everywhere + * and have subtly different semantics depending on their placement, the + * following is a guide on where to place the attributes. + * + * Attributes that apply to a struct or class precede the name of the class: + * (Note that this is different from the placement of final for classes!) + * + * class MOZ_CLASS_ATTRIBUTE SomeClass {}; + * + * Attributes that apply to functions follow the parentheses and const + * qualifiers but precede final, override and the function body: + * + * void DeclaredFunction() MOZ_FUNCTION_ATTRIBUTE; + * void SomeFunction() MOZ_FUNCTION_ATTRIBUTE {} + * void PureFunction() const MOZ_FUNCTION_ATTRIBUTE = 0; + * void OverriddenFunction() MOZ_FUNCTION_ATTRIBUTE override; + * + * Attributes that apply to variables or parameters follow the variable's name: + * + * int variable MOZ_VARIABLE_ATTRIBUTE; + * + * Attributes that apply to types follow the type name: + * + * typedef int MOZ_TYPE_ATTRIBUTE MagicInt; + * int MOZ_TYPE_ATTRIBUTE someVariable; + * int* MOZ_TYPE_ATTRIBUTE magicPtrInt; + * int MOZ_TYPE_ATTRIBUTE* ptrToMagicInt; + * + * Attributes that apply to statements precede the statement: + * + * MOZ_IF_ATTRIBUTE if (x == 0) + * MOZ_DO_ATTRIBUTE do { } while (0); + * + * Attributes that apply to labels precede the label: + * + * MOZ_LABEL_ATTRIBUTE target: + * goto target; + * MOZ_CASE_ATTRIBUTE case 5: + * MOZ_DEFAULT_ATTRIBUTE default: + * + * The static analyses that are performed by the plugin are as follows: + * + * MOZ_MUST_OVERRIDE: Applies to all C++ member functions. All immediate + * subclasses must provide an exact override of this method; if a subclass + * does not override this method, the compiler will emit an error. This + * attribute is not limited to virtual methods, so if it is applied to a + * nonvirtual method and the subclass does not provide an equivalent + * definition, the compiler will emit an error. + * MOZ_STACK_CLASS: Applies to all classes. Any class with this annotation is + * expected to live on the stack, so it is a compile-time error to use it, or + * an array of such objects, as a global or static variable, or as the type of + * a new expression (unless placement new is being used). If a member of + * another class uses this class, or if another class inherits from this + * class, then it is considered to be a stack class as well, although this + * attribute need not be provided in such cases. + * MOZ_NONHEAP_CLASS: Applies to all classes. Any class with this annotation is + * expected to live on the stack or in static storage, so it is a compile-time + * error to use it, or an array of such objects, as the type of a new + * expression (unless placement new is being used). If a member of another + * class uses this class, or if another class inherits from this class, then + * it is considered to be a non-heap class as well, although this attribute + * need not be provided in such cases. + * MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS: Applies to all classes that are + * intended to prevent introducing static initializers. This attribute + * currently makes it a compile-time error to instantiate these classes + * anywhere other than at the global scope, or as a static member of a class. + * MOZ_TRIVIAL_CTOR_DTOR: Applies to all classes that must have both a trivial + * constructor and a trivial destructor. Setting this attribute on a class + * makes it a compile-time error for that class to get a non-trivial + * constructor or destructor for any reason. + * MOZ_HEAP_ALLOCATOR: Applies to any function. This indicates that the return + * value is allocated on the heap, and will as a result check such allocations + * during MOZ_STACK_CLASS and MOZ_NONHEAP_CLASS annotation checking. + * MOZ_IMPLICIT: Applies to constructors. Implicit conversion constructors + * are disallowed by default unless they are marked as MOZ_IMPLICIT. This + * attribute must be used for constructors which intend to provide implicit + * conversions. + * MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT: Applies to functions. Makes it a compile + * time error to pass arithmetic expressions on variables to the function. + * MOZ_OWNING_REF: Applies to declarations of pointer types. This attribute + * tells the compiler that the raw pointer is a strong reference, and that + * property is somehow enforced by the code. This can make the compiler + * ignore these pointers when validating the usage of pointers otherwise. + * MOZ_NON_OWNING_REF: Applies to declarations of pointer types. This attribute + * tells the compiler that the raw pointer is a weak reference, and that + * property is somehow enforced by the code. This can make the compiler + * ignore these pointers when validating the usage of pointers otherwise. + * MOZ_UNSAFE_REF: Applies to declarations of pointer types. This attribute + * should be used for non-owning references that can be unsafe, and their + * safety needs to be validated through code inspection. The string argument + * passed to this macro documents the safety conditions. + * MOZ_NO_ADDREF_RELEASE_ON_RETURN: Applies to function declarations. Makes it + * a compile time error to call AddRef or Release on the return value of a + * function. This is intended to be used with operator->() of our smart + * pointer classes to ensure that the refcount of an object wrapped in a + * smart pointer is not manipulated directly. + */ +#ifdef MOZ_CLANG_PLUGIN +# define MOZ_MUST_OVERRIDE __attribute__((annotate("moz_must_override"))) +# define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class"))) +# define MOZ_NONHEAP_CLASS __attribute__((annotate("moz_nonheap_class"))) +# define MOZ_TRIVIAL_CTOR_DTOR __attribute__((annotate("moz_trivial_ctor_dtor"))) +# ifdef DEBUG + /* in debug builds, these classes do have non-trivial constructors. */ +# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) +# else +# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS __attribute__((annotate("moz_global_class"))) \ + MOZ_TRIVIAL_CTOR_DTOR +# endif +# define MOZ_IMPLICIT __attribute__((annotate("moz_implicit"))) +# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT __attribute__((annotate("moz_no_arith_expr_in_arg"))) +# define MOZ_OWNING_REF __attribute__((annotate("moz_strong_ref"))) +# define MOZ_NON_OWNING_REF __attribute__((annotate("moz_weak_ref"))) +# define MOZ_UNSAFE_REF(reason) __attribute__((annotate("moz_strong_ref"))) +# define MOZ_NO_ADDREF_RELEASE_ON_RETURN __attribute__((annotate("moz_no_addref_release_on_return"))) +/* + * It turns out that clang doesn't like void func() __attribute__ {} without a + * warning, so use pragmas to disable the warning. This code won't work on GCC + * anyways, so the warning is safe to ignore. + */ +# define MOZ_HEAP_ALLOCATOR \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((annotate("moz_heap_allocator"))) \ + _Pragma("clang diagnostic pop") +#else +# define MOZ_MUST_OVERRIDE /* nothing */ +# define MOZ_STACK_CLASS /* nothing */ +# define MOZ_NONHEAP_CLASS /* nothing */ +# define MOZ_TRIVIAL_CTOR_DTOR /* nothing */ +# define MOZ_ONLY_USED_TO_AVOID_STATIC_CONSTRUCTORS /* nothing */ +# define MOZ_IMPLICIT /* nothing */ +# define MOZ_NO_ARITHMETIC_EXPR_IN_ARGUMENT /* nothing */ +# define MOZ_HEAP_ALLOCATOR /* nothing */ +# define MOZ_OWNING_REF /* nothing */ +# define MOZ_NON_OWNING_REF /* nothing */ +# define MOZ_UNSAFE_REF(reason) /* nothing */ +# define MOZ_NO_ADDREF_RELEASE_ON_RETURN /* nothing */ +#endif /* MOZ_CLANG_PLUGIN */ + +#endif /* __cplusplus */ + +#endif /* mozilla_Attributes_h */ diff --git a/include/onlineupdate/mozilla/Compiler.h b/include/onlineupdate/mozilla/Compiler.h new file mode 100644 index 000000000..6d6fcbbb1 --- /dev/null +++ b/include/onlineupdate/mozilla/Compiler.h @@ -0,0 +1,110 @@ +/* -*- 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/. */ + +/* Various compiler checks. */ + +#ifndef mozilla_Compiler_h +#define mozilla_Compiler_h + +#define MOZ_IS_GCC 0 +#define MOS_IS_MSVC 0 + +#if !defined(__clang__) && defined(__GNUC__) + +# undef MOZ_IS_GCC +# define MOZ_IS_GCC 1 + /* + * This macro should simplify gcc version checking. For example, to check + * for gcc 4.7.1 or later, check `#if MOZ_GCC_VERSION_AT_LEAST(4, 7, 1)`. + */ +# define MOZ_GCC_VERSION_AT_LEAST(major, minor, patchlevel) \ + ((__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) \ + >= ((major) * 10000 + (minor) * 100 + (patchlevel))) +# if !MOZ_GCC_VERSION_AT_LEAST(4, 7, 0) +# error "mfbt (and Gecko) require at least gcc 4.7 to build." +# endif + +#elif defined(_MSC_VER) + +# undef MOZ_IS_MSVC +# define MOZ_IS_MSVC 1 + +#endif + +/* + * The situation with standard libraries is a lot worse than with compilers, + * particularly as clang and gcc could end up using one of three or so standard + * libraries, and they may not be up-to-snuff with newer C++11 versions. To + * detect the library, we're going to include cstddef (which is a small header + * which will be transitively included by everybody else at some point) to grab + * the version macros and deduce macros from there. + */ +#ifdef __cplusplus +# include <cstddef> +# ifdef _STLPORT_MAJOR +# define MOZ_USING_STLPORT 1 +# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) \ + (_STLPORT_VERSION >= ((major) << 8 | (minor) << 4 | (patch))) +# elif defined(_LIBCPP_VERSION) + /* + * libc++, unfortunately, doesn't appear to have useful versioning macros. + * Hopefully, the recommendations of N3694 with respect to standard libraries + * will get applied instead and we won't need to worry about version numbers + * here. + */ +# define MOZ_USING_LIBCXX 1 +# elif defined(__GLIBCXX__) +# define MOZ_USING_LIBSTDCXX 1 + /* + * libstdc++ is also annoying and doesn't give us useful versioning macros + * for the library. If we're using gcc, then assume that libstdc++ matches + * the compiler version. If we're using clang, we're going to have to fake + * major/minor combinations by looking for newly-defined config macros. + */ +# if MOZ_IS_GCC +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + MOZ_GCC_VERSION_AT_LEAST(major, minor, patch) +# elif defined(_GLIBCXX_THROW_OR_ABORT) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 8)) +# elif defined(_GLIBCXX_NOEXCEPT) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 7)) +# elif defined(_GLIBCXX_USE_DEPRECATED) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 6)) +# elif defined(_GLIBCXX_PSEUDO_VISIBILITY) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 5)) +# elif defined(_GLIBCXX_BEGIN_EXTERN_C) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 4)) +# elif defined(_GLIBCXX_VISIBILITY_ATTR) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 3)) +# elif defined(_GLIBCXX_VISIBILITY) +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) \ + ((major) < 4 || ((major) == 4 && (minor) <= 2)) +# else +# error "Your version of libstdc++ is unknown to us and is likely too old." +# endif +# endif + + // Flesh out the defines for everyone else +# ifndef MOZ_USING_STLPORT +# define MOZ_USING_STLPORT 0 +# define MOZ_STLPORT_VERSION_AT_LEAST(major, minor, patch) 0 +# endif +# ifndef MOZ_USING_LIBCXX +# define MOZ_USING_LIBCXX 0 +# endif +# ifndef MOZ_USING_LIBSTDCXX +# define MOZ_USING_LIBSTDCXX 0 +# define MOZ_LIBSTDCXX_VERSION_AT_LEAST(major, minor, patch) 0 +# endif +#endif /* __cplusplus */ + +#endif /* mozilla_Compiler_h */ diff --git a/include/onlineupdate/mozilla/Likely.h b/include/onlineupdate/mozilla/Likely.h new file mode 100644 index 000000000..5625bb226 --- /dev/null +++ b/include/onlineupdate/mozilla/Likely.h @@ -0,0 +1,23 @@ +/* -*- 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/. */ + +/* + * MOZ_LIKELY and MOZ_UNLIKELY macros to hint to the compiler how a + * boolean predicate should be branch-predicted. + */ + +#ifndef mozilla_Likely_h +#define mozilla_Likely_h + +#if defined(__clang__) || defined(__GNUC__) +#define MOZ_LIKELY(x) (__builtin_expect(!!(x), 1)) +#define MOZ_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#else +#define MOZ_LIKELY(x) (!!(x)) +#define MOZ_UNLIKELY(x) (!!(x)) +#endif + +#endif /* mozilla_Likely_h */ diff --git a/include/onlineupdate/mozilla/MacroArgs.h b/include/onlineupdate/mozilla/MacroArgs.h new file mode 100644 index 000000000..c8b733821 --- /dev/null +++ b/include/onlineupdate/mozilla/MacroArgs.h @@ -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. 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__ + +/* + * 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 */ diff --git a/include/onlineupdate/mozilla/TypeTraits.h b/include/onlineupdate/mozilla/TypeTraits.h new file mode 100644 index 000000000..7ca9d3315 --- /dev/null +++ b/include/onlineupdate/mozilla/TypeTraits.h @@ -0,0 +1,1116 @@ +/* -*- 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/. */ + +/* Template-based metaprogramming and type-testing facilities. */ + +#ifndef mozilla_TypeTraits_h +#define mozilla_TypeTraits_h + +#include "Types.h" + +/* + * These traits are approximate copies of the traits and semantics from C++11's + * <type_traits> header. Don't add traits not in that header! When all + * platforms provide that header, we can convert all users and remove this one. + */ + +#include <wchar.h> + +namespace mozilla { + +/* Forward declarations. */ + +template<typename> struct RemoveCV; + +/* 20.9.3 Helper classes [meta.help] */ + +/** + * Helper class used as a base for various type traits, exposed publicly + * because <type_traits> exposes it as well. + */ +template<typename T, T Value> +struct IntegralConstant +{ + static const T value = Value; + typedef T ValueType; + typedef IntegralConstant<T, Value> Type; +}; + +/** Convenient aliases. */ +typedef IntegralConstant<bool, true> TrueType; +typedef IntegralConstant<bool, false> FalseType; + +/* 20.9.4 Unary type traits [meta.unary] */ + +/* 20.9.4.1 Primary type categories [meta.unary.cat] */ + +namespace detail { + +template<typename T> +struct IsVoidHelper : FalseType {}; + +template<> +struct IsVoidHelper<void> : TrueType {}; + +} // namespace detail + +/** + * IsVoid determines whether a type is void. + * + * mozilla::IsVoid<int>::value is false; + * mozilla::IsVoid<void>::value is true; + * mozilla::IsVoid<void*>::value is false; + * mozilla::IsVoid<volatile void>::value is true. + */ +template<typename T> +struct IsVoid : detail::IsVoidHelper<typename RemoveCV<T>::Type> {}; + +namespace detail { + +template <typename T> +struct IsIntegralHelper : FalseType {}; + +template<> struct IsIntegralHelper<char> : TrueType {}; +template<> struct IsIntegralHelper<signed char> : TrueType {}; +template<> struct IsIntegralHelper<unsigned char> : TrueType {}; +template<> struct IsIntegralHelper<short> : TrueType {}; +template<> struct IsIntegralHelper<unsigned short> : TrueType {}; +template<> struct IsIntegralHelper<int> : TrueType {}; +template<> struct IsIntegralHelper<unsigned int> : TrueType {}; +template<> struct IsIntegralHelper<long> : TrueType {}; +template<> struct IsIntegralHelper<unsigned long> : TrueType {}; +template<> struct IsIntegralHelper<long long> : TrueType {}; +template<> struct IsIntegralHelper<unsigned long long> : TrueType {}; +template<> struct IsIntegralHelper<bool> : TrueType {}; +template<> struct IsIntegralHelper<wchar_t> : TrueType {}; +#ifdef MOZ_CHAR16_IS_NOT_WCHAR +template<> struct IsIntegralHelper<char16_t> : TrueType {}; +#endif + +} /* namespace detail */ + +/** + * IsIntegral determines whether a type is an integral type. + * + * mozilla::IsIntegral<int>::value is true; + * mozilla::IsIntegral<unsigned short>::value is true; + * mozilla::IsIntegral<const long>::value is true; + * mozilla::IsIntegral<int*>::value is false; + * mozilla::IsIntegral<double>::value is false; + * + * Note that the behavior of IsIntegral on char16_t and char32_t is + * unspecified. + */ +template<typename T> +struct IsIntegral : detail::IsIntegralHelper<typename RemoveCV<T>::Type> +{}; + +template<typename T, typename U> +struct IsSame; + +namespace detail { + +template<typename T> +struct IsFloatingPointHelper + : IntegralConstant<bool, + IsSame<T, float>::value || + IsSame<T, double>::value || + IsSame<T, long double>::value> +{}; + +} // namespace detail + +/** + * IsFloatingPoint determines whether a type is a floating point type (float, + * double, long double). + * + * mozilla::IsFloatingPoint<int>::value is false; + * mozilla::IsFloatingPoint<const float>::value is true; + * mozilla::IsFloatingPoint<long double>::value is true; + * mozilla::IsFloatingPoint<double*>::value is false. + */ +template<typename T> +struct IsFloatingPoint + : detail::IsFloatingPointHelper<typename RemoveCV<T>::Type> +{}; + +namespace detail { + +template<typename T> +struct IsArrayHelper : FalseType {}; + +template<typename T, decltype(sizeof(1)) N> +struct IsArrayHelper<T[N]> : TrueType {}; + +template<typename T> +struct IsArrayHelper<T[]> : TrueType {}; + +} // namespace detail + +/** + * IsArray determines whether a type is an array type, of known or unknown + * length. + * + * mozilla::IsArray<int>::value is false; + * mozilla::IsArray<int[]>::value is true; + * mozilla::IsArray<int[5]>::value is true. + */ +template<typename T> +struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type> +{}; + +namespace detail { + +template<typename T> +struct IsPointerHelper : FalseType {}; + +template<typename T> +struct IsPointerHelper<T*> : TrueType {}; + +} // namespace detail + +/** + * IsPointer determines whether a type is a possibly-CV-qualified pointer type + * (but not a pointer-to-member type). + * + * mozilla::IsPointer<struct S*>::value is true; + * mozilla::IsPointer<int*>::value is true; + * mozilla::IsPointer<int**>::value is true; + * mozilla::IsPointer<const int*>::value is true; + * mozilla::IsPointer<int* const>::value is true; + * mozilla::IsPointer<int* volatile>::value is true; + * mozilla::IsPointer<void (*)(void)>::value is true; + * mozilla::IsPointer<int>::value is false; + * mozilla::IsPointer<struct S>::value is false. + * mozilla::IsPointer<int(struct S::*)>::value is false + */ +template<typename T> +struct IsPointer : detail::IsPointerHelper<typename RemoveCV<T>::Type> +{}; + +/** + * IsLvalueReference determines whether a type is an lvalue reference. + * + * mozilla::IsLvalueReference<struct S*>::value is false; + * mozilla::IsLvalueReference<int**>::value is false; + * mozilla::IsLvalueReference<void (*)(void)>::value is false; + * mozilla::IsLvalueReference<int>::value is false; + * mozilla::IsLvalueReference<struct S>::value is false; + * mozilla::IsLvalueReference<struct S*&>::value is true; + * mozilla::IsLvalueReference<struct S&&>::value is false. + */ +template<typename T> +struct IsLvalueReference : FalseType {}; + +template<typename T> +struct IsLvalueReference<T&> : TrueType {}; + +/** + * IsRvalueReference determines whether a type is an rvalue reference. + * + * mozilla::IsRvalueReference<struct S*>::value is false; + * mozilla::IsRvalueReference<int**>::value is false; + * mozilla::IsRvalueReference<void (*)(void)>::value is false; + * mozilla::IsRvalueReference<int>::value is false; + * mozilla::IsRvalueReference<struct S>::value is false; + * mozilla::IsRvalueReference<struct S*&>::value is false; + * mozilla::IsRvalueReference<struct S&&>::value is true. + */ +template<typename T> +struct IsRvalueReference : FalseType {}; + +template<typename T> +struct IsRvalueReference<T&&> : TrueType {}; + +namespace detail { + +// __is_enum is a supported extension across all of our supported compilers. +template<typename T> +struct IsEnumHelper + : IntegralConstant<bool, __is_enum(T)> +{}; + +} // namespace detail + +/** + * IsEnum determines whether a type is an enum type. + * + * mozilla::IsEnum<enum S>::value is true; + * mozilla::IsEnum<enum S*>::value is false; + * mozilla::IsEnum<int>::value is false; + */ +template<typename T> +struct IsEnum + : detail::IsEnumHelper<typename RemoveCV<T>::Type> +{}; + +namespace detail { + +// __is_class is a supported extension across all of our supported compilers: +// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html +// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits +// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx +template<typename T> +struct IsClassHelper + : IntegralConstant<bool, __is_class(T)> +{}; + +} // namespace detail + +/** + * IsClass determines whether a type is a class type (but not a union). + * + * struct S {}; + * union U {}; + * mozilla::IsClass<int>::value is false; + * mozilla::IsClass<const S>::value is true; + * mozilla::IsClass<U>::value is false; + */ +template<typename T> +struct IsClass + : detail::IsClassHelper<typename RemoveCV<T>::Type> +{}; + +/* 20.9.4.2 Composite type traits [meta.unary.comp] */ + +/** + * IsReference determines whether a type is an lvalue or rvalue reference. + * + * mozilla::IsReference<struct S*>::value is false; + * mozilla::IsReference<int**>::value is false; + * mozilla::IsReference<int&>::value is true; + * mozilla::IsReference<void (*)(void)>::value is false; + * mozilla::IsReference<const int&>::value is true; + * mozilla::IsReference<int>::value is false; + * mozilla::IsReference<struct S>::value is false; + * mozilla::IsReference<struct S&>::value is true; + * mozilla::IsReference<struct S*&>::value is true; + * mozilla::IsReference<struct S&&>::value is true. + */ +template<typename T> +struct IsReference + : IntegralConstant<bool, + IsLvalueReference<T>::value || IsRvalueReference<T>::value> +{}; + +/** + * IsArithmetic determines whether a type is arithmetic. A type is arithmetic + * iff it is an integral type or a floating point type. + * + * mozilla::IsArithmetic<int>::value is true; + * mozilla::IsArithmetic<double>::value is true; + * mozilla::IsArithmetic<long double*>::value is false. + */ +template<typename T> +struct IsArithmetic + : IntegralConstant<bool, IsIntegral<T>::value || IsFloatingPoint<T>::value> +{}; + +/* 20.9.4.3 Type properties [meta.unary.prop] */ + +/** + * IsConst determines whether a type is const or not. + * + * mozilla::IsConst<int>::value is false; + * mozilla::IsConst<void* const>::value is true; + * mozilla::IsConst<const char*>::value is false. + */ +template<typename T> +struct IsConst : FalseType {}; + +template<typename T> +struct IsConst<const T> : TrueType {}; + +/** + * IsVolatile determines whether a type is volatile or not. + * + * mozilla::IsVolatile<int>::value is false; + * mozilla::IsVolatile<void* volatile>::value is true; + * mozilla::IsVolatile<volatile char*>::value is false. + */ +template<typename T> +struct IsVolatile : FalseType {}; + +template<typename T> +struct IsVolatile<volatile T> : TrueType {}; + +/** + * Traits class for identifying POD types. Until C++11 there's no automatic + * way to detect PODs, so for the moment this is done manually. Users may + * define specializations of this class that inherit from mozilla::TrueType and + * mozilla::FalseType (or equivalently mozilla::IntegralConstant<bool, true or + * false>, or conveniently from mozilla::IsPod for composite types) as needed to + * ensure correct IsPod behavior. + */ +template<typename T> +struct IsPod : public FalseType {}; + +template<> struct IsPod<char> : TrueType {}; +template<> struct IsPod<signed char> : TrueType {}; +template<> struct IsPod<unsigned char> : TrueType {}; +template<> struct IsPod<short> : TrueType {}; +template<> struct IsPod<unsigned short> : TrueType {}; +template<> struct IsPod<int> : TrueType {}; +template<> struct IsPod<unsigned int> : TrueType {}; +template<> struct IsPod<long> : TrueType {}; +template<> struct IsPod<unsigned long> : TrueType {}; +template<> struct IsPod<long long> : TrueType {}; +template<> struct IsPod<unsigned long long> : TrueType {}; +template<> struct IsPod<bool> : TrueType {}; +template<> struct IsPod<float> : TrueType {}; +template<> struct IsPod<double> : TrueType {}; +template<> struct IsPod<wchar_t> : TrueType {}; +#ifdef MOZ_CHAR16_IS_NOT_WCHAR +template<> struct IsPod<char16_t> : TrueType {}; +#endif +template<typename T> struct IsPod<T*> : TrueType {}; + +namespace detail { + +// __is_empty is a supported extension across all of our supported compilers: +// http://llvm.org/releases/3.0/docs/ClangReleaseNotes.html +// http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Type-Traits.html#Type-Traits +// http://msdn.microsoft.com/en-us/library/ms177194%28v=vs.100%29.aspx +template<typename T> +struct IsEmptyHelper + : IntegralConstant<bool, IsClass<T>::value && __is_empty(T)> +{}; + +} // namespace detail + +/** + * IsEmpty determines whether a type is a class (but not a union) that is empty. + * + * A class is empty iff it and all its base classes have no non-static data + * members (except bit-fields of length 0) and no virtual member functions, and + * no base class is empty or a virtual base class. + * + * Intuitively, empty classes don't have any data that has to be stored in + * instances of those classes. (The size of the class must still be non-zero, + * because distinct array elements of any type must have different addresses. + * However, if the Empty Base Optimization is implemented by the compiler [most + * compilers implement it, and in certain cases C++11 requires it], the size of + * a class inheriting from an empty |Base| class need not be inflated by + * |sizeof(Base)|.) And intuitively, non-empty classes have data members and/or + * vtable pointers that must be stored in each instance for proper behavior. + * + * static_assert(!mozilla::IsEmpty<int>::value, "not a class => not empty"); + * union U1 { int x; }; + * static_assert(!mozilla::IsEmpty<U1>::value, "not a class => not empty"); + * struct E1 {}; + * struct E2 { int : 0 }; + * struct E3 : E1 {}; + * struct E4 : E2 {}; + * static_assert(mozilla::IsEmpty<E1>::value && + * mozilla::IsEmpty<E2>::value && + * mozilla::IsEmpty<E3>::value && + * mozilla::IsEmpty<E4>::value, + * "all empty"); + * union U2 { E1 e1; }; + * static_assert(!mozilla::IsEmpty<U2>::value, "not a class => not empty"); + * struct NE1 { int x; }; + * struct NE2 : virtual E1 {}; + * struct NE3 : E2 { virtual ~NE3() {} }; + * struct NE4 { virtual void f() {} }; + * static_assert(!mozilla::IsEmpty<NE1>::value && + * !mozilla::IsEmpty<NE2>::value && + * !mozilla::IsEmpty<NE3>::value && + * !mozilla::IsEmpty<NE4>::value, + * "all empty"); + */ +template<typename T> +struct IsEmpty : detail::IsEmptyHelper<typename RemoveCV<T>::Type> +{}; + + +namespace detail { + +template<typename T, + bool = IsFloatingPoint<T>::value, + bool = IsIntegral<T>::value, + typename NoCV = typename RemoveCV<T>::Type> +struct IsSignedHelper; + +// Floating point is signed. +template<typename T, typename NoCV> +struct IsSignedHelper<T, true, false, NoCV> : TrueType {}; + +// Integral is conditionally signed. +template<typename T, typename NoCV> +struct IsSignedHelper<T, false, true, NoCV> + : IntegralConstant<bool, bool(NoCV(-1) < NoCV(1))> +{}; + +// Non-floating point, non-integral is not signed. +template<typename T, typename NoCV> +struct IsSignedHelper<T, false, false, NoCV> : FalseType {}; + +} // namespace detail + +/** + * IsSigned determines whether a type is a signed arithmetic type. |char| is + * considered a signed type if it has the same representation as |signed char|. + * + * mozilla::IsSigned<int>::value is true; + * mozilla::IsSigned<const unsigned int>::value is false; + * mozilla::IsSigned<unsigned char>::value is false; + * mozilla::IsSigned<float>::value is true. + */ +template<typename T> +struct IsSigned : detail::IsSignedHelper<T> {}; + +namespace detail { + +template<typename T, + bool = IsFloatingPoint<T>::value, + bool = IsIntegral<T>::value, + typename NoCV = typename RemoveCV<T>::Type> +struct IsUnsignedHelper; + +// Floating point is not unsigned. +template<typename T, typename NoCV> +struct IsUnsignedHelper<T, true, false, NoCV> : FalseType {}; + +// Integral is conditionally unsigned. +template<typename T, typename NoCV> +struct IsUnsignedHelper<T, false, true, NoCV> + : IntegralConstant<bool, + (IsSame<NoCV, bool>::value || bool(NoCV(1) < NoCV(-1)))> +{}; + +// Non-floating point, non-integral is not unsigned. +template<typename T, typename NoCV> +struct IsUnsignedHelper<T, false, false, NoCV> : FalseType {}; + +} // namespace detail + +/** + * IsUnsigned determines whether a type is an unsigned arithmetic type. + * + * mozilla::IsUnsigned<int>::value is false; + * mozilla::IsUnsigned<const unsigned int>::value is true; + * mozilla::IsUnsigned<unsigned char>::value is true; + * mozilla::IsUnsigned<float>::value is false. + */ +template<typename T> +struct IsUnsigned : detail::IsUnsignedHelper<T> {}; + +/* 20.9.5 Type property queries [meta.unary.prop.query] */ + +/* 20.9.6 Relationships between types [meta.rel] */ + +/** + * IsSame tests whether two types are the same type. + * + * mozilla::IsSame<int, int>::value is true; + * mozilla::IsSame<int*, int*>::value is true; + * mozilla::IsSame<int, unsigned int>::value is false; + * mozilla::IsSame<void, void>::value is true; + * mozilla::IsSame<const int, int>::value is false; + * mozilla::IsSame<struct S, struct S>::value is true. + */ +template<typename T, typename U> +struct IsSame : FalseType {}; + +template<typename T> +struct IsSame<T, T> : TrueType {}; + +namespace detail { + +#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) + +template<class Base, class Derived> +struct BaseOfTester : IntegralConstant<bool, __is_base_of(Base, Derived)> {}; + +#else + +// The trickery used to implement IsBaseOf here makes it possible to use it for +// the cases of private and multiple inheritance. This code was inspired by the +// sample code here: +// +// http://stackoverflow.com/questions/2910979/how-is-base-of-works +template<class Base, class Derived> +struct BaseOfHelper +{ +public: + operator Base*() const; + operator Derived*(); +}; + +template<class Base, class Derived> +struct BaseOfTester +{ +private: + template<class T> + static char test(Derived*, T); + static int test(Base*, int); + +public: + static const bool value = + sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char); +}; + +template<class Base, class Derived> +struct BaseOfTester<Base, const Derived> +{ +private: + template<class T> + static char test(Derived*, T); + static int test(Base*, int); + +public: + static const bool value = + sizeof(test(BaseOfHelper<Base, Derived>(), int())) == sizeof(char); +}; + +template<class Base, class Derived> +struct BaseOfTester<Base&, Derived&> : FalseType {}; + +template<class Type> +struct BaseOfTester<Type, Type> : TrueType {}; + +template<class Type> +struct BaseOfTester<Type, const Type> : TrueType {}; + +#endif + +} /* namespace detail */ + +/* + * IsBaseOf allows to know whether a given class is derived from another. + * + * Consider the following class definitions: + * + * class A {}; + * class B : public A {}; + * class C {}; + * + * mozilla::IsBaseOf<A, B>::value is true; + * mozilla::IsBaseOf<A, C>::value is false; + */ +template<class Base, class Derived> +struct IsBaseOf + : IntegralConstant<bool, detail::BaseOfTester<Base, Derived>::value> +{}; + +namespace detail { + +template<typename From, typename To> +struct ConvertibleTester +{ +private: + static From create(); + + template<typename From1, typename To1> + static char test(To to); + + template<typename From1, typename To1> + static int test(...); + +public: + static const bool value = + sizeof(test<From, To>(create())) == sizeof(char); +}; + +} // namespace detail + +/** + * IsConvertible determines whether a value of type From will implicitly convert + * to a value of type To. For example: + * + * struct A {}; + * struct B : public A {}; + * struct C {}; + * + * mozilla::IsConvertible<A, A>::value is true; + * mozilla::IsConvertible<A*, A*>::value is true; + * mozilla::IsConvertible<B, A>::value is true; + * mozilla::IsConvertible<B*, A*>::value is true; + * mozilla::IsConvertible<C, A>::value is false; + * mozilla::IsConvertible<A, C>::value is false; + * mozilla::IsConvertible<A*, C*>::value is false; + * mozilla::IsConvertible<C*, A*>::value is false. + * + * For obscure reasons, you can't use IsConvertible when the types being tested + * are related through private inheritance, and you'll get a compile error if + * you try. Just don't do it! + * + * Note - we need special handling for void, which ConvertibleTester doesn't + * handle. The void handling here doesn't handle const/volatile void correctly, + * which could be easily fixed if the need arises. + */ +template<typename From, typename To> +struct IsConvertible + : IntegralConstant<bool, detail::ConvertibleTester<From, To>::value> +{}; + +template<typename B> +struct IsConvertible<void, B> + : IntegralConstant<bool, IsVoid<B>::value> +{}; + +template<typename A> +struct IsConvertible<A, void> + : IntegralConstant<bool, IsVoid<A>::value> +{}; + +template<> +struct IsConvertible<void, void> + : TrueType +{}; + +/* 20.9.7 Transformations between types [meta.trans] */ + +/* 20.9.7.1 Const-volatile modifications [meta.trans.cv] */ + +/** + * RemoveConst removes top-level const qualifications on a type. + * + * mozilla::RemoveConst<int>::Type is int; + * mozilla::RemoveConst<const int>::Type is int; + * mozilla::RemoveConst<const int*>::Type is const int*; + * mozilla::RemoveConst<int* const>::Type is int*. + */ +template<typename T> +struct RemoveConst +{ + typedef T Type; +}; + +template<typename T> +struct RemoveConst<const T> +{ + typedef T Type; +}; + +/** + * RemoveVolatile removes top-level volatile qualifications on a type. + * + * mozilla::RemoveVolatile<int>::Type is int; + * mozilla::RemoveVolatile<volatile int>::Type is int; + * mozilla::RemoveVolatile<volatile int*>::Type is volatile int*; + * mozilla::RemoveVolatile<int* volatile>::Type is int*. + */ +template<typename T> +struct RemoveVolatile +{ + typedef T Type; +}; + +template<typename T> +struct RemoveVolatile<volatile T> +{ + typedef T Type; +}; + +/** + * RemoveCV removes top-level const and volatile qualifications on a type. + * + * mozilla::RemoveCV<int>::Type is int; + * mozilla::RemoveCV<const int>::Type is int; + * mozilla::RemoveCV<volatile int>::Type is int; + * mozilla::RemoveCV<int* const volatile>::Type is int*. + */ +template<typename T> +struct RemoveCV +{ + typedef typename RemoveConst<typename RemoveVolatile<T>::Type>::Type Type; +}; + +/* 20.9.7.2 Reference modifications [meta.trans.ref] */ + +/** + * Converts reference types to the underlying types. + * + * mozilla::RemoveReference<T>::Type is T; + * mozilla::RemoveReference<T&>::Type is T; + * mozilla::RemoveReference<T&&>::Type is T; + */ + +template<typename T> +struct RemoveReference +{ + typedef T Type; +}; + +template<typename T> +struct RemoveReference<T&> +{ + typedef T Type; +}; + +template<typename T> +struct RemoveReference<T&&> +{ + typedef T Type; +}; + +template<bool Condition, typename A, typename B> +struct Conditional; + +namespace detail { + +enum Voidness { TIsVoid, TIsNotVoid }; + +template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid> +struct AddLvalueReferenceHelper; + +template<typename T> +struct AddLvalueReferenceHelper<T, TIsVoid> +{ + typedef void Type; +}; + +template<typename T> +struct AddLvalueReferenceHelper<T, TIsNotVoid> +{ + typedef T& Type; +}; + +} // namespace detail + +/** + * AddLvalueReference adds an lvalue & reference to T if one isn't already + * present. (Note: adding an lvalue reference to an rvalue && reference in + * essence replaces the && with a &&, per C+11 reference collapsing rules. For + * example, int&& would become int&.) + * + * The final computed type will only *not* be an lvalue reference if T is void. + * + * mozilla::AddLvalueReference<int>::Type is int&; + * mozilla::AddLvalueRference<volatile int&>::Type is volatile int&; + * mozilla::AddLvalueReference<void*>::Type is void*&; + * mozilla::AddLvalueReference<void>::Type is void; + * mozilla::AddLvalueReference<struct S&&>::Type is struct S&. + */ +template<typename T> +struct AddLvalueReference + : detail::AddLvalueReferenceHelper<T> +{}; + +namespace detail { + +template<typename T, Voidness V = IsVoid<T>::value ? TIsVoid : TIsNotVoid> +struct AddRvalueReferenceHelper; + +template<typename T> +struct AddRvalueReferenceHelper<T, TIsVoid> +{ + typedef void Type; +}; + +template<typename T> +struct AddRvalueReferenceHelper<T, TIsNotVoid> +{ + typedef T&& Type; +}; + +} // namespace detail + +/** + * AddRvalueReference adds an rvalue && reference to T if one isn't already + * present. (Note: adding an rvalue reference to an lvalue & reference in + * essence keeps the &, per C+11 reference collapsing rules. For example, + * int& would remain int&.) + * + * The final computed type will only *not* be a reference if T is void. + * + * mozilla::AddRvalueReference<int>::Type is int&&; + * mozilla::AddRvalueRference<volatile int&>::Type is volatile int&; + * mozilla::AddRvalueRference<const int&&>::Type is const int&&; + * mozilla::AddRvalueReference<void*>::Type is void*&&; + * mozilla::AddRvalueReference<void>::Type is void; + * mozilla::AddRvalueReference<struct S&>::Type is struct S&. + */ +template<typename T> +struct AddRvalueReference + : detail::AddRvalueReferenceHelper<T> +{}; + +/* 20.2.4 Function template declval [declval] */ + +/** + * DeclVal simplifies the definition of expressions which occur as unevaluated + * operands. It converts T to a reference type, making it possible to use in + * decltype expressions even if T does not have a default constructor, e.g.: + * decltype(DeclVal<TWithNoDefaultConstructor>().foo()) + */ +template<typename T> +typename AddRvalueReference<T>::Type DeclVal(); + +/* 20.9.7.3 Sign modifications [meta.trans.sign] */ + +template<bool B, typename T = void> +struct EnableIf; + +namespace detail { + +template<bool MakeConst, typename T> +struct WithC : Conditional<MakeConst, const T, T> +{}; + +template<bool MakeVolatile, typename T> +struct WithV : Conditional<MakeVolatile, volatile T, T> +{}; + + +template<bool MakeConst, bool MakeVolatile, typename T> +struct WithCV : WithC<MakeConst, typename WithV<MakeVolatile, T>::Type> +{}; + +template<typename T> +struct CorrespondingSigned; + +template<> +struct CorrespondingSigned<char> { typedef signed char Type; }; +template<> +struct CorrespondingSigned<unsigned char> { typedef signed char Type; }; +template<> +struct CorrespondingSigned<unsigned short> { typedef short Type; }; +template<> +struct CorrespondingSigned<unsigned int> { typedef int Type; }; +template<> +struct CorrespondingSigned<unsigned long> { typedef long Type; }; +template<> +struct CorrespondingSigned<unsigned long long> { typedef long long Type; }; + +template<typename T, + typename CVRemoved = typename RemoveCV<T>::Type, + bool IsSignedIntegerType = IsSigned<CVRemoved>::value && + !IsSame<char, CVRemoved>::value> +struct MakeSigned; + +template<typename T, typename CVRemoved> +struct MakeSigned<T, CVRemoved, true> +{ + typedef T Type; +}; + +template<typename T, typename CVRemoved> +struct MakeSigned<T, CVRemoved, false> + : WithCV<IsConst<T>::value, IsVolatile<T>::value, + typename CorrespondingSigned<CVRemoved>::Type> +{}; + +} // namespace detail + +/** + * MakeSigned produces the corresponding signed integer type for a given + * integral type T, with the const/volatile qualifiers of T. T must be a + * possibly-const/volatile-qualified integral type that isn't bool. + * + * If T is already a signed integer type (not including char!), then T is + * produced. + * + * Otherwise, if T is an unsigned integer type, the signed variety of T, with + * T's const/volatile qualifiers, is produced. + * + * Otherwise, the integral type of the same size as T, with the lowest rank, + * with T's const/volatile qualifiers, is produced. (This basically only acts + * to produce signed char when T = char.) + * + * mozilla::MakeSigned<unsigned long>::Type is signed long; + * mozilla::MakeSigned<volatile int>::Type is volatile int; + * mozilla::MakeSigned<const unsigned short>::Type is const signed short; + * mozilla::MakeSigned<const char>::Type is const signed char; + * mozilla::MakeSigned<bool> is an error; + * mozilla::MakeSigned<void*> is an error. + */ +template<typename T> +struct MakeSigned + : EnableIf<IsIntegral<T>::value && + !IsSame<bool, typename RemoveCV<T>::Type>::value, + typename detail::MakeSigned<T> + >::Type +{}; + +namespace detail { + +template<typename T> +struct CorrespondingUnsigned; + +template<> +struct CorrespondingUnsigned<char> { typedef unsigned char Type; }; +template<> +struct CorrespondingUnsigned<signed char> { typedef unsigned char Type; }; +template<> +struct CorrespondingUnsigned<short> { typedef unsigned short Type; }; +template<> +struct CorrespondingUnsigned<int> { typedef unsigned int Type; }; +template<> +struct CorrespondingUnsigned<long> { typedef unsigned long Type; }; +template<> +struct CorrespondingUnsigned<long long> { typedef unsigned long long Type; }; + + +template<typename T, + typename CVRemoved = typename RemoveCV<T>::Type, + bool IsUnsignedIntegerType = IsUnsigned<CVRemoved>::value && + !IsSame<char, CVRemoved>::value> +struct MakeUnsigned; + +template<typename T, typename CVRemoved> +struct MakeUnsigned<T, CVRemoved, true> +{ + typedef T Type; +}; + +template<typename T, typename CVRemoved> +struct MakeUnsigned<T, CVRemoved, false> + : WithCV<IsConst<T>::value, IsVolatile<T>::value, + typename CorrespondingUnsigned<CVRemoved>::Type> +{}; + +} // namespace detail + +/** + * MakeUnsigned produces the corresponding unsigned integer type for a given + * integral type T, with the const/volatile qualifiers of T. T must be a + * possibly-const/volatile-qualified integral type that isn't bool. + * + * If T is already an unsigned integer type (not including char!), then T is + * produced. + * + * Otherwise, if T is a signed integer type, the unsigned variety of T, with + * T's const/volatile qualifiers, is produced. + * + * Otherwise, the unsigned integral type of the same size as T, with the lowest + * rank, with T's const/volatile qualifiers, is produced. (This basically only + * acts to produce unsigned char when T = char.) + * + * mozilla::MakeUnsigned<signed long>::Type is unsigned long; + * mozilla::MakeUnsigned<volatile unsigned int>::Type is volatile unsigned int; + * mozilla::MakeUnsigned<const signed short>::Type is const unsigned short; + * mozilla::MakeUnsigned<const char>::Type is const unsigned char; + * mozilla::MakeUnsigned<bool> is an error; + * mozilla::MakeUnsigned<void*> is an error. + */ +template<typename T> +struct MakeUnsigned + : EnableIf<IsIntegral<T>::value && + !IsSame<bool, typename RemoveCV<T>::Type>::value, + typename detail::MakeUnsigned<T> + >::Type +{}; + +/* 20.9.7.4 Array modifications [meta.trans.arr] */ + +/** + * RemoveExtent produces either the type of the elements of the array T, or T + * itself. + * + * mozilla::RemoveExtent<int>::Type is int; + * mozilla::RemoveExtent<const int[]>::Type is const int; + * mozilla::RemoveExtent<volatile int[5]>::Type is volatile int; + * mozilla::RemoveExtent<long[][17]>::Type is long[17]. + */ +template<typename T> +struct RemoveExtent +{ + typedef T Type; +}; + +template<typename T> +struct RemoveExtent<T[]> +{ + typedef T Type; +}; + +template<typename T, decltype(sizeof(1)) N> +struct RemoveExtent<T[N]> +{ + typedef T Type; +}; + +/* 20.9.7.5 Pointer modifications [meta.trans.ptr] */ + +namespace detail { + +template<typename T, typename CVRemoved> +struct RemovePointerHelper +{ + typedef T Type; +}; + +template<typename T, typename Pointee> +struct RemovePointerHelper<T, Pointee*> +{ + typedef Pointee Type; +}; + +} // namespace detail + +/** + * Produces the pointed-to type if a pointer is provided, else returns the input + * type. Note that this does not dereference pointer-to-member pointers. + * + * struct S { bool m; void f(); }; + * mozilla::RemovePointer<int>::Type is int; + * mozilla::RemovePointer<int*>::Type is int; + * mozilla::RemovePointer<int* const>::Type is int; + * mozilla::RemovePointer<int* volatile>::Type is int; + * mozilla::RemovePointer<const long*>::Type is const long; + * mozilla::RemovePointer<void* const>::Type is void; + * mozilla::RemovePointer<void (S::*)()>::Type is void (S::*)(); + * mozilla::RemovePointer<void (*)()>::Type is void(); + * mozilla::RemovePointer<bool S::*>::Type is bool S::*. + */ +template<typename T> +struct RemovePointer + : detail::RemovePointerHelper<T, typename RemoveCV<T>::Type> +{}; + +/* 20.9.7.6 Other transformations [meta.trans.other] */ + +/** + * EnableIf is a struct containing a typedef of T if and only if B is true. + * + * mozilla::EnableIf<true, int>::Type is int; + * mozilla::EnableIf<false, int>::Type is a compile-time error. + * + * Use this template to implement SFINAE-style (Substitution Failure Is not An + * Error) requirements. For example, you might use it to impose a restriction + * on a template parameter: + * + * template<typename T> + * class PodVector // vector optimized to store POD (memcpy-able) types + * { + * EnableIf<IsPod<T>::value, T>::Type* vector; + * size_t length; + * ... + * }; + */ +template<bool B, typename T> +struct EnableIf +{}; + +template<typename T> +struct EnableIf<true, T> +{ + typedef T Type; +}; + +/** + * Conditional selects a class between two, depending on a given boolean value. + * + * mozilla::Conditional<true, A, B>::Type is A; + * mozilla::Conditional<false, A, B>::Type is B; + */ +template<bool Condition, typename A, typename B> +struct Conditional +{ + typedef A Type; +}; + +template<class A, class B> +struct Conditional<false, A, B> +{ + typedef B Type; +}; + +} /* namespace mozilla */ + +#endif /* mozilla_TypeTraits_h */ diff --git a/include/onlineupdate/mozilla/Types.h b/include/onlineupdate/mozilla/Types.h new file mode 100644 index 000000000..9d1e34b6d --- /dev/null +++ b/include/onlineupdate/mozilla/Types.h @@ -0,0 +1,134 @@ +/* -*- 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/. */ + +/* mfbt foundational types and macros. */ + +#ifndef mozilla_Types_h +#define mozilla_Types_h + +/* + * This header must be valid C and C++, includable by code embedding either + * SpiderMonkey or Gecko. + */ + +/* Expose all <stdint.h> types and size_t. */ +#include <stddef.h> +#include <stdint.h> + +/* Implement compiler and linker macros needed for APIs. */ + +/* + * MOZ_EXPORT is used to declare and define a symbol or type which is externally + * visible to users of the current library. It encapsulates various decorations + * needed to properly export the method's symbol. + * + * api.h: + * extern MOZ_EXPORT int MeaningOfLife(void); + * extern MOZ_EXPORT int LuggageCombination; + * + * api.c: + * int MeaningOfLife(void) { return 42; } + * int LuggageCombination = 12345; + * + * If you are merely sharing a method across files, just use plain |extern|. + * These macros are designed for use by library interfaces -- not for normal + * methods or data used cross-file. + */ +#if defined(_WIN32) +# define MOZ_EXPORT __declspec(dllexport) +#else /* Unix */ +# ifdef HAVE_VISIBILITY_ATTRIBUTE +# define MOZ_EXPORT __attribute__((visibility("default"))) +# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# define MOZ_EXPORT __global +# else +# define MOZ_EXPORT /* nothing */ +# endif +#endif + + +/* + * Whereas implementers use MOZ_EXPORT to declare and define library symbols, + * users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to access them. Most often the + * implementer of the library will expose an API macro which expands to either + * the export or import version of the macro, depending upon the compilation + * mode. + */ +#ifdef _WIN32 +# if defined(__MWERKS__) +# define MOZ_IMPORT_API /* nothing */ +# else +# define MOZ_IMPORT_API __declspec(dllimport) +# endif +#else +# define MOZ_IMPORT_API MOZ_EXPORT +#endif + +#if defined(_WIN32) && !defined(__MWERKS__) +# define MOZ_IMPORT_DATA __declspec(dllimport) +#else +# define MOZ_IMPORT_DATA MOZ_EXPORT +#endif + +/* + * Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose + * export mfbt declarations when building mfbt, and they expose import mfbt + * declarations when using mfbt. + */ +#if defined(IMPL_MFBT) +# define MFBT_API MOZ_EXPORT +# define MFBT_DATA MOZ_EXPORT +#else + /* + * On linux mozglue is linked in the program and we link libxul.so with + * -z,defs. Normally that causes the linker to reject undefined references in + * libxul.so, but as a loophole it allows undefined references to weak + * symbols. We add the weak attribute to the import version of the MFBT API + * macros to exploit this. + */ +# if defined(MOZ_GLUE_IN_PROGRAM) && !defined(MOZILLA_XPCOMRT_API) +# define MFBT_API __attribute__((weak)) MOZ_IMPORT_API +# define MFBT_DATA __attribute__((weak)) MOZ_IMPORT_DATA +# else +# define MFBT_API MOZ_IMPORT_API +# define MFBT_DATA MOZ_IMPORT_DATA +# endif +#endif + +/* + * C symbols in C++ code must be declared immediately within |extern "C"| + * blocks. However, in C code, they need not be declared specially. This + * difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C + * macros, so that the user need not know whether he is being used in C or C++ + * code. + * + * MOZ_BEGIN_EXTERN_C + * + * extern MOZ_EXPORT int MostRandomNumber(void); + * ...other declarations... + * + * MOZ_END_EXTERN_C + * + * This said, it is preferable to just use |extern "C"| in C++ header files for + * its greater clarity. + */ +#ifdef __cplusplus +# define MOZ_BEGIN_EXTERN_C extern "C" { +# define MOZ_END_EXTERN_C } +#else +# define MOZ_BEGIN_EXTERN_C +# define MOZ_END_EXTERN_C +#endif + +/* + * GCC's typeof is available when decltype is not. + */ +#if defined(__GNUC__) && defined(__cplusplus) && \ + !defined(__GXX_EXPERIMENTAL_CXX0X__) && __cplusplus < 201103L +# define decltype __typeof__ +#endif + +#endif /* mozilla_Types_h */ diff --git a/include/onlineupdate/mozilla/nsTraceRefcnt.h b/include/onlineupdate/mozilla/nsTraceRefcnt.h new file mode 100644 index 000000000..c5b1de7e8 --- /dev/null +++ b/include/onlineupdate/mozilla/nsTraceRefcnt.h @@ -0,0 +1,67 @@ +/* -*- 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/. */ +#ifndef nsTraceRefcnt_h___ +#define nsTraceRefcnt_h___ + +#include <stdio.h> // for FILE +#include "nscore.h" + +class nsTraceRefcnt +{ +public: + static void Shutdown(); + + enum StatisticsType { + ALL_STATS, + NEW_STATS + }; + + static nsresult DumpStatistics(StatisticsType aType = ALL_STATS, + FILE* aOut = 0); + + static void ResetStatistics(); + + static void DemangleSymbol(const char* aSymbol, char* aBuffer, int aBufLen); + + static void WalkTheStack(FILE* aStream); + + /** + * This is a variant of |WalkTheStack| that uses |CodeAddressService| to cache + * the results of |NS_DescribeCodeAddress|. If |WalkTheStackCached| is being + * called frequently, it will be a few orders of magnitude faster than + * |WalkTheStack|. However, the cache uses a lot of memory, which can cause + * OOM crashes. Therefore, this should only be used for things like refcount + * logging which walk the stack extremely frequently. + */ + static void WalkTheStackCached(FILE* aStream); + + /** + * Tell nsTraceRefcnt whether refcounting, allocation, and destruction + * activity is legal. This is used to trigger assertions for any such + * activity that occurs because of static constructors or destructors. + */ + static void SetActivityIsLegal(bool aLegal); +}; + +#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1" +#define NS_TRACE_REFCNT_CID \ +{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \ + 0xe3e7511e, \ + 0xa395, \ + 0x4924, \ + {0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \ +} \ + +//////////////////////////////////////////////////////////////////////////////// +// And now for that utility that you've all been asking for... + +extern "C" void +NS_MeanAndStdDev(double aNumberOfValues, + double aSumOfValues, double aSumOfSquaredValues, + double* aMeanResult, double* aStdDevResult); + +//////////////////////////////////////////////////////////////////////////////// +#endif |