blob: 44c2fa9f1538adb5406d0bd0731e4471f3096ede [file] [log] [blame]
// Copyright 2019 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
//
// Preprocessor macros that wrap compiler-specific features.
// This file is used by both C++ and C code.
#pragma once
#include <assert.h>
// TODO(b/234877280): compiler.h should be refactored out of pw_preprocessor as
// the scope is outside of the module. Perhaps it should be split up and placed
// under pw_compiler, e.g. pw_compiler/attributes.h & pw_compiler/builtins.h.
// Marks a struct or class as packed.
#define PW_PACKED(declaration) declaration __attribute__((packed))
// Marks a function or object as used, ensuring code for it is generated.
#define PW_USED __attribute__((used))
// Prevents generation of a prologue or epilogue for a function. This is
// helpful when implementing the function in assembly.
#define PW_NO_PROLOGUE __attribute__((naked))
// Marks that a function declaration takes a printf-style format string and
// variadic arguments. This allows the compiler to perform check the validity of
// the format string and arguments. This macro must only be on the function
// declaration, not the definition.
//
// The format_index is index of the format string parameter and parameter_index
// is the starting index of the variadic arguments. Indices start at 1. For C++
// class member functions, add one to the index to account for the implicit this
// parameter.
//
// This example shows a function where the format string is argument 2 and the
// varargs start at argument 3.
//
// int PrintfStyleFunction(char* buffer,
// const char* fmt, ...) PW_PRINTF_FORMAT(2,3);
//
// int PrintfStyleFunction(char* buffer, const char* fmt, ...) {
// ... implementation here ...
// }
//
// When compiling for host using MinGW, use gnu_printf() rather than printf()
// to support %z format specifiers.
#ifdef __USE_MINGW_ANSI_STDIO
#define _PW_PRINTF_FORMAT_TYPE gnu_printf
#else
#define _PW_PRINTF_FORMAT_TYPE printf
#endif // __USE_MINGW_ANSI_STDIO
#define PW_PRINTF_FORMAT(format_index, parameter_index) \
__attribute__((format(_PW_PRINTF_FORMAT_TYPE, format_index, parameter_index)))
// Places a variable in the specified linker section.
#ifdef __APPLE__
#define PW_PLACE_IN_SECTION(name) __attribute__((section("__DATA," name)))
#else
#define PW_PLACE_IN_SECTION(name) __attribute__((section(name)))
#endif // __APPLE__
// Places a variable in the specified linker section and directs the compiler
// to keep the variable, even if it is not used. Depending on the linker
// options, the linker may still remove this section if it is not declared in
// the linker script and marked KEEP.
#ifdef __APPLE__
#define PW_KEEP_IN_SECTION(name) __attribute__((section("__DATA," name), used))
#else
#define PW_KEEP_IN_SECTION(name) __attribute__((section(name), used))
#endif // __APPLE__
// Indicate to the compiler that the annotated function won't return. Example:
//
// PW_NO_RETURN void HandleAssertFailure(ErrorCode error_code);
//
#define PW_NO_RETURN __attribute__((noreturn))
// Prevents the compiler from inlining a fuction.
#define PW_NO_INLINE __attribute__((noinline))
// Indicate to the compiler that the given section of code will not be reached.
// Example:
//
// int main() {
// InitializeBoard();
// vendor_StartScheduler(); // Note: vendor forgot noreturn attribute.
// PW_UNREACHABLE;
// }
//
#define PW_UNREACHABLE __builtin_unreachable()
// Indicate to a sanitizer compiler runtime to skip the named check in the
// associated function.
// Example:
//
// uint32_t djb2(const void* buf, size_t len)
// PW_NO_SANITIZE("unsigned-integer-overflow"){
// uint32_t hash = 5381;
// const uint8_t* u8 = static_cast<const uint8_t*>(buf);
// for (size_t i = 0; i < len; ++i) {
// hash = (hash * 33) + u8[i]; /* hash * 33 + c */
// }
// return hash;
// }
#ifdef __clang__
#define PW_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
#else
#define PW_NO_SANITIZE(check)
#endif // __clang__
// Wrapper around `__has_attribute`, which is defined by GCC 5+ and Clang and
// evaluates to a non zero constant integer if the attribute is supported or 0
// if not.
#ifdef __has_attribute
#define PW_HAVE_ATTRIBUTE(x) __has_attribute(x)
#else
#define PW_HAVE_ATTRIBUTE(x) 0
#endif // __has_attribute
// A function-like feature checking macro that accepts C++11 style attributes.
// It's a wrapper around __has_cpp_attribute
// (https://en.cppreference.com/w/cpp/feature_test), borrowed from
// ABSL_HAVE_CPP_ATTRIBUTE. If there is no __has_cpp_attribute, evaluates to 0.
#if defined(__cplusplus) && defined(__has_cpp_attribute)
#define PW_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
#else
#define PW_HAVE_CPP_ATTRIBUTE(x) 0
#endif // defined(__cplusplus) && defined(__has_cpp_attribute)
#define _PW_REQUIRE_SEMICOLON \
static_assert(1, "This macro must be terminated with a semicolon")
// PW_MODIFY_DIAGNOSTICS_PUSH and PW_MODIFY_DIAGNOSTICS_POP are used to turn off
// or on diagnostics (warnings or errors) for a section of code. Use
// PW_MODIFY_DIAGNOSTICS_PUSH, use PW_MODIFY_DIAGNOSTIC as many times as needed,
// then use PW_MODIFY_DIAGNOSTICS_POP to restore the previous settings.
#define PW_MODIFY_DIAGNOSTICS_PUSH() \
_Pragma("GCC diagnostic push") _PW_REQUIRE_SEMICOLON
#define PW_MODIFY_DIAGNOSTICS_POP() \
_Pragma("GCC diagnostic pop") _PW_REQUIRE_SEMICOLON
// Changes how a diagnostic (warning or error) is handled. Most commonly used to
// disable warnings. PW_MODIFY_DIAGNOSTIC should be used between
// PW_MODIFY_DIAGNOSTICS_PUSH and PW_MODIFY_DIAGNOSTICS_POP statements to avoid
// applying the modifications too broadly.
//
// 'kind' must be one of warning, error, or ignored.
#define PW_MODIFY_DIAGNOSTIC(kind, option) \
PW_PRAGMA(GCC diagnostic kind option) _PW_REQUIRE_SEMICOLON
// Applies PW_MODIFY_DIAGNOSTIC only for GCC. This is useful for warnings that
// aren't supported by or don't need to be changed in other compilers.
#ifdef __clang__
#define PW_MODIFY_DIAGNOSTIC_GCC(kind, option) _PW_REQUIRE_SEMICOLON
#else
#define PW_MODIFY_DIAGNOSTIC_GCC(kind, option) \
PW_MODIFY_DIAGNOSTIC(kind, option)
#endif // __clang__
// Expands to a _Pragma with the contents as a string. _Pragma must take a
// single string literal; this can be used to construct a _Pragma argument.
#define PW_PRAGMA(contents) _Pragma(#contents)
// Marks a function or object as weak, allowing the definition to be overriden.
//
// This can be useful when supporting third-party SDKs which may conditionally
// compile in code, for example:
//
// PW_WEAK void SysTick_Handler(void) {
// // Default interrupt handler that might be overriden.
// }
#define PW_WEAK __attribute__((weak))
// Marks a weak function as an alias to another, allowing the definition to
// be given a default and overriden.
//
// This can be useful when supporting third-party SDKs which may conditionally
// compile in code, for example:
//
// // Driver handler replaced with default unless overridden.
// void USART_DriverHandler(void) PW_ALIAS(DefaultDriverHandler);
#define PW_ALIAS(aliased_to) __attribute__((weak, alias(#aliased_to)))
// PW_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function
// parameter or implicit object parameter is retained by the return value of the
// annotated function (or, for a parameter of a constructor, in the value of the
// constructed object). This attribute causes warnings to be produced if a
// temporary object does not live long enough.
//
// When applied to a reference parameter, the referenced object is assumed to be
// retained by the return value of the function. When applied to a non-reference
// parameter (for example, a pointer or a class type), all temporaries
// referenced by the parameter are assumed to be retained by the return value of
// the function.
//
// See also the upstream documentation:
// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound
//
// This is a copy of ABSL_ATTRIBUTE_LIFETIME_BOUND.
#if PW_HAVE_CPP_ATTRIBUTE(clang::lifetimebound)
#define PW_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]]
#elif PW_HAVE_ATTRIBUTE(lifetimebound)
#define PW_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound))
#else
#define PW_ATTRIBUTE_LIFETIME_BOUND
#endif // PW_ATTRIBUTE_LIFETIME_BOUND