diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst index 912cca72e1ad5..e358bcc621064 100644 --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1543,8 +1543,20 @@ Currently, only the following parameter attributes are defined: is null is captured in some other way. ``nofree`` - This indicates that the callee does not free the pointer argument. This is not - a valid attribute for return values. + This indicates that a pointer based on this argument cannot be freed during + the execution of the function. + + More formally, a ``nofree`` argument provides the callee with a new pointer + with the same address and a derived provenance, where the derived + provenance has the same permissions as the original, except that the + underlying object cannot be freed until the function returns (or unwinds), + otherwise the behavior is undefined. This includes frees of the pointer on + other threads if the free *happens-before* the function return. + + Notably, it is still possible to free the underlying object through a + pointer that is not based on the argument. + + This is not a valid attribute for return values. .. _nest: @@ -2326,22 +2338,21 @@ For example: internal linkage and only has one call site, so the original call is dead after inlining. ``nofree`` - This function attribute indicates that the function does not, directly or - transitively, call a memory-deallocation function (``free``, for example) - on a memory allocation which existed before the call. - - As a result, uncaptured pointers that are known to be dereferenceable - prior to a call to a function with the ``nofree`` attribute are still - known to be dereferenceable after the call. The capturing condition is - necessary in environments where the function might communicate the - pointer to another thread which then deallocates the memory. Alternatively, - ``nosync`` would ensure such communication cannot happen and even captured - pointers cannot be freed by the function. + This function attribute indicates that the function does not free any memory + allocation which existed before the call, either through direct calls to + a memory-deallocation function like ``free``, or through synchronization. + Freeing through synchronization here means that a deallocation + *happens-before* the function exit but does not *happens-before* the + function entry. + + As a result, pointers that are known to be dereferenceable prior to a call + to a function with the ``nofree`` attribute are still known to be + dereferenceable after the call. A ``nofree`` function is explicitly allowed to free memory which it - allocated or (if not ``nosync``) arrange for another thread to free - memory on its behalf. As a result, perhaps surprisingly, a ``nofree`` - function can return a pointer to a previously deallocated + allocated or arrange for another thread to free such memory on its behalf. + As a result, perhaps surprisingly, a ``nofree`` function can return a + pointer to a previously deallocated :ref:`allocated object`. ``noimplicitfloat`` Disallows implicit floating-point code. This inhibits optimizations that