1 // Copyright 2019 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 //
15 // Preprocessor macros that wrap compiler-specific features.
16 // This file is used by both C++ and C code.
17 #pragma once
18 
19 #include <assert.h>
20 
21 // Marks a struct or class as packed.
22 #define PW_PACKED(declaration) declaration __attribute__((packed))
23 
24 // Marks a function or object as used, ensuring code for it is generated.
25 #define PW_USED __attribute__((used))
26 
27 // Prevents generation of a prologue or epilogue for a function. This is
28 // helpful when implementing the function in assembly.
29 #define PW_NO_PROLOGUE __attribute__((naked))
30 
31 // Marks that a function declaration takes a printf-style format string and
32 // variadic arguments. This allows the compiler to perform check the validity of
33 // the format string and arguments. This macro must only be on the function
34 // declaration, not the definition.
35 //
36 // The format_index is index of the format string parameter and parameter_index
37 // is the starting index of the variadic arguments. Indices start at 1. For C++
38 // class member functions, add one to the index to account for the implicit this
39 // parameter.
40 //
41 // This example shows a function where the format string is argument 2 and the
42 // varargs start at argument 3.
43 //
44 //   int PrintfStyleFunction(char* buffer,
45 //                           const char* fmt, ...) PW_PRINTF_FORMAT(2,3);
46 //
47 //   int PrintfStyleFunction(char* buffer, const char* fmt, ...) {
48 //     ... implementation here ...
49 //   }
50 //
51 
52 // When compiling for host using MinGW, use gnu_printf() rather than printf()
53 // to support %z format specifiers.
54 #ifdef __USE_MINGW_ANSI_STDIO
55 #define _PW_PRINTF_FORMAT_TYPE gnu_printf
56 #else
57 #define _PW_PRINTF_FORMAT_TYPE printf
58 #endif  // __USE_MINGW_ANSI_STDIO
59 
60 #define PW_PRINTF_FORMAT(format_index, parameter_index) \
61   __attribute__((format(_PW_PRINTF_FORMAT_TYPE, format_index, parameter_index)))
62 
63 // Places a variable in the specified linker section and directs the compiler
64 // to keep the variable, even if it is not used. Depending on the linker
65 // options, the linker may still remove this section if it is not declared in
66 // the linker script and marked KEEP.
67 #ifdef __APPLE__
68 #define PW_KEEP_IN_SECTION(name) __attribute__((section("__DATA," name), used))
69 #else
70 #define PW_KEEP_IN_SECTION(name) __attribute__((section(name), used))
71 #endif  // __APPLE__
72 
73 // Indicate to the compiler that the annotated function won't return. Example:
74 //
75 //   PW_NO_RETURN void HandleAssertFailure(ErrorCode error_code);
76 //
77 #define PW_NO_RETURN __attribute__((noreturn))
78 
79 // Prevents the compiler from inlining a fuction.
80 #define PW_NO_INLINE __attribute__((noinline))
81 
82 // Indicate to the compiler that the given section of code will not be reached.
83 // Example:
84 //
85 //   int main() {
86 //     InitializeBoard();
87 //     vendor_StartScheduler();  // Note: vendor forgot noreturn attribute.
88 //     PW_UNREACHABLE;
89 //   }
90 //
91 #define PW_UNREACHABLE __builtin_unreachable()
92 
93 // Indicate to a sanitizer compiler runtime to skip the named check in the
94 // associated function.
95 // Example:
96 //
97 //   uint32_t djb2(const void* buf, size_t len)
98 //       PW_NO_SANITIZE("unsigned-integer-overflow"){
99 //     uint32_t hash = 5381;
100 //     const uint8_t* u8 = static_cast<const uint8_t*>(buf);
101 //     for (size_t i = 0; i < len; ++i) {
102 //       hash = (hash * 33) + u8[i]; /* hash * 33 + c */
103 //     }
104 //     return hash;
105 //   }
106 #ifdef __clang__
107 #define PW_NO_SANITIZE(check) __attribute__((no_sanitize(check)))
108 #else
109 #define PW_NO_SANITIZE(check)
110 #endif  // __clang__
111 
112 // Wrapper around `__has_attribute`, which is defined by GCC 5+ and Clang and
113 // evaluates to a non zero constant integer if the attribute is supported or 0
114 // if not.
115 #ifdef __has_attribute
116 #define PW_HAVE_ATTRIBUTE(x) __has_attribute(x)
117 #else
118 #define PW_HAVE_ATTRIBUTE(x) 0
119 #endif
120 
121 #define _PW_REQUIRE_SEMICOLON \
122   static_assert(1, "This macro must be terminated with a semicolon")
123 
124 // PW_MODIFY_DIAGNOSTICS_PUSH and PW_MODIFY_DIAGNOSTICS_POP are used to turn off
125 // or on diagnostics (warnings or errors) for a section of code. Use
126 // PW_MODIFY_DIAGNOSTICS_PUSH, use PW_MODIFY_DIAGNOSTIC as many times as needed,
127 // then use PW_MODIFY_DIAGNOSTICS_POP to restore the previous settings.
128 #define PW_MODIFY_DIAGNOSTICS_PUSH() \
129   _Pragma("GCC diagnostic push") _PW_REQUIRE_SEMICOLON
130 #define PW_MODIFY_DIAGNOSTICS_POP() \
131   _Pragma("GCC diagnostic pop") _PW_REQUIRE_SEMICOLON
132 
133 // Changes how a diagnostic (warning or error) is handled. Most commonly used to
134 // disable warnings. PW_MODIFY_DIAGNOSTIC should be used between
135 // PW_MODIFY_DIAGNOSTICS_PUSH and PW_MODIFY_DIAGNOSTICS_POP statements to avoid
136 // applying the modifications too broadly.
137 //
138 // 'kind' must be one of warning, error, or ignored.
139 #define PW_MODIFY_DIAGNOSTIC(kind, option) \
140   PW_PRAGMA(GCC diagnostic kind option) _PW_REQUIRE_SEMICOLON
141 
142 // Applies PW_MODIFY_DIAGNOSTIC only for GCC. This is useful for warnings that
143 // aren't supported by or don't need to be changed in other compilers.
144 #ifdef __clang__
145 #define PW_MODIFY_DIAGNOSTIC_GCC(kind, option) _PW_REQUIRE_SEMICOLON
146 #else
147 #define PW_MODIFY_DIAGNOSTIC_GCC(kind, option) \
148   PW_MODIFY_DIAGNOSTIC(kind, option)
149 #endif  // __clang__
150 
151 // Expands to a _Pragma with the contents as a string. _Pragma must take a
152 // single string literal; this can be used to construct a _Pragma argument.
153 #define PW_PRAGMA(contents) _Pragma(#contents)
154