Skip to content

Commit 7ce15f3

Browse files
SzelethusNagyDonatsteakhalisuckatcs
authored
[NFC][analyzer][docs] Document MallocChecker's ownership attributes (#121759)
Exactly what it says on the tin! These were written ages ago (2010s), but are still functional, only the docs are missing. ![image](https://github.com/user-attachments/assets/d6b89611-4064-41dd-8482-8643e9e68836) --------- Co-authored-by: Donát Nagy <[email protected]> Co-authored-by: Balazs Benics <[email protected]> Co-authored-by: isuckatcs <[email protected]>
1 parent 5514865 commit 7ce15f3

File tree

2 files changed

+76
-1
lines changed

2 files changed

+76
-1
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2776,7 +2776,7 @@ def Ownership : InheritableAttr {
27762776
let Args = [IdentifierArgument<"Module">,
27772777
VariadicParamIdxArgument<"Args">];
27782778
let Subjects = SubjectList<[HasFunctionProto]>;
2779-
let Documentation = [Undocumented];
2779+
let Documentation = [OwnershipDocs];
27802780
}
27812781

27822782
def Packed : InheritableAttr {

clang/include/clang/Basic/AttrDocs.td

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,81 @@ Query for this attribute with ``__has_attribute(overloadable)``.
13891389
}];
13901390
}
13911391

1392+
def OwnershipDocs : Documentation {
1393+
let Heading = "ownership_holds, ownership_returns, ownership_takes (Clang "
1394+
"Static Analyzer)";
1395+
let Category = DocCatFunction;
1396+
let Content = [{
1397+
1398+
.. note::
1399+
1400+
In order for the Clang Static Analyzer to acknowledge these attributes, the
1401+
``Optimistic`` config needs to be set to true for the checker
1402+
``unix.DynamicMemoryModeling``:
1403+
1404+
``-Xclang -analyzer-config -Xclang unix.DynamicMemoryModeling:Optimistic=true``
1405+
1406+
These attributes are used by the Clang Static Analyzer's dynamic memory modeling
1407+
facilities to mark custom allocating/deallocating functions.
1408+
1409+
All 3 attributes' first parameter of type string is the type of the allocation:
1410+
``malloc``, ``new``, etc. to allow for catching :ref:`mismatched deallocation
1411+
<unix-MismatchedDeallocator>` bugs. The allocation type can be any string, e.g.
1412+
a function annotated with
1413+
returning a piece of memory of type ``lasagna`` but freed with a function
1414+
annotated to release ``cheese`` typed memory will result in mismatched
1415+
deallocation warning.
1416+
1417+
The (currently) only allocation type having special meaning is ``malloc`` --
1418+
the Clang Static Analyzer makes sure that allocating functions annotated with
1419+
``malloc`` are treated like they used the standard ``malloc()``, and can be
1420+
safely deallocated with the standard ``free()``.
1421+
1422+
* Use ``ownership_returns`` to mark a function as an allocating function. Takes
1423+
1 parameter to denote the allocation type.
1424+
* Use ``ownership_takes`` to mark a function as a deallocating function. Takes 2
1425+
parameters: the allocation type, and the index of the parameter that is being
1426+
deallocated (counting from 1).
1427+
* Use ``ownership_holds`` to mark that a function takes over the ownership of a
1428+
piece of memory and will free it at some unspecified point in the future. Like
1429+
``ownership_takes``, this takes 2 parameters: the allocation type, and the
1430+
index of the parameter whose ownership will be taken over (counting from 1).
1431+
1432+
The annotations ``ownership_takes`` and ``ownership_holds`` both prevent memory
1433+
leak reports (concerning the specified argument); the difference between them
1434+
is that using taken memory is a use-after-free error, while using held memory
1435+
is assumed to be legitimate.
1436+
1437+
Example:
1438+
1439+
.. code-block:: c
1440+
1441+
// Denotes that my_malloc will return with a dynamically allocated piece of
1442+
// memory using malloc().
1443+
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
1444+
1445+
// Denotes that my_free will deallocate its parameter using free().
1446+
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
1447+
1448+
// Denotes that my_hold will take over the ownership of its parameter that was
1449+
// allocated via malloc().
1450+
void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
1451+
1452+
Further reading about dynamic memory modeling in the Clang Static Analyzer is
1453+
found in these checker docs:
1454+
:ref:`unix.Malloc <unix-Malloc>`, :ref:`unix.MallocSizeof <unix-MallocSizeof>`,
1455+
:ref:`unix.MismatchedDeallocator <unix-MismatchedDeallocator>`,
1456+
:ref:`cplusplus.NewDelete <cplusplus-NewDelete>`,
1457+
:ref:`cplusplus.NewDeleteLeaks <cplusplus-NewDeleteLeaks>`,
1458+
:ref:`optin.taint.TaintedAlloc <optin-taint-TaintedAlloc>`.
1459+
Mind that many more checkers are affected by dynamic memory modeling changes to
1460+
some extent.
1461+
1462+
Further reading for other annotations:
1463+
`Source Annotations in the Clang Static Analyzer <https://clang-analyzer.llvm.org/annotations.html>`_.
1464+
}];
1465+
}
1466+
13921467
def ObjCMethodFamilyDocs : Documentation {
13931468
let Category = DocCatFunction;
13941469
let Content = [{

0 commit comments

Comments
 (0)