1 ========================
2 Function Effect Analysis
3 ========================
13 Clang Function Effect Analysis is a language extension which can warn about "unsafe"
14 constructs. The feature is currently tailored for the Performance Constraint attributes
15 ``nonblocking`` and ``nonallocating``; functions with these attributes are verified as not
16 containing any language constructs or calls to other functions which violate the constraint.
17 (See :doc:`AttributeReference`.)
20 The ``nonblocking`` and ``nonallocating`` attributes
21 ====================================================
26 The ``nonblocking`` and ``nonallocating`` attributes apply to function types, allowing them to be
27 attached to functions, blocks, function pointers, lambdas, and member functions.
32 void nonblockingFunction() [[clang::nonblocking]];
33 void nonallocatingFunction() [[clang::nonallocating]];
36 void (*nonblockingFunctionPtr)() [[clang::nonblocking]];
38 // Typedefs, type aliases.
39 typedef void (*NBFunctionPtrTypedef)() [[clang::nonblocking]];
40 using NBFunctionPtrTypeAlias_gnu = __attribute__((nonblocking)) void (*)();
41 using NBFunctionPtrTypeAlias_std = void (*)() [[clang::nonblocking]];
45 void NBMethod() [[clang::nonblocking]];
49 auto nbLambda = []() [[clang::nonblocking]] {};
52 void (^nbBlock)() = ^() [[clang::nonblocking]] {};
54 The attribute applies only to the function itself. In particular, it does not apply to any nested
55 functions or declarations, such as blocks, lambdas, and local classes.
57 This document uses the C++/C23 syntax ``[[clang::nonblocking]]``, since it parallels the placement
58 of the ``noexcept`` specifier, and the attributes have other similarities to ``noexcept``. The GNU
59 ``__attribute__((nonblocking))`` syntax is also supported. Note that it requires a different
60 placement on a C++ type alias.
62 Like ``noexcept``, ``nonblocking`` and ``nonallocating`` have an optional argument, a compile-time
63 constant boolean expression. By default, the argument is ``true``, so ``[[clang::nonblocking]]``
64 is equivalent to ``[[clang::nonblocking(true)]]``, and declares the function type as never blocking.
70 Together with ``noexcept``, the ``nonallocating`` and ``nonblocking`` attributes define an ordered
71 series of performance constraints. From weakest to strongest:
73 - ``noexcept`` (as per the C++ standard): The function type will never throw an exception.
74 - ``nonallocating``: The function type will never allocate memory on the heap or throw an
76 - ``nonblocking``: The function type will never block on a lock, allocate memory on the heap,
77 or throw an exception.
79 ``nonblocking`` includes the ``nonallocating`` guarantee.
81 While ``nonblocking`` and ``nonallocating`` are conceptually a superset of ``noexcept``, neither
82 attribute implicitly specifies ``noexcept``. Further, ``noexcept`` has a specified runtime behavior of
83 aborting if an exception is thrown, while the ``nonallocating`` and ``nonblocking`` attributes are
84 mainly for compile-time analysis and have no runtime behavior, except in code built
85 with Clang's :doc:`RealtimeSanitizer`. Nonetheless, Clang emits a
86 warning if, in C++, a function is declared ``nonblocking`` or ``nonallocating`` without
87 ``noexcept``. This diagnostic is controlled by ``-Wperf-constraint-implies-noexcept``.
89 ``nonblocking(true)`` and ``nonallocating(true)`` apply to function *types*, and by extension, to
90 function-like declarations. When applied to a declaration with a body, the compiler verifies the
91 function, as described in the section "Analysis and warnings", below.
93 ``blocking`` and ``allocating`` are synonyms for ``nonblocking(false)`` and
94 ``nonallocating(false)``, respectively. They can be used on a function-like declaration to
95 explicitly disable any potential inference of ``nonblocking`` or ``nonallocating`` during
96 verification. (Inference is described later in this document). ``nonblocking(false)`` and
97 ``nonallocating(false)`` are legal, but superfluous when applied to a function *type*
98 that is not part of a declarator: ``float (int) [[nonblocking(false)]]`` and
99 ``float (int)`` are identical types.
101 For functions with no explicit performance constraint, the worst is assumed: the function
102 allocates memory and potentially blocks, unless it can be inferred otherwise. This is detailed in the
103 discussion of verification.
105 The following example describes the meanings of all permutations of the two attributes and arguments:
109 void nb1_na1() [[clang::nonblocking(true)]] [[clang::nonallocating(true)]];
110 // Valid; nonallocating(true) is superfluous but doesn't contradict the guarantee.
112 void nb1_na0() [[clang::nonblocking(true)]] [[clang::nonallocating(false)]];
113 // error: 'allocating' and 'nonblocking' attributes are not compatible
115 void nb0_na1() [[clang::nonblocking(false)]] [[clang::nonallocating(true)]];
116 // Valid; the function does not allocate memory, but may lock for other reasons.
118 void nb0_na0() [[clang::nonblocking(false)]] [[clang::nonallocating(false)]];
125 A performance constraint can be removed or weakened via an implicit conversion. An attempt to add
126 or strengthen a performance constraint is unsafe and results in a warning. The rules for this
127 are comparable to that for ``noexcept`` in C++17 and later.
132 void nonblocking() [[clang::nonblocking]];
133 void nonallocating() [[clang::nonallocating]];
137 // It's fine to remove a performance constraint.
139 fp_plain = unannotated;
140 fp_plain = nonblocking;
141 fp_plain = nonallocating;
143 // Adding/spoofing nonblocking is unsafe.
144 void (*fp_nonblocking)() [[clang::nonblocking]];
145 fp_nonblocking = nullptr;
146 fp_nonblocking = nonblocking;
147 fp_nonblocking = unannotated;
148 // ^ warning: attribute 'nonblocking' should not be added via type conversion
149 fp_nonblocking = nonallocating;
150 // ^ warning: attribute 'nonblocking' should not be added via type conversion
152 // Adding/spoofing nonallocating is unsafe.
153 void (*fp_nonallocating)() [[clang::nonallocating]];
154 fp_nonallocating = nullptr;
155 fp_nonallocating = nonallocating;
156 fp_nonallocating = nonblocking; // no warning because nonblocking includes nonallocating
157 fp_nonallocating = unannotated;
158 // ^ warning: attribute 'nonallocating' should not be added via type conversion
164 In C++, when a virtual method has a performance constraint, overriding methods in
165 subclasses inherit the constraint.
170 virtual void unsafe();
171 virtual void safe() noexcept [[clang::nonblocking]];
174 struct Derived : public Base {
175 void unsafe() [[clang::nonblocking]] override;
176 // It's okay for an overridden method to be more constrained
178 void safe() noexcept override;
179 // This method is implicitly declared `nonblocking`, inherited from Base.
182 Redeclarations, overloads, and name mangling
183 --------------------------------------------
185 The ``nonblocking`` and ``nonallocating`` attributes, like ``noexcept``, do not factor into
186 argument-dependent lookup and overloaded functions/methods.
188 First, consider that ``noexcept`` is integral to a function's type:
193 void f1(int) noexcept;
194 // error: exception specification in declaration does not match previous
197 Unlike ``noexcept``, a redeclaration of ``f2`` with an added or stronger performance constraint is
198 legal and propagates the attribute to the previous declaration:
203 int f2() [[clang::nonblocking]]; // redeclaration with stronger constraint is OK.
205 This greatly eases adoption by making it possible to annotate functions in external libraries
206 without modifying library headers.
208 A redeclaration with a removed or weaker performance constraint produces a warning, paralleling
209 the behavior of ``noexcept``:
213 int f2() { return 42; }
214 // warning: attribute 'nonblocking' on function does not match previous declaration
216 In C++14, the following two declarations of `f3` are identical (a single function). In C++17 they
217 are separate overloads:
222 void f3(void (*)() noexcept);
224 Similarly, the following two declarations of `f4` are separate overloads. This pattern may pose
225 difficulties due to ambiguity:
230 void f4(void (*)() [[clang::nonblocking]]);
232 The attributes have no effect on the mangling of function and method names.
237 The attributes are currently unsupported on Objective-C methods.
239 Analysis and warnings
240 =====================
245 Functions declared ``nonallocating`` or ``nonblocking``, when defined, are verified according to the
246 following rules. Such functions:
248 1. May not allocate or deallocate memory on the heap. The analysis follows the calls to
249 ``operator new`` and ``operator delete`` generated by the ``new`` and ``delete`` keywords, and
250 treats them like any other function call. The global ``operator new`` and ``operator delete``
251 aren't declared ``nonblocking`` or ``nonallocating`` and so they are considered unsafe. (This
252 is correct because most memory allocators are not lock-free. Note that the placement form of
253 ``operator new`` is implemented inline in libc++'s ``<new>`` header, and is verifiably
254 ``nonblocking``, since it merely casts the supplied pointer to the result type.)
256 2. May not throw or catch exceptions. To throw, the compiler must allocate the exception on the
257 heap. (Also, many subclasses of ``std::exception`` allocate a string). Exceptions are
258 deallocated when caught.
260 3. May not make any indirect function call, via a virtual method, function pointer, or
261 pointer-to-member function, unless the target is explicitly declared with the same
262 ``nonblocking`` or ``nonallocating`` attribute (or stronger).
264 4. May not make direct calls to any other function, with the following exceptions:
266 a. The callee is also explicitly declared with the same ``nonblocking`` or ``nonallocating``
267 attribute (or stronger).
268 b. The callee is defined in the same translation unit as the caller, does not have the ``false``
269 form of the required attribute, and can be verified to have the same attribute or stronger,
270 according to these same rules.
271 c. The callee is a built-in function that is known not to block or allocate.
272 d. The callee is declared ``noreturn`` and, if compiling C++, the callee is also declared
273 ``noexcept``. This special case excludes functions such as ``abort()`` and ``std::terminate()``
274 from the analysis. (The reason for requiring ``noexcept`` in C++ is that a function declared
275 ``noreturn`` could be a wrapper for ``throw``.)
277 5. May not invoke or access an Objective-C method or property, since ``objc_msgSend()`` calls into
278 the Objective-C runtime, which may allocate memory or otherwise block.
280 6. May not access thread-local variables. Typically, thread-local variables are allocated on the
281 heap when first accessed.
283 Functions declared ``nonblocking`` have an additional constraint:
285 7. May not declare static local variables (e.g. Meyers singletons). The compiler generates a lock
286 protecting the initialization of the variable.
288 Violations of any of these rules result in warnings, in the ``-Wfunction-effects`` category:
294 void example() [[clang::nonblocking]]
297 // warning: function with 'nonblocking' attribute must not allocate or deallocate
301 static Logger* logger = createLogger();
302 // warning: function with 'nonblocking' attribute must not have static local variables
304 throw std::runtime_warning{ "null" };
305 // warning: 'nonblocking" function 'example' must not throw exceptions
308 // warning: 'function with 'nonblocking' attribute must not call non-'nonblocking' function
310 // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
311 // definition in this translation unit
314 Inferring ``nonblocking`` or ``nonallocating``
315 ----------------------------------------------
317 In the absence of a ``nonblocking`` or ``nonallocating`` attribute (whether ``true`` or ``false``),
318 a function that is called from a performance-constrained function may be analyzed to
319 infer whether it has a desired attribute. This analysis happens when the function is not a virtual
320 method, and it has a visible definition within the current translation unit (i.e. its body can be
326 int implicitlySafe() { return 42; }
327 void implicitlyUnsafe() { notInline(); }
329 void example() [[clang::nonblocking]]
331 int x = implicitlySafe(); // OK
333 // warning: function with 'nonblocking' attribute must not call non-'nonblocking' function
334 // 'implicitlyUnsafe'
335 // note (on implicitlyUnsafe): function cannot be inferred 'nonblocking' because it calls
336 // non-'nonblocking' function 'notInline'
337 // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
338 // definition in this translation unit
344 As mentioned earlier, the performance constraint attributes apply only to a single function and not
345 to any code nested inside it, including blocks, lambdas, and local classes. It is possible for a
346 nonblocking function to schedule the execution of a blocking lambda on another thread. Similarly, a
347 blocking function may create a ``nonblocking`` lambda for use in a realtime context.
349 Operations which create, destroy, copy, and move lambdas and blocks are analyzed in terms of the
350 underlying function calls. For example, the creation of a lambda with captures generates a function
351 call to an anonymous struct's constructor, passing the captures as parameters.
353 Implicit function calls in the AST
354 ----------------------------------
356 The ``nonblocking`` / ``nonallocating`` analysis occurs at the Sema phase of analysis in Clang.
357 During Sema, there are some constructs which will eventually become function calls, but do not
358 appear as function calls in the AST. For example, ``auto* foo = new Foo;`` becomes a declaration
359 containing a ``CXXNewExpr`` which is understood as a function call to the global ``operator new``
360 (in this example), and a ``CXXConstructExpr``, which, for analysis purposes, is a function call to
361 ``Foo``'s constructor. Most gaps in the analysis would be due to incomplete knowledge of AST
362 constructs which become function calls.
364 Disabling diagnostics
365 ---------------------
367 Function effect diagnostics are controlled by ``-Wfunction-effects``.
369 A construct like this can be used to exempt code from the checks described here:
373 #define NONBLOCKING_UNSAFE(...) \
374 _Pragma("clang diagnostic push") \
375 _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \
376 _Pragma("clang diagnostic ignored \"-Wfunction-effects\"") \
378 _Pragma("clang diagnostic pop")
380 Disabling the diagnostic allows for:
382 - constructs which do block, but which in practice are used in ways to avoid unbounded blocking,
383 e.g. a thread pool with semaphores to coordinate multiple realtime threads;
384 - using libraries which are safe but not yet annotated;
385 - incremental adoption in a large codebase.
390 There are a few common issues that arise when adopting the ``nonblocking`` and ``nonallocating``
396 Exceptions pose a challenge to the adoption of the performance constraints. Common library functions
397 which throw exceptions include:
399 +----------------------------------+-----------------------------------------------------------------------+
400 | Method | Alternative |
401 +==================================+=======================================================================+
402 | ``std::vector<T>::at()`` | ``operator[](size_t)``, after verifying that the index is in range. |
403 +----------------------------------+-----------------------------------------------------------------------+
404 | ``std::optional<T>::value()`` | ``operator*``, after checking ``has_value()`` or ``operator bool()``. |
405 +----------------------------------+-----------------------------------------------------------------------+
406 | ``std::expected<T, E>::value()`` | Same as for ``std::optional<T>::value()``. |
407 +----------------------------------+-----------------------------------------------------------------------+
410 ``std::function<R(Args...)>``
411 -----------------------------
413 ``std::function<R(Args...)>`` is generally incompatible with ``nonblocking`` and ``nonallocating``
414 code, because a typical implementation may allocate heap memory in the constructor.
418 - ``std::function_ref`` (available in C++26 or as ``llvm::function_ref``). This is appropriate and
419 optimal when a functor's lifetime does not need to extend past the function that created it.
421 - ``inplace_function`` from WG14. This solves the allocation problem by giving the functor wrapper
422 a fixed size known at compile time and using an inline buffer.
424 While these alternatives both address the heap allocation of ``std::function``, they are still
425 obstacles to ``nonblocking/nonallocating`` verification, for reasons detailed in the next section.
428 Interactions with type-erasure techniques
429 -----------------------------------------
431 ``std::function<R(Args...)>`` illustrates a common C++ type-erasure technique. Using template
432 argument deduction, it decomposes a function type into its return and parameter types. Additional
433 components of the function type, including ``noexcept``, ``nonblocking``, ``nonallocating``, and any
434 other attributes, are discarded.
436 Standard library support for these components of a function type is not immediately forthcoming.
438 Code can work around this limitation in either of two ways:
440 1. Avoid abstractions like ``std::function`` and instead work directly with the original lambda type.
442 2. Create a specialized alternative, e.g. ``nonblocking_function_ref<R(Args...)>`` where all function
443 pointers used in the implementation and its interface are ``nonblocking``.
445 As an example of the first approach, when using a lambda as a *Callable* template parameter, the
446 attribute is preserved:
450 std::sort(vec.begin(), vec.end(),
451 [](const Elem& a, const Elem& b) [[clang::nonblocking]] { return a.mem < b.mem; });
453 Here, the type of the ``Compare`` template parameter is an anonymous class generated from the
454 lambda, with an ``operator()`` method holding the ``nonblocking`` attribute.
456 A complication arises when a *Callable* template parameter, instead of being a lambda or class
457 implementing ``operator()``, is a function pointer:
461 static bool compare_elems(const Elem& a, const Elem& b) [[clang::nonblocking]] {
462 return a.mem < b.mem; };
464 std::sort(vec.begin(), vec.end(), compare_elems);
466 Here, the type of ``compare_elems`` is decomposed to ``bool(const Elem&, const Elem&)``, without
467 ``nonblocking``, when forming the template parameter. This can be solved using the second approach,
468 creating a specialized alternative which explicitly requires the attribute. In this case, it's
469 possible to use a small wrapper to transform the function pointer into a functor:
474 class nonblocking_fp;
476 template <typename R, typename... Args>
477 class nonblocking_fp<R(Args...)> {
479 using impl_t = R (*)(Args...) [[clang::nonblocking]];
482 impl_t mImpl{ nullptr_t };
484 nonblocking_fp() = default;
485 nonblocking_fp(impl_t f) : mImpl{ f } {}
487 R operator()(Args... args) const
489 return mImpl(std::forward<Args>(args)...);
493 // deduction guide (like std::function's)
494 template< class R, class... ArgTypes >
495 nonblocking_fp( R(*)(ArgTypes...) ) -> nonblocking_fp<R(ArgTypes...)>;
499 // Wrap the function pointer in a functor which preserves ``nonblocking``.
500 std::sort(vec.begin(), vec.end(), nonblocking_fp{ compare_elems });
502 Now, the ``nonblocking`` attribute of ``compare_elems`` is verified when it is converted to a
503 ``nonblocking`` function pointer, as the argument to ``nonblocking_fp``'s constructor. The template
504 parameter is the functor class ``nonblocking_fp``.
507 Static local variables
508 ----------------------
510 Static local variables are often used for lazily-constructed globals (Meyers singletons). Beyond the
511 compiler's use of a lock to ensure thread-safe initialization, it is dangerously easy to
512 inadvertently trigger initialization, involving heap allocation, from a ``nonblocking`` or
513 ``nonallocating`` context.
515 Generally, such singletons need to be replaced by globals, and care must be taken to ensure their
516 initialization before they are used from ``nonblocking`` or ``nonallocating`` contexts.
522 It can be surprising that the analysis does not depend on knowledge of any primitives; it simply
523 assumes the worst, that all function calls are unsafe unless explicitly marked as safe or able to be
524 inferred as safe. With ``nonblocking``, this appears to suffice for all but the most primitive of
527 At least for an operating system's C functions, it is possible to define an override header which
528 redeclares safe common functions (e.g. ``pthread_self()``) with the addition of ``nonblocking``.
529 This may help in adopting the feature incrementally.
531 It also helps that many of the functions in the standard C libraries (notably ``<math.h>``)
532 are treated as built-in functions by Clang, which the diagnosis understands to be safe.
534 Much of the C++ standard library consists of inline templated functions which work well with
535 inference. A small number of primitives may need explicit ``nonblocking/nonallocating`` attributes.