| // Protocol Buffers - Google's data interchange format |
| // Copyright 2023 Google LLC. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd |
| |
| /* |
| * This is where we define internal portability macros used across upb. |
| * |
| * All of these macros are undef'd in undef.inc to avoid leaking them to users. |
| * |
| * The correct usage is: |
| * |
| * #include "upb/foobar.h" |
| * #include "upb/baz.h" |
| * |
| * // MUST be last included header. |
| * #include "upb/port/def.inc" |
| * |
| * // Code for this file. |
| * // <...> |
| * |
| * // Can be omitted for .c files, required for .h. |
| * #include "upb/port/undef.inc" |
| * |
| * This file is private and must not be included by users! |
| */ |
| |
| #if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ |
| (defined(__cplusplus) && __cplusplus >= 201703L) || \ |
| (defined(_MSC_VER) && _MSC_VER >= 1900)) |
| #error upb requires C99 or C++17 or MSVC >= 2015. |
| #endif |
| |
| // Portable check for GCC minimum version: |
| // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html |
| #if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) |
| #define UPB_GNUC_MIN(x, y) \ |
| (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y)) |
| #else |
| #define UPB_GNUC_MIN(x, y) 0 |
| #endif |
| |
| // Macros for checking for compiler attributes, defined here to avoid the |
| // problem described in |
| // https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fattribute.html. |
| #ifdef __has_attribute |
| #define UPB_HAS_ATTRIBUTE(x) __has_attribute(x) |
| #else |
| #define UPB_HAS_ATTRIBUTE(x) 0 |
| #endif |
| |
| #ifdef __has_builtin |
| #define UPB_HAS_BUILTIN(x) __has_builtin(x) |
| #else |
| #define UPB_HAS_BUILTIN(x) 0 |
| #endif |
| |
| #ifdef __has_extension |
| #define UPB_HAS_EXTENSION(x) __has_extension(x) |
| #else |
| #define UPB_HAS_EXTENSION(x) 0 |
| #endif |
| |
| #ifdef __has_feature |
| #define UPB_HAS_FEATURE(x) __has_feature(x) |
| #else |
| #define UPB_HAS_FEATURE(x) 0 |
| #endif |
| |
| #include <assert.h> |
| #include <setjmp.h> |
| #include <stdbool.h> |
| #include <stdint.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| |
| #ifndef UINTPTR_MAX |
| Error, UINTPTR_MAX is undefined |
| #endif |
| |
| #if UINTPTR_MAX == 0xffffffff |
| #define UPB_SIZE(size32, size64) size32 |
| #else |
| #define UPB_SIZE(size32, size64) size64 |
| #endif |
| |
| /* If we always read/write as a consistent type to each address, this shouldn't |
| * violate aliasing. |
| */ |
| #define UPB_PTR_AT(msg, ofs, type) ((type *)((char *)(msg) + (ofs))) |
| |
| // A flexible array member may have lower alignment requirements than the struct |
| // overall - in that case, it can overlap with the trailing padding of the rest |
| // of the struct, and a naive sizeof(base) + sizeof(flex) * count calculation |
| // will not take into account that overlap, and allocate more than is required. |
| #define UPB_SIZEOF_FLEX(type, member, count) \ |
| UPB_MAX(sizeof(type), offsetof(type, member[count])) |
| |
| #define UPB_SIZEOF_FLEX_WOULD_OVERFLOW(type, member, count) \ |
| (((SIZE_MAX - offsetof(type, member[0])) / \ |
| (offsetof(type, member[1]) - offsetof(type, member[0]))) < (size_t)count) |
| |
| #define UPB_ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) |
| |
| #define UPB_MAPTYPE_STRING 0 |
| |
| // UPB_EXPORT: always generate a public symbol. |
| #if defined(__GNUC__) || defined(__clang__) |
| #define UPB_EXPORT __attribute__((visibility("default"))) __attribute__((used)) |
| #else |
| #define UPB_EXPORT |
| #endif |
| |
| // UPB_INLINE: inline if possible, emit standalone code if required. |
| #ifdef __cplusplus |
| #define UPB_INLINE inline |
| #elif defined(__GNUC__) || defined(__clang__) |
| #define UPB_INLINE static __inline__ |
| #else |
| #define UPB_INLINE static |
| #endif |
| |
| // UPB_INLINE_IF_NOT_GCC: because gcc can be very noisy at times. |
| #if defined(__GNUC__) && !defined(__clang__) |
| #define UPB_INLINE_IF_NOT_GCC static |
| #else |
| #define UPB_INLINE_IF_NOT_GCC UPB_INLINE |
| #endif |
| |
| #ifdef UPB_BUILD_API |
| #define UPB_API UPB_EXPORT |
| #define UPB_API_INLINE UPB_EXPORT |
| #else |
| #define UPB_API |
| #define UPB_API_INLINE UPB_INLINE |
| #endif |
| |
| #ifdef EXPORT_UPBC |
| #define UPBC_API UPB_EXPORT |
| #else |
| #define UPBC_API |
| #endif |
| |
| #if UPB_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__) |
| #define UPB_ASAN 1 |
| #else |
| #define UPB_ASAN 0 |
| #endif |
| |
| #if UPB_HAS_FEATURE(hwaddress_sanitizer) |
| #define UPB_HWASAN 1 |
| #define UPB_HWASAN_POISON_TAG 17 |
| #define UPB_MALLOC_ALIGN 16 |
| #else |
| #define UPB_HWASAN 0 |
| #define UPB_MALLOC_ALIGN 8 |
| #endif |
| |
| #if UPB_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__) |
| #define UPB_TSAN 1 |
| #else |
| #define UPB_TSAN 0 |
| #endif |
| |
| // An unfortunate concession to C++17 and MSVC, which don't support zero-sized |
| // structs. |
| #if UPB_ASAN || UPB_HWASAN || UPB_TSAN |
| #define UPB_XSAN_MEMBER upb_Xsan xsan; |
| #define UPB_XSAN(st) (&(st)->xsan) |
| #define UPB_XSAN_STRUCT_SIZE 1 |
| #else |
| #define UPB_XSAN_MEMBER |
| #define UPB_XSAN(st) (NULL) |
| #define UPB_XSAN_STRUCT_SIZE 0 |
| #endif |
| |
| #define UPB_ALIGN_UP(size, align) (((size) + (align) - 1) / (align) * (align)) |
| #define UPB_ALIGN_DOWN(size, align) ((size) / (align) * (align)) |
| #define UPB_ALIGN_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN) |
| |
| #if __STDC_VERSION__ >= 202311L || UPB_HAS_EXTENSION(cxx_alignof) || \ |
| defined(__cplusplus) |
| #define UPB_ALIGN_OF(type) alignof(type) |
| #elif __STDC_VERSION__ >= 201112L || UPB_HAS_EXTENSION(c_alignof) |
| #define UPB_ALIGN_OF(type) _Alignof(type) |
| #elif UPB_GNUC_MIN(2, 95) |
| #define UPB_ALIGN_OF(type) __alignof__(type) |
| #elif defined(_MSC_VER) |
| #define UPB_ALIGN_OF(type) __alignof(type) |
| #else |
| #define UPB_ALIGN_OF(type) \ |
| offsetof( \ |
| struct { \ |
| char c; \ |
| type member; \ |
| }, \ |
| member) |
| #endif |
| |
| #ifdef _MSC_VER |
| // Some versions of our Windows compiler don't support the C11 syntax. |
| #define UPB_ALIGN_AS(x) __declspec(align(x)) |
| #elif defined(__GNUC__) |
| #define UPB_ALIGN_AS(x) __attribute__((aligned(x))) |
| #else |
| #define UPB_ALIGN_AS(x) _Alignas(x) |
| #endif |
| |
| #if __STDC_VERSION__ >= 202311L || UPB_HAS_EXTENSION(cxx_static_assert) || \ |
| defined(__cplusplus) |
| #define UPB_STATIC_ASSERT(val, msg) static_assert((val), msg) |
| #elif __STDC_VERSION__ >= 201112L || UPB_HAS_EXTENSION(c_static_assert) || \ |
| UPB_GNUC_MIN(4, 6) |
| #define UPB_STATIC_ASSERT(val, msg) _Static_assert((val), msg) |
| #else |
| // Unfortunately this hack doesn't work inside struct declarations, but it works |
| // everywhere else |
| #define UPB_STATIC_ASSERT_CONCAT_IMPL(s1, s2) s1##s2 |
| #define UPB_STATIC_ASSERT_CONCAT(s1, s2) UPB_STATIC_ASSERT_CONCAT_IMPL(s1, s2) |
| #ifdef __COUNTER__ |
| #define UPB_STATIC_ASSERT(condition, message) \ |
| typedef char UPB_STATIC_ASSERT_CONCAT(static_assertion_failure_, \ |
| __COUNTER__)[(condition) ? 1 : -1] |
| #else |
| #define UPB_STATIC_ASSERT(condition, message) \ |
| typedef char UPB_STATIC_ASSERT_CONCAT(static_assertion_failure_, \ |
| __LINE__)[(condition) ? 1 : -1] |
| #endif |
| #endif |
| |
| // Hints to the compiler about likely/unlikely branches. |
| #if defined(__GNUC__) || defined(__clang__) |
| #define UPB_LIKELY(x) __builtin_expect((bool)(x), 1) |
| #define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0) |
| #else |
| #define UPB_LIKELY(x) (x) |
| #define UPB_UNLIKELY(x) (x) |
| #endif |
| |
| #if UPB_HAS_BUILTIN(__builtin_expect_with_probability) |
| #define UPB_UNPREDICTABLE(x) \ |
| __builtin_expect_with_probability((bool)(x), 1, 0.5) |
| #else |
| #define UPB_UNPREDICTABLE(x) (x) |
| #endif |
| |
| // Macros for function attributes on compilers that support them. |
| #if defined(__GNUC__) || defined(__clang__) |
| #define UPB_FORCEINLINE __inline__ __attribute__((always_inline)) static |
| #define UPB_NOINLINE __attribute__((noinline)) |
| #define UPB_NORETURN __attribute__((__noreturn__)) |
| #define UPB_PRINTF(str, first_vararg) \ |
| __attribute__((format(printf, str, first_vararg))) |
| #elif defined(_MSC_VER) |
| #define UPB_NOINLINE |
| #define UPB_FORCEINLINE static |
| #define UPB_NORETURN __declspec(noreturn) |
| #define UPB_PRINTF(str, first_vararg) |
| #else /* !defined(__GNUC__) */ |
| #define UPB_FORCEINLINE static |
| #define UPB_NOINLINE |
| #define UPB_NORETURN |
| #define UPB_PRINTF(str, first_vararg) |
| #endif |
| |
| #if defined(__clang__) |
| #define UPB_NODEREF __attribute__((noderef)) |
| #else |
| #define UPB_NODEREF |
| #endif |
| |
| #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) |
| #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) |
| |
| #define UPB_UNUSED(var) (void)(var) |
| |
| // UPB_ASSUME(): in release mode, we tell the compiler to assume this is true. |
| #ifdef NDEBUG |
| #ifdef __GNUC__ |
| #define UPB_ASSUME(expr) \ |
| if (!(expr)) __builtin_unreachable() |
| #elif defined _MSC_VER |
| #define UPB_ASSUME(expr) \ |
| if (!(expr)) __assume(0) |
| #else |
| #define UPB_ASSUME(expr) \ |
| do { \ |
| } while (false && (expr)) |
| #endif |
| #else |
| #define UPB_ASSUME(expr) assert(expr) |
| #endif |
| |
| /* UPB_ASSERT(): in release mode, we use the expression without letting it be |
| * evaluated. This prevents "unused variable" warnings. */ |
| #ifdef NDEBUG |
| #define UPB_ASSERT(expr) \ |
| do { \ |
| } while (false && (expr)) |
| #else |
| #define UPB_ASSERT(expr) assert(expr) |
| #endif |
| |
| #if !defined(NDEBUG) && !defined(UPB_TSAN) |
| #define UPB_ENABLE_REF_CYCLE_CHECKS 1 |
| #else |
| #define UPB_ENABLE_REF_CYCLE_CHECKS 0 |
| #endif |
| |
| #if defined(__GNUC__) || defined(__clang__) |
| #define UPB_UNREACHABLE() \ |
| do { \ |
| assert(0); \ |
| __builtin_unreachable(); \ |
| } while (0) |
| #elif defined(_MSC_VER) |
| #define UPB_UNREACHABLE() \ |
| do { \ |
| assert(0); \ |
| __assume(0); \ |
| } while (0) |
| #else |
| #define UPB_UNREACHABLE() \ |
| do { \ |
| assert(0); \ |
| } while (0) |
| #endif |
| |
| #ifdef __ANDROID__ |
| #define UPB_DEFAULT_MAX_BLOCK_SIZE 8192 |
| #else |
| #define UPB_DEFAULT_MAX_BLOCK_SIZE 32768 |
| #endif |
| |
| /* UPB_SETJMP() / UPB_LONGJMP() */ |
| // Android uses a custom libc that does not implement all of posix, but it has |
| // had sigsetjmp/siglongjmp forever on arm and since API 12 on x86. Apple has |
| // sigsetjmp, but does not define the posix feature test macro. |
| #if defined(__APPLE__) || defined(_POSIX_C_SOURCE) || defined(__ANDROID__) |
| // avoid setting/restoring signal mask, which involves costly syscalls |
| #define UPB_SETJMP(buf) sigsetjmp(buf, 0) |
| #define UPB_LONGJMP(buf, val) siglongjmp(buf, val) |
| #elif defined(WASM_WAMR) |
| #define UPB_SETJMP(buf) 0 |
| #define UPB_LONGJMP(buf, val) abort() |
| #else |
| #define UPB_SETJMP(buf) setjmp(buf) |
| #define UPB_LONGJMP(buf, val) longjmp(buf, val) |
| #endif |
| |
| #if ((__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__)) || \ |
| UPB_HAS_EXTENSION(c_atomic) || \ |
| defined(__GNUC__) // GCC supported atomics as an extension before it |
| // supported __has_extension |
| #define UPB_USE_C11_ATOMICS |
| #elif defined(_MSC_VER) |
| #define UPB_USE_MSC_ATOMICS |
| #endif |
| |
| #if defined(UPB_USE_C11_ATOMICS) |
| #define UPB_ATOMIC(T) _Atomic(T) |
| #elif defined(UPB_USE_MSC_ATOMICS) |
| #define UPB_ATOMIC(T) volatile T |
| #else |
| #define UPB_ATOMIC(T) T |
| #endif |
| |
| /* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */ |
| #define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr)) |
| |
| #define UPB_PRIVATE(x) x##_dont_copy_me__upb_internal_use_only |
| |
| #ifdef UPB_ALLOW_PRIVATE_ACCESS__FOR_BITS_ONLY |
| #define UPB_ONLYBITS(x) x |
| #else |
| #define UPB_ONLYBITS(x) UPB_PRIVATE(x) |
| #endif |
| |
| /* Configure whether fasttable is switched on or not. *************************/ |
| |
| #if UPB_HAS_ATTRIBUTE(musttail) |
| #define UPB_MUSTTAIL __attribute__((musttail)) |
| #else |
| #define UPB_MUSTTAIL |
| #endif |
| |
| #if UPB_HAS_ATTRIBUTE(preserve_none) |
| #define UPB_PRESERVE_NONE __attribute__((preserve_none)) |
| #else |
| #define UPB_PRESERVE_NONE |
| #endif |
| |
| /* This check is not fully robust: it does not require that we have "musttail" |
| * support available. We need tail calls to avoid consuming arbitrary amounts |
| * of stack space. |
| * |
| * GCC/Clang can mostly be trusted to generate tail calls as long as |
| * optimization is enabled, but, debug builds will not generate tail calls |
| * unless "musttail" is available. |
| * |
| * We should probably either: |
| * 1. require that the compiler supports musttail. |
| * 2. add some fallback code for when musttail isn't available (ie. return |
| * instead of tail calling). This is safe and portable, but this comes at |
| * a CPU cost. |
| */ |
| #if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__) |
| #define UPB_FASTTABLE_SUPPORTED 1 |
| #else |
| #define UPB_FASTTABLE_SUPPORTED 0 |
| #endif |
| |
| /* define UPB_ENABLE_FASTTABLE to force fast table support. |
| * This is useful when we want to ensure we are really getting fasttable, |
| * for example for testing or benchmarking. */ |
| #if defined(UPB_ENABLE_FASTTABLE) |
| #if !UPB_FASTTABLE_SUPPORTED |
| #error fasttable is x86-64/ARM64 only and requires GCC or Clang. |
| #endif |
| #define UPB_FASTTABLE 1 |
| /* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible. |
| * This is useful for releasing code that might be used on multiple platforms, |
| * for example the PHP or Ruby C extensions. */ |
| #elif defined(UPB_TRY_ENABLE_FASTTABLE) |
| #define UPB_FASTTABLE UPB_FASTTABLE_SUPPORTED |
| #else |
| #define UPB_FASTTABLE 0 |
| #endif |
| |
| /* UPB_FASTTABLE_INIT() allows protos compiled for fasttable to gracefully |
| * degrade to non-fasttable if the runtime or platform do not support it. */ |
| #if !UPB_FASTTABLE |
| #define UPB_FASTTABLE_INIT(...) |
| #define UPB_FASTTABLE_MASK(mask) -1 |
| #else |
| #define UPB_FASTTABLE_INIT(...) __VA_ARGS__ |
| #define UPB_FASTTABLE_MASK(mask) mask |
| #endif |
| |
| #undef UPB_FASTTABLE_SUPPORTED |
| |
| /* Disable proto2 arena behavior (TEMPORARY) **********************************/ |
| |
| #ifdef UPB_DISABLE_CLOSED_ENUM_CHECKING |
| #define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 1 |
| #else |
| #define UPB_TREAT_CLOSED_ENUMS_LIKE_OPEN 0 |
| #endif |
| |
| #if defined(__cplusplus) |
| #if defined(__clang__) || UPB_GNUC_MIN(6, 0) |
| // https://gcc.gnu.org/gcc-6/changes.html |
| #define UPB_DEPRECATED [[deprecated]] |
| #else |
| #define UPB_DEPRECATED |
| #endif |
| #else |
| #define UPB_DEPRECATED |
| #endif |
| |
| #if defined(UPB_IS_GOOGLE3) && \ |
| (!defined(UPB_BOOTSTRAP_STAGE) || UPB_BOOTSTRAP_STAGE != 0) |
| #define UPB_DESC(sym) proto2_##sym |
| #define UPB_DESC_MINITABLE(sym) &proto2__##sym##_msg_init |
| #elif defined(UPB_IS_GOOGLE3) && defined(UPB_BOOTSTRAP_STAGE) && \ |
| UPB_BOOTSTRAP_STAGE == 0 |
| #define UPB_DESC(sym) proto2_##sym |
| #define UPB_DESC_MINITABLE(sym) proto2__##sym##_msg_init() |
| #elif defined(UPB_BOOTSTRAP_STAGE) && UPB_BOOTSTRAP_STAGE == 0 |
| #define UPB_DESC(sym) google_protobuf_##sym |
| #define UPB_DESC_MINITABLE(sym) google__protobuf__##sym##_msg_init() |
| #else |
| #define UPB_DESC(sym) google_protobuf_##sym |
| #define UPB_DESC_MINITABLE(sym) &google__protobuf__##sym##_msg_init |
| #endif |
| |
| #undef UPB_IS_GOOGLE3 |
| |
| #ifdef __clang__ |
| #define UPB_NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) |
| #else |
| #define UPB_NO_SANITIZE_ADDRESS |
| #endif |
| |
| // Linker arrays combine elements from multiple translation units into a single |
| // array that can be iterated over at runtime. |
| // |
| // It is an alternative to pre-main "registration" functions. |
| // |
| // Usage: |
| // |
| // // In N translation units. |
| // UPB_LINKARR_APPEND(foo_array) static int elems[3] = {1, 2, 3}; |
| // |
| // // At runtime: |
| // UPB_LINKARR_DECLARE(foo_array, int); |
| // |
| // void f() { |
| // const int* start = UPB_LINKARR_START(foo_array); |
| // const int* stop = UPB_LINKARR_STOP(foo_array); |
| // for (const int* p = start; p < stop; p++) { |
| // // Windows can introduce zero padding, so we have to skip zeroes. |
| // if (*p != 0) { |
| // vec.push_back(*p); |
| // } |
| // } |
| // } |
| |
| #if defined(__ELF__) || defined(__wasm__) |
| |
| #define UPB_LINKARR_APPEND(name) \ |
| __attribute__((section("linkarr_" #name))) UPB_NO_SANITIZE_ADDRESS |
| #define UPB_LINKARR_DECLARE(name, type) \ |
| extern type __start_linkarr_##name; \ |
| extern type __stop_linkarr_##name; \ |
| UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] |
| #define UPB_LINKARR_START(name) (&__start_linkarr_##name) |
| #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) |
| |
| #elif defined(__MACH__) |
| |
| /* As described in: https://stackoverflow.com/a/22366882 */ |
| #define UPB_LINKARR_APPEND(name) \ |
| __attribute__((section("__DATA,__la_" #name))) UPB_NO_SANITIZE_ADDRESS |
| #define UPB_LINKARR_DECLARE(name, type) \ |
| extern type __start_linkarr_##name __asm( \ |
| "section$start$__DATA$__la_" #name); \ |
| extern type __stop_linkarr_##name __asm( \ |
| "section$end$__DATA$" \ |
| "__la_" #name); \ |
| UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] |
| #define UPB_LINKARR_START(name) (&__start_linkarr_##name) |
| #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) |
| |
| #elif defined(_MSC_VER) && defined(__clang__) |
| |
| /* See: |
| * https://devblogs.microsoft.com/oldnewthing/20181107-00/?p=100155 |
| * https://devblogs.microsoft.com/oldnewthing/20181108-00/?p=100165 |
| * https://devblogs.microsoft.com/oldnewthing/20181109-00/?p=100175 */ |
| |
| // Usage of __attribute__ here probably means this is Clang-specific, and would |
| // not work on MSVC. |
| #define UPB_LINKARR_APPEND(name) \ |
| __declspec(allocate("la_" #name "$j")) UPB_NO_SANITIZE_ADDRESS |
| #define UPB_LINKARR_DECLARE(name, type) \ |
| __declspec(allocate("la_" #name "$a")) type __start_linkarr_##name; \ |
| __declspec(allocate("la_" #name "$z")) type __stop_linkarr_##name; \ |
| UPB_LINKARR_APPEND(name) type UPB_linkarr_internal_empty_##name[1] = {0} |
| #define UPB_LINKARR_START(name) (&__start_linkarr_##name) |
| #define UPB_LINKARR_STOP(name) (&__stop_linkarr_##name) |
| |
| #else |
| |
| // Linker arrays are not supported on this platform. Make appends a no-op but |
| // don't define the other macros. |
| #define UPB_LINKARR_APPEND(name) |
| |
| #endif |
| |
| // Future versions of upb will include breaking changes to some APIs. |
| // This macro can be set to enable these API changes ahead of time, so that |
| // user code can be updated before upgrading versions of protobuf. |
| #ifdef UPB_FUTURE_BREAKING_CHANGES |
| |
| #endif |