aboutsummaryrefslogtreecommitdiff
path: root/pw_preprocessor/public/pw_preprocessor/compiler.h
blob: 44c2fa9f1538adb5406d0bd0731e4471f3096ede (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
// 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