xref: /llvm-project/clang/docs/FunctionEffectAnalysis.rst (revision 48adfaf3b290d97260eabb53254de9ada313cd0e)
1*034cae42SDoug Wyatt========================
2*034cae42SDoug WyattFunction Effect Analysis
3*034cae42SDoug Wyatt========================
4*034cae42SDoug Wyatt
5*034cae42SDoug Wyatt.. contents::
6*034cae42SDoug Wyatt  :depth: 3
7*034cae42SDoug Wyatt  :local:
8*034cae42SDoug Wyatt
9*034cae42SDoug Wyatt
10*034cae42SDoug WyattIntroduction
11*034cae42SDoug Wyatt============
12*034cae42SDoug Wyatt
13*034cae42SDoug WyattClang Function Effect Analysis is a language extension which can warn about "unsafe"
14*034cae42SDoug Wyattconstructs. The feature is currently tailored for the Performance Constraint attributes
15*034cae42SDoug Wyatt``nonblocking`` and ``nonallocating``; functions with these attributes are verified as not
16*034cae42SDoug Wyattcontaining any language constructs or calls to other functions which violate the constraint.
17*034cae42SDoug Wyatt(See :doc:`AttributeReference`.)
18*034cae42SDoug Wyatt
19*034cae42SDoug Wyatt
20*034cae42SDoug WyattThe ``nonblocking`` and ``nonallocating`` attributes
21*034cae42SDoug Wyatt====================================================
22*034cae42SDoug Wyatt
23*034cae42SDoug WyattAttribute syntax
24*034cae42SDoug Wyatt----------------
25*034cae42SDoug Wyatt
26*034cae42SDoug WyattThe ``nonblocking`` and ``nonallocating`` attributes apply to function types, allowing them to be
27*034cae42SDoug Wyattattached to functions, blocks, function pointers, lambdas, and member functions.
28*034cae42SDoug Wyatt
29*034cae42SDoug Wyatt.. code-block:: c++
30*034cae42SDoug Wyatt
31*034cae42SDoug Wyatt  // Functions
32*034cae42SDoug Wyatt  void nonblockingFunction() [[clang::nonblocking]];
33*034cae42SDoug Wyatt  void nonallocatingFunction() [[clang::nonallocating]];
34*034cae42SDoug Wyatt
35*034cae42SDoug Wyatt  // Function pointers
36*034cae42SDoug Wyatt  void (*nonblockingFunctionPtr)() [[clang::nonblocking]];
37*034cae42SDoug Wyatt
38*034cae42SDoug Wyatt  // Typedefs, type aliases.
39*034cae42SDoug Wyatt  typedef void (*NBFunctionPtrTypedef)() [[clang::nonblocking]];
40*034cae42SDoug Wyatt  using NBFunctionPtrTypeAlias_gnu = __attribute__((nonblocking)) void (*)();
41*034cae42SDoug Wyatt  using NBFunctionPtrTypeAlias_std = void (*)() [[clang::nonblocking]];
42*034cae42SDoug Wyatt
43*034cae42SDoug Wyatt  // C++ methods
44*034cae42SDoug Wyatt  struct Struct {
45*034cae42SDoug Wyatt    void NBMethod() [[clang::nonblocking]];
46*034cae42SDoug Wyatt  };
47*034cae42SDoug Wyatt
48*034cae42SDoug Wyatt  // C++ lambdas
49*034cae42SDoug Wyatt  auto nbLambda = []() [[clang::nonblocking]] {};
50*034cae42SDoug Wyatt
51*034cae42SDoug Wyatt  // Blocks
52*034cae42SDoug Wyatt  void (^nbBlock)() = ^() [[clang::nonblocking]] {};
53*034cae42SDoug Wyatt
54*034cae42SDoug WyattThe attribute applies only to the function itself. In particular, it does not apply to any nested
55*034cae42SDoug Wyattfunctions or declarations, such as blocks, lambdas, and local classes.
56*034cae42SDoug Wyatt
57*034cae42SDoug WyattThis document uses the C++/C23 syntax ``[[clang::nonblocking]]``, since it parallels the placement
58*034cae42SDoug Wyattof the ``noexcept`` specifier, and the attributes have other similarities to ``noexcept``. The GNU
59*034cae42SDoug Wyatt``__attribute__((nonblocking))`` syntax is also supported. Note that it requires a different
60*034cae42SDoug Wyattplacement on a C++ type alias.
61*034cae42SDoug Wyatt
62*034cae42SDoug WyattLike ``noexcept``, ``nonblocking`` and ``nonallocating`` have an optional argument, a compile-time
63*034cae42SDoug Wyattconstant boolean expression. By default, the argument is ``true``, so ``[[clang::nonblocking]]``
64*034cae42SDoug Wyattis equivalent to ``[[clang::nonblocking(true)]]``, and declares the function type as never blocking.
65*034cae42SDoug Wyatt
66*034cae42SDoug Wyatt
67*034cae42SDoug WyattAttribute semantics
68*034cae42SDoug Wyatt-------------------
69*034cae42SDoug Wyatt
70*034cae42SDoug WyattTogether with ``noexcept``, the ``nonallocating`` and ``nonblocking`` attributes define an ordered
71*034cae42SDoug Wyattseries of performance constraints. From weakest to strongest:
72*034cae42SDoug Wyatt
73*034cae42SDoug Wyatt- ``noexcept`` (as per the C++ standard): The function type will never throw an exception.
74*034cae42SDoug Wyatt- ``nonallocating``: The function type will never allocate memory on the heap or throw an
75*034cae42SDoug Wyatt  exception.
76*034cae42SDoug Wyatt- ``nonblocking``: The function type will never block on a lock, allocate memory on the heap,
77*034cae42SDoug Wyatt  or throw an exception.
78*034cae42SDoug Wyatt
79*034cae42SDoug Wyatt``nonblocking`` includes the ``nonallocating`` guarantee.
80*034cae42SDoug Wyatt
81*034cae42SDoug WyattWhile ``nonblocking`` and ``nonallocating`` are conceptually a superset of ``noexcept``, neither
82*034cae42SDoug Wyattattribute implicitly specifies ``noexcept``. Further, ``noexcept`` has a specified runtime behavior of
83*034cae42SDoug Wyattaborting if an exception is thrown, while the ``nonallocating`` and ``nonblocking`` attributes are
84*034cae42SDoug Wyattmainly for compile-time analysis and have no runtime behavior, except in code built
85*034cae42SDoug Wyattwith Clang's :doc:`RealtimeSanitizer`. Nonetheless, Clang emits a
86*034cae42SDoug Wyattwarning if, in C++, a function is declared ``nonblocking`` or ``nonallocating`` without
87*034cae42SDoug Wyatt``noexcept``. This diagnostic is controlled by ``-Wperf-constraint-implies-noexcept``.
88*034cae42SDoug Wyatt
89*034cae42SDoug Wyatt``nonblocking(true)`` and ``nonallocating(true)`` apply to function *types*, and by extension, to
90*034cae42SDoug Wyattfunction-like declarations. When applied to a declaration with a body, the compiler verifies the
91*034cae42SDoug Wyattfunction, as described in the section "Analysis and warnings", below.
92*034cae42SDoug Wyatt
93*034cae42SDoug Wyatt``blocking`` and ``allocating`` are synonyms for ``nonblocking(false)`` and
94*034cae42SDoug Wyatt``nonallocating(false)``, respectively. They can be used on a function-like declaration to
95*034cae42SDoug Wyattexplicitly disable any potential inference of ``nonblocking`` or ``nonallocating`` during
96*034cae42SDoug Wyattverification. (Inference is described later in this document). ``nonblocking(false)`` and
97*034cae42SDoug Wyatt``nonallocating(false)`` are legal, but superfluous  when applied to a function *type*
98*034cae42SDoug Wyattthat is not part of a declarator: ``float (int) [[nonblocking(false)]]`` and
99*034cae42SDoug Wyatt``float (int)`` are identical types.
100*034cae42SDoug Wyatt
101*034cae42SDoug WyattFor functions with no explicit performance constraint, the worst is assumed: the function
102*034cae42SDoug Wyattallocates memory and potentially blocks, unless it can be inferred otherwise. This is detailed in the
103*034cae42SDoug Wyattdiscussion of verification.
104*034cae42SDoug Wyatt
105*034cae42SDoug WyattThe following example describes the meanings of all permutations of the two attributes and arguments:
106*034cae42SDoug Wyatt
107*034cae42SDoug Wyatt.. code-block:: c++
108*034cae42SDoug Wyatt
109*034cae42SDoug Wyatt  void nb1_na1() [[clang::nonblocking(true)]] [[clang::nonallocating(true)]];
110*034cae42SDoug Wyatt  // Valid; nonallocating(true) is superfluous but doesn't contradict the guarantee.
111*034cae42SDoug Wyatt
112*034cae42SDoug Wyatt  void nb1_na0() [[clang::nonblocking(true)]] [[clang::nonallocating(false)]];
113*034cae42SDoug Wyatt  // error: 'allocating' and 'nonblocking' attributes are not compatible
114*034cae42SDoug Wyatt
115*034cae42SDoug Wyatt  void nb0_na1() [[clang::nonblocking(false)]] [[clang::nonallocating(true)]];
116*034cae42SDoug Wyatt  // Valid; the function does not allocate memory, but may lock for other reasons.
117*034cae42SDoug Wyatt
118*034cae42SDoug Wyatt  void nb0_na0() [[clang::nonblocking(false)]] [[clang::nonallocating(false)]];
119*034cae42SDoug Wyatt  // Valid.
120*034cae42SDoug Wyatt
121*034cae42SDoug Wyatt
122*034cae42SDoug WyattType conversions
123*034cae42SDoug Wyatt----------------
124*034cae42SDoug Wyatt
125*034cae42SDoug WyattA performance constraint can be removed or weakened via an implicit conversion. An attempt to add
126*034cae42SDoug Wyattor strengthen a performance constraint is unsafe and results in a warning. The rules for this
127*034cae42SDoug Wyattare comparable to that for ``noexcept`` in C++17 and later.
128*034cae42SDoug Wyatt
129*034cae42SDoug Wyatt.. code-block:: c++
130*034cae42SDoug Wyatt
131*034cae42SDoug Wyatt  void unannotated();
132*034cae42SDoug Wyatt  void nonblocking() [[clang::nonblocking]];
133*034cae42SDoug Wyatt  void nonallocating() [[clang::nonallocating]];
134*034cae42SDoug Wyatt
135*034cae42SDoug Wyatt  void example()
136*034cae42SDoug Wyatt  {
137*034cae42SDoug Wyatt    // It's fine to remove a performance constraint.
138*034cae42SDoug Wyatt    void (*fp_plain)();
139*034cae42SDoug Wyatt    fp_plain = unannotated;
140*034cae42SDoug Wyatt    fp_plain = nonblocking;
141*034cae42SDoug Wyatt    fp_plain = nonallocating;
142*034cae42SDoug Wyatt
143*034cae42SDoug Wyatt    // Adding/spoofing nonblocking is unsafe.
144*034cae42SDoug Wyatt    void (*fp_nonblocking)() [[clang::nonblocking]];
145*034cae42SDoug Wyatt    fp_nonblocking = nullptr;
146*034cae42SDoug Wyatt    fp_nonblocking = nonblocking;
147*034cae42SDoug Wyatt    fp_nonblocking = unannotated;
148*034cae42SDoug Wyatt    // ^ warning: attribute 'nonblocking' should not be added via type conversion
149*034cae42SDoug Wyatt    fp_nonblocking = nonallocating;
150*034cae42SDoug Wyatt    // ^ warning: attribute 'nonblocking' should not be added via type conversion
151*034cae42SDoug Wyatt
152*034cae42SDoug Wyatt    // Adding/spoofing nonallocating is unsafe.
153*034cae42SDoug Wyatt    void (*fp_nonallocating)() [[clang::nonallocating]];
154*034cae42SDoug Wyatt    fp_nonallocating = nullptr;
155*034cae42SDoug Wyatt    fp_nonallocating = nonallocating;
156*034cae42SDoug Wyatt    fp_nonallocating = nonblocking; // no warning because nonblocking includes nonallocating
157*034cae42SDoug Wyatt    fp_nonallocating = unannotated;
158*034cae42SDoug Wyatt    // ^ warning: attribute 'nonallocating' should not be added via type conversion
159*034cae42SDoug Wyatt  }
160*034cae42SDoug Wyatt
161*034cae42SDoug WyattVirtual methods
162*034cae42SDoug Wyatt---------------
163*034cae42SDoug Wyatt
164*034cae42SDoug WyattIn C++, when a virtual method has a performance constraint, overriding methods in
165*034cae42SDoug Wyattsubclasses inherit the constraint.
166*034cae42SDoug Wyatt
167*034cae42SDoug Wyatt.. code-block:: c++
168*034cae42SDoug Wyatt
169*034cae42SDoug Wyatt  struct Base {
170*034cae42SDoug Wyatt    virtual void unsafe();
171*034cae42SDoug Wyatt    virtual void safe() noexcept [[clang::nonblocking]];
172*034cae42SDoug Wyatt  };
173*034cae42SDoug Wyatt
174*034cae42SDoug Wyatt  struct Derived : public Base {
175*034cae42SDoug Wyatt    void unsafe() [[clang::nonblocking]] override;
176*034cae42SDoug Wyatt    // It's okay for an overridden method to be more constrained
177*034cae42SDoug Wyatt
178*034cae42SDoug Wyatt    void safe() noexcept override;
179*034cae42SDoug Wyatt    // This method is implicitly declared `nonblocking`, inherited from Base.
180*034cae42SDoug Wyatt  };
181*034cae42SDoug Wyatt
182*034cae42SDoug WyattRedeclarations, overloads, and name mangling
183*034cae42SDoug Wyatt--------------------------------------------
184*034cae42SDoug Wyatt
185*034cae42SDoug WyattThe ``nonblocking`` and ``nonallocating`` attributes, like ``noexcept``, do not factor into
186*034cae42SDoug Wyattargument-dependent lookup and overloaded functions/methods.
187*034cae42SDoug Wyatt
188*034cae42SDoug WyattFirst, consider that ``noexcept`` is integral to a function's type:
189*034cae42SDoug Wyatt
190*034cae42SDoug Wyatt.. code-block:: c++
191*034cae42SDoug Wyatt
192*034cae42SDoug Wyatt  void f1(int);
193*034cae42SDoug Wyatt  void f1(int) noexcept;
194*034cae42SDoug Wyatt  // error: exception specification in declaration does not match previous
195*034cae42SDoug Wyatt  //   declaration
196*034cae42SDoug Wyatt
197*034cae42SDoug WyattUnlike ``noexcept``, a redeclaration of ``f2`` with an added or stronger performance constraint is
198*034cae42SDoug Wyattlegal and propagates the attribute to the previous declaration:
199*034cae42SDoug Wyatt
200*034cae42SDoug Wyatt.. code-block:: c++
201*034cae42SDoug Wyatt
202*034cae42SDoug Wyatt  int f2();
203*034cae42SDoug Wyatt  int f2() [[clang::nonblocking]]; // redeclaration with stronger constraint is OK.
204*034cae42SDoug Wyatt
205*034cae42SDoug WyattThis greatly eases adoption by making it possible to annotate functions in external libraries
206*034cae42SDoug Wyattwithout modifying library headers.
207*034cae42SDoug Wyatt
208*034cae42SDoug WyattA redeclaration with a removed or weaker performance constraint produces a warning, paralleling
209*034cae42SDoug Wyattthe behavior of ``noexcept``:
210*034cae42SDoug Wyatt
211*034cae42SDoug Wyatt.. code-block:: c++
212*034cae42SDoug Wyatt
213*034cae42SDoug Wyatt  int f2() { return 42; }
214*034cae42SDoug Wyatt  // warning: attribute 'nonblocking' on function does not match previous declaration
215*034cae42SDoug Wyatt
216*034cae42SDoug WyattIn C++14, the following two declarations of `f3` are identical (a single function). In C++17 they
217*034cae42SDoug Wyattare separate overloads:
218*034cae42SDoug Wyatt
219*034cae42SDoug Wyatt.. code-block:: c++
220*034cae42SDoug Wyatt
221*034cae42SDoug Wyatt  void f3(void (*)());
222*034cae42SDoug Wyatt  void f3(void (*)() noexcept);
223*034cae42SDoug Wyatt
224*034cae42SDoug WyattSimilarly, the following two declarations of `f4` are separate overloads. This pattern may pose
225*034cae42SDoug Wyattdifficulties due to ambiguity:
226*034cae42SDoug Wyatt
227*034cae42SDoug Wyatt.. code-block:: c++
228*034cae42SDoug Wyatt
229*034cae42SDoug Wyatt  void f4(void (*)());
230*034cae42SDoug Wyatt  void f4(void (*)() [[clang::nonblocking]]);
231*034cae42SDoug Wyatt
232*034cae42SDoug WyattThe attributes have no effect on the mangling of function and method names.
233*034cae42SDoug Wyatt
234*034cae42SDoug WyattObjective-C
235*034cae42SDoug Wyatt-----------
236*034cae42SDoug Wyatt
237*034cae42SDoug WyattThe attributes are currently unsupported on Objective-C methods.
238*034cae42SDoug Wyatt
239*034cae42SDoug WyattAnalysis and warnings
240*034cae42SDoug Wyatt=====================
241*034cae42SDoug Wyatt
242*034cae42SDoug WyattConstraints
243*034cae42SDoug Wyatt-----------
244*034cae42SDoug Wyatt
245*034cae42SDoug WyattFunctions declared ``nonallocating`` or ``nonblocking``, when defined, are verified according to the
246*034cae42SDoug Wyattfollowing rules. Such functions:
247*034cae42SDoug Wyatt
248*034cae42SDoug Wyatt1. May not allocate or deallocate memory on the heap. The analysis follows the calls to
249*034cae42SDoug Wyatt   ``operator new`` and ``operator delete`` generated by the ``new`` and ``delete`` keywords, and
250*034cae42SDoug Wyatt   treats them like any other function call. The global ``operator new`` and ``operator delete``
251*034cae42SDoug Wyatt   aren't declared ``nonblocking`` or ``nonallocating`` and so they are considered unsafe. (This
252*034cae42SDoug Wyatt   is correct because most memory allocators are not lock-free. Note that the placement form of
253*034cae42SDoug Wyatt   ``operator new`` is implemented inline in libc++'s ``<new>`` header, and is verifiably
254*034cae42SDoug Wyatt   ``nonblocking``, since it merely casts the supplied pointer to the result type.)
255*034cae42SDoug Wyatt
256*034cae42SDoug Wyatt2. May not throw or catch exceptions. To throw, the compiler must allocate the exception on the
257*034cae42SDoug Wyatt   heap. (Also, many subclasses of ``std::exception`` allocate a string). Exceptions are
258*034cae42SDoug Wyatt   deallocated when caught.
259*034cae42SDoug Wyatt
260*034cae42SDoug Wyatt3. May not make any indirect function call, via a virtual method, function pointer, or
261*034cae42SDoug Wyatt   pointer-to-member function, unless the target is explicitly declared with the same
262*034cae42SDoug Wyatt   ``nonblocking`` or ``nonallocating`` attribute (or stronger).
263*034cae42SDoug Wyatt
264*034cae42SDoug Wyatt4. May not make direct calls to any other function, with the following exceptions:
265*034cae42SDoug Wyatt
266*034cae42SDoug Wyatt  a. The callee is also explicitly declared with the same ``nonblocking`` or ``nonallocating``
267*034cae42SDoug Wyatt     attribute (or stronger).
268*034cae42SDoug Wyatt  b. The callee is defined in the same translation unit as the caller, does not have the ``false``
269*034cae42SDoug Wyatt     form of the required attribute, and can be verified to have the same attribute or stronger,
270*034cae42SDoug Wyatt     according to these same rules.
271*034cae42SDoug Wyatt  c. The callee is a built-in function that is known not to block or allocate.
272*034cae42SDoug Wyatt  d. The callee is declared ``noreturn`` and, if compiling C++, the callee is also declared
273*034cae42SDoug Wyatt     ``noexcept``. This special case excludes functions such as ``abort()`` and ``std::terminate()``
274*034cae42SDoug Wyatt     from the analysis. (The reason for requiring ``noexcept`` in C++ is that a function declared
275*034cae42SDoug Wyatt     ``noreturn`` could be a wrapper for ``throw``.)
276*034cae42SDoug Wyatt
277*034cae42SDoug Wyatt5. May not invoke or access an Objective-C method or property, since ``objc_msgSend()`` calls into
278*034cae42SDoug Wyatt   the Objective-C runtime, which may allocate memory or otherwise block.
279*034cae42SDoug Wyatt
280*034cae42SDoug Wyatt6. May not access thread-local variables. Typically, thread-local variables are allocated on the
281*034cae42SDoug Wyatt   heap when first accessed.
282*034cae42SDoug Wyatt
283*034cae42SDoug WyattFunctions declared ``nonblocking`` have an additional constraint:
284*034cae42SDoug Wyatt
285*034cae42SDoug Wyatt7. May not declare static local variables (e.g. Meyers singletons). The compiler generates a lock
286*034cae42SDoug Wyatt   protecting the initialization of the variable.
287*034cae42SDoug Wyatt
288*034cae42SDoug WyattViolations of any of these rules result in warnings, in the ``-Wfunction-effects`` category:
289*034cae42SDoug Wyatt
290*034cae42SDoug Wyatt.. code-block:: c++
291*034cae42SDoug Wyatt
292*034cae42SDoug Wyatt  void notInline();
293*034cae42SDoug Wyatt
294*034cae42SDoug Wyatt  void example() [[clang::nonblocking]]
295*034cae42SDoug Wyatt  {
296*034cae42SDoug Wyatt    auto* x = new int;
297*034cae42SDoug Wyatt    // warning: function with 'nonblocking' attribute must not allocate or deallocate
298*034cae42SDoug Wyatt    //   memory
299*034cae42SDoug Wyatt
300*034cae42SDoug Wyatt    if (x == nullptr) {
301*034cae42SDoug Wyatt      static Logger* logger = createLogger();
302*034cae42SDoug Wyatt      // warning: function with 'nonblocking' attribute must not have static local variables
303*034cae42SDoug Wyatt
304*034cae42SDoug Wyatt      throw std::runtime_warning{ "null" };
305*034cae42SDoug Wyatt      // warning: 'nonblocking" function 'example' must not throw exceptions
306*034cae42SDoug Wyatt    }
307*034cae42SDoug Wyatt    notInline();
308*034cae42SDoug Wyatt    // warning: 'function with 'nonblocking' attribute must not call non-'nonblocking' function
309*034cae42SDoug Wyatt    //   'notInline'
310*034cae42SDoug Wyatt    // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
311*034cae42SDoug Wyatt    //   definition in this translation unit
312*034cae42SDoug Wyatt  }
313*034cae42SDoug Wyatt
314*034cae42SDoug WyattInferring ``nonblocking`` or ``nonallocating``
315*034cae42SDoug Wyatt----------------------------------------------
316*034cae42SDoug Wyatt
317*034cae42SDoug WyattIn the absence of a ``nonblocking`` or ``nonallocating`` attribute (whether ``true`` or ``false``),
318*034cae42SDoug Wyatta function that is called from a performance-constrained function may be analyzed to
319*034cae42SDoug Wyattinfer whether it has a desired attribute. This analysis happens when the function is not a virtual
320*034cae42SDoug Wyattmethod, and it has a visible definition within the current translation unit (i.e. its body can be
321*034cae42SDoug Wyatttraversed).
322*034cae42SDoug Wyatt
323*034cae42SDoug Wyatt.. code-block:: c++
324*034cae42SDoug Wyatt
325*034cae42SDoug Wyatt  void notInline();
326*034cae42SDoug Wyatt  int implicitlySafe() { return 42; }
327*034cae42SDoug Wyatt  void implicitlyUnsafe() { notInline(); }
328*034cae42SDoug Wyatt
329*034cae42SDoug Wyatt  void example() [[clang::nonblocking]]
330*034cae42SDoug Wyatt  {
331*034cae42SDoug Wyatt    int x = implicitlySafe(); // OK
332*034cae42SDoug Wyatt    implicitlyUnsafe();
333*034cae42SDoug Wyatt    // warning: function with 'nonblocking' attribute must not call non-'nonblocking' function
334*034cae42SDoug Wyatt    //   'implicitlyUnsafe'
335*034cae42SDoug Wyatt    // note (on implicitlyUnsafe): function cannot be inferred 'nonblocking' because it calls
336*034cae42SDoug Wyatt    //   non-'nonblocking' function 'notInline'
337*034cae42SDoug Wyatt    // note (on notInline()): declaration cannot be inferred 'nonblocking' because it has no
338*034cae42SDoug Wyatt    //   definition in this translation unit
339*034cae42SDoug Wyatt  }
340*034cae42SDoug Wyatt
341*034cae42SDoug WyattLambdas and blocks
342*034cae42SDoug Wyatt------------------
343*034cae42SDoug Wyatt
344*034cae42SDoug WyattAs mentioned earlier, the performance constraint attributes apply only to a single function and not
345*034cae42SDoug Wyattto any code nested inside it, including blocks, lambdas, and local classes. It is possible for a
346*034cae42SDoug Wyattnonblocking function to schedule the execution of a blocking lambda on another thread. Similarly, a
347*034cae42SDoug Wyattblocking function may create a ``nonblocking`` lambda for use in a realtime context.
348*034cae42SDoug Wyatt
349*034cae42SDoug WyattOperations which create, destroy, copy, and move lambdas and blocks are analyzed in terms of the
350*034cae42SDoug Wyattunderlying function calls. For example, the creation of a lambda with captures generates a function
351*034cae42SDoug Wyattcall to an anonymous struct's constructor, passing the captures as parameters.
352*034cae42SDoug Wyatt
353*034cae42SDoug WyattImplicit function calls in the AST
354*034cae42SDoug Wyatt----------------------------------
355*034cae42SDoug Wyatt
356*034cae42SDoug WyattThe ``nonblocking`` / ``nonallocating`` analysis occurs at the Sema phase of analysis in Clang.
357*034cae42SDoug WyattDuring Sema, there are some constructs which will eventually become function calls, but do not
358*034cae42SDoug Wyattappear as function calls in the AST. For example, ``auto* foo = new Foo;`` becomes a declaration
359*034cae42SDoug Wyattcontaining a ``CXXNewExpr`` which is understood as a function call to the global ``operator new``
360*034cae42SDoug Wyatt(in this example), and a ``CXXConstructExpr``, which, for analysis purposes, is a function call to
361*034cae42SDoug Wyatt``Foo``'s constructor. Most gaps in the analysis would be due to incomplete knowledge of AST
362*034cae42SDoug Wyattconstructs which become function calls.
363*034cae42SDoug Wyatt
364*034cae42SDoug WyattDisabling diagnostics
365*034cae42SDoug Wyatt---------------------
366*034cae42SDoug Wyatt
367*034cae42SDoug WyattFunction effect diagnostics are controlled by ``-Wfunction-effects``.
368*034cae42SDoug Wyatt
369*034cae42SDoug WyattA construct like this can be used to exempt code from the checks described here:
370*034cae42SDoug Wyatt
371*034cae42SDoug Wyatt.. code-block:: c++
372*034cae42SDoug Wyatt
373*034cae42SDoug Wyatt  #define NONBLOCKING_UNSAFE(...)                                    \
374*034cae42SDoug Wyatt    _Pragma("clang diagnostic push")                                 \
375*034cae42SDoug Wyatt    _Pragma("clang diagnostic ignored \"-Wunknown-warning-option\"") \
376*034cae42SDoug Wyatt    _Pragma("clang diagnostic ignored \"-Wfunction-effects\"")       \
377*034cae42SDoug Wyatt    __VA_ARGS__                                                      \
378*034cae42SDoug Wyatt    _Pragma("clang diagnostic pop")
379*034cae42SDoug Wyatt
380*034cae42SDoug WyattDisabling the diagnostic allows for:
381*034cae42SDoug Wyatt
382*034cae42SDoug Wyatt- constructs which do block, but which in practice are used in ways to avoid unbounded blocking,
383*034cae42SDoug Wyatt  e.g. a thread pool with semaphores to coordinate multiple realtime threads;
384*034cae42SDoug Wyatt- using libraries which are safe but not yet annotated;
385*034cae42SDoug Wyatt- incremental adoption in a large codebase.
386*034cae42SDoug Wyatt
387*034cae42SDoug WyattAdoption
388*034cae42SDoug Wyatt========
389*034cae42SDoug Wyatt
390*034cae42SDoug WyattThere are a few common issues that arise when adopting the ``nonblocking`` and ``nonallocating``
391*034cae42SDoug Wyattattributes.
392*034cae42SDoug Wyatt
393*034cae42SDoug WyattC++ exceptions
394*034cae42SDoug Wyatt--------------
395*034cae42SDoug Wyatt
396*034cae42SDoug WyattExceptions pose a challenge to the adoption of the performance constraints. Common library functions
397*034cae42SDoug Wyattwhich throw exceptions include:
398*034cae42SDoug Wyatt
399*034cae42SDoug Wyatt+----------------------------------+-----------------------------------------------------------------------+
400*034cae42SDoug Wyatt| Method                           | Alternative                                                           |
401*034cae42SDoug Wyatt+==================================+=======================================================================+
402*034cae42SDoug Wyatt| ``std::vector<T>::at()``         | ``operator[](size_t)``, after verifying that the index is in range.   |
403*034cae42SDoug Wyatt+----------------------------------+-----------------------------------------------------------------------+
404*034cae42SDoug Wyatt| ``std::optional<T>::value()``    | ``operator*``, after checking ``has_value()`` or ``operator bool()``. |
405*034cae42SDoug Wyatt+----------------------------------+-----------------------------------------------------------------------+
406*034cae42SDoug Wyatt| ``std::expected<T, E>::value()`` | Same as for ``std::optional<T>::value()``.                            |
407*034cae42SDoug Wyatt+----------------------------------+-----------------------------------------------------------------------+
408*034cae42SDoug Wyatt
409*034cae42SDoug Wyatt
410*034cae42SDoug Wyatt``std::function<R(Args...)>``
411*034cae42SDoug Wyatt-----------------------------
412*034cae42SDoug Wyatt
413*034cae42SDoug Wyatt``std::function<R(Args...)>`` is generally incompatible with ``nonblocking`` and ``nonallocating``
414*034cae42SDoug Wyattcode, because a typical implementation may allocate heap memory in the constructor.
415*034cae42SDoug Wyatt
416*034cae42SDoug WyattAlternatives:
417*034cae42SDoug Wyatt
418*034cae42SDoug Wyatt- ``std::function_ref`` (available in C++26 or as ``llvm::function_ref``). This is appropriate and
419*034cae42SDoug Wyatt  optimal when a functor's lifetime does not need to extend past the function that created it.
420*034cae42SDoug Wyatt
421*034cae42SDoug Wyatt- ``inplace_function`` from WG14. This solves the allocation problem by giving the functor wrapper
422*034cae42SDoug Wyatt  a fixed size known at compile time and using an inline buffer.
423*034cae42SDoug Wyatt
424*034cae42SDoug WyattWhile these alternatives both address the heap allocation of ``std::function``, they are still
425*034cae42SDoug Wyattobstacles to ``nonblocking/nonallocating`` verification, for reasons detailed in the next section.
426*034cae42SDoug Wyatt
427*034cae42SDoug Wyatt
428*034cae42SDoug WyattInteractions with type-erasure techniques
429*034cae42SDoug Wyatt-----------------------------------------
430*034cae42SDoug Wyatt
431*034cae42SDoug Wyatt``std::function<R(Args...)>`` illustrates a common C++ type-erasure technique. Using template
432*034cae42SDoug Wyattargument deduction, it decomposes a function type into its return and parameter types. Additional
433*034cae42SDoug Wyattcomponents of the function type, including ``noexcept``, ``nonblocking``, ``nonallocating``, and any
434*034cae42SDoug Wyattother attributes, are discarded.
435*034cae42SDoug Wyatt
436*034cae42SDoug WyattStandard library support for these components of a function type is not immediately forthcoming.
437*034cae42SDoug Wyatt
438*034cae42SDoug WyattCode can work around this limitation in either of two ways:
439*034cae42SDoug Wyatt
440*034cae42SDoug Wyatt1. Avoid abstractions like ``std::function`` and instead work directly with the original lambda type.
441*034cae42SDoug Wyatt
442*034cae42SDoug Wyatt2. Create a specialized alternative, e.g. ``nonblocking_function_ref<R(Args...)>`` where all function
443*034cae42SDoug Wyatt   pointers used in the implementation and its interface are ``nonblocking``.
444*034cae42SDoug Wyatt
445*034cae42SDoug WyattAs an example of the first approach, when using a lambda as a *Callable* template parameter, the
446*034cae42SDoug Wyattattribute is preserved:
447*034cae42SDoug Wyatt
448*034cae42SDoug Wyatt.. code-block:: c++
449*034cae42SDoug Wyatt
450*034cae42SDoug Wyatt  std::sort(vec.begin(), vec.end(),
451*034cae42SDoug Wyatt    [](const Elem& a, const Elem& b) [[clang::nonblocking]] { return a.mem < b.mem; });
452*034cae42SDoug Wyatt
453*034cae42SDoug WyattHere, the type of the ``Compare`` template parameter is an anonymous class generated from the
454*034cae42SDoug Wyattlambda, with an ``operator()`` method holding the ``nonblocking`` attribute.
455*034cae42SDoug Wyatt
456*034cae42SDoug WyattA complication arises when a *Callable* template parameter, instead of being a lambda or class
457*034cae42SDoug Wyattimplementing ``operator()``, is a function pointer:
458*034cae42SDoug Wyatt
459*034cae42SDoug Wyatt.. code-block:: c++
460*034cae42SDoug Wyatt
461*034cae42SDoug Wyatt  static bool compare_elems(const Elem& a, const Elem& b) [[clang::nonblocking]] {
462*034cae42SDoug Wyatt    return a.mem < b.mem; };
463*034cae42SDoug Wyatt
464*034cae42SDoug Wyatt  std::sort(vec.begin(), vec.end(), compare_elems);
465*034cae42SDoug Wyatt
466*034cae42SDoug WyattHere, the type of ``compare_elems`` is decomposed to ``bool(const Elem&, const Elem&)``, without
467*034cae42SDoug Wyatt``nonblocking``, when forming the template parameter. This can be solved using the second approach,
468*034cae42SDoug Wyattcreating a specialized alternative which explicitly requires the attribute. In this case, it's
469*034cae42SDoug Wyattpossible to use a small wrapper to transform the function pointer into a functor:
470*034cae42SDoug Wyatt
471*034cae42SDoug Wyatt.. code-block:: c++
472*034cae42SDoug Wyatt
473*034cae42SDoug Wyatt  template <typename>
474*034cae42SDoug Wyatt  class nonblocking_fp;
475*034cae42SDoug Wyatt
476*034cae42SDoug Wyatt  template <typename R, typename... Args>
477*034cae42SDoug Wyatt  class nonblocking_fp<R(Args...)> {
478*034cae42SDoug Wyatt  public:
479*034cae42SDoug Wyatt    using impl_t = R (*)(Args...) [[clang::nonblocking]];
480*034cae42SDoug Wyatt
481*034cae42SDoug Wyatt  private:
482*034cae42SDoug Wyatt    impl_t mImpl{ nullptr_t };
483*034cae42SDoug Wyatt  public:
484*034cae42SDoug Wyatt    nonblocking_fp() = default;
485*034cae42SDoug Wyatt    nonblocking_fp(impl_t f) : mImpl{ f } {}
486*034cae42SDoug Wyatt
487*034cae42SDoug Wyatt    R operator()(Args... args) const
488*034cae42SDoug Wyatt    {
489*034cae42SDoug Wyatt      return mImpl(std::forward<Args>(args)...);
490*034cae42SDoug Wyatt    }
491*034cae42SDoug Wyatt  };
492*034cae42SDoug Wyatt
493*034cae42SDoug Wyatt  // deduction guide (like std::function's)
494*034cae42SDoug Wyatt  template< class R, class... ArgTypes >
495*034cae42SDoug Wyatt  nonblocking_fp( R(*)(ArgTypes...) ) -> nonblocking_fp<R(ArgTypes...)>;
496*034cae42SDoug Wyatt
497*034cae42SDoug Wyatt  // --
498*034cae42SDoug Wyatt
499*034cae42SDoug Wyatt  // Wrap the function pointer in a functor which preserves ``nonblocking``.
500*034cae42SDoug Wyatt  std::sort(vec.begin(), vec.end(), nonblocking_fp{ compare_elems });
501*034cae42SDoug Wyatt
502*034cae42SDoug WyattNow, the ``nonblocking`` attribute of ``compare_elems`` is verified when it is converted to a
503*034cae42SDoug Wyatt``nonblocking`` function pointer, as the argument to ``nonblocking_fp``'s constructor. The template
504*034cae42SDoug Wyattparameter is the functor class ``nonblocking_fp``.
505*034cae42SDoug Wyatt
506*034cae42SDoug Wyatt
507*034cae42SDoug WyattStatic local variables
508*034cae42SDoug Wyatt----------------------
509*034cae42SDoug Wyatt
510*034cae42SDoug WyattStatic local variables are often used for lazily-constructed globals (Meyers singletons). Beyond the
511*034cae42SDoug Wyattcompiler's use of a lock to ensure thread-safe initialization, it is dangerously easy to
512*034cae42SDoug Wyattinadvertently trigger initialization, involving heap allocation, from a ``nonblocking`` or
513*034cae42SDoug Wyatt``nonallocating`` context.
514*034cae42SDoug Wyatt
515*034cae42SDoug WyattGenerally, such singletons need to be replaced by globals, and care must be taken to ensure their
516*034cae42SDoug Wyattinitialization before they are used from ``nonblocking`` or ``nonallocating`` contexts.
517*034cae42SDoug Wyatt
518*034cae42SDoug Wyatt
519*034cae42SDoug WyattAnnotating libraries
520*034cae42SDoug Wyatt--------------------
521*034cae42SDoug Wyatt
522*034cae42SDoug WyattIt can be surprising that the analysis does not depend on knowledge of any primitives; it simply
523*034cae42SDoug Wyattassumes the worst, that all function calls are unsafe unless explicitly marked as safe or able to be
524*034cae42SDoug Wyattinferred as safe. With ``nonblocking``, this appears to suffice for all but the most primitive of
525*034cae42SDoug Wyattspinlocks.
526*034cae42SDoug Wyatt
527*034cae42SDoug WyattAt least for an operating system's C functions, it is possible to define an override header which
528*034cae42SDoug Wyattredeclares safe common functions (e.g. ``pthread_self()``) with the addition of ``nonblocking``.
529*034cae42SDoug WyattThis may help in adopting the feature incrementally.
530*034cae42SDoug Wyatt
531*034cae42SDoug WyattIt also helps that many of the functions in the standard C libraries (notably ``<math.h>``)
532*034cae42SDoug Wyattare treated as built-in functions by Clang, which the diagnosis understands to be safe.
533*034cae42SDoug Wyatt
534*034cae42SDoug WyattMuch of the C++ standard library consists of inline templated functions which work well with
535*034cae42SDoug Wyattinference. A small number of primitives may need explicit ``nonblocking/nonallocating`` attributes.
536