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