Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -2776,7 +2776,7 @@ def Ownership : InheritableAttr {
let Args = [IdentifierArgument<"Module">,
VariadicParamIdxArgument<"Args">];
let Subjects = SubjectList<[HasFunctionProto]>;
let Documentation = [Undocumented];
let Documentation = [OwnershipDocs];
}

def Packed : InheritableAttr {
Expand Down
62 changes: 62 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1389,6 +1389,68 @@ Query for this attribute with ``__has_attribute(overloadable)``.
}];
}

def OwnershipDocs : Documentation {
let Heading = "ownership_holds, ownership_returns, ownership_takes (Clang "
"Static Analyzer)";
let Category = DocCatFunction;
let Content = [{

.. note::

In order for the Clang Static Analyzer to acknowledge these attributes, the
``Optimistic`` config needs to be set to true for the checker
``unix.DynamicMemoryModeling``:

``-Xclang -analyzer-config -Xclang unix.DynamicMemoryModeling:Optimistic=true``

These attributes are used by the Clang Static Analyzer's dynamic memory modeling
facilities to mark custom allocating/deallocating functions.

All 3 attributes' first parameter of type string is the type of the allocation:
``malloc``, ``new``, etc. to allow for catching mismatched deallocation bugs to
be found.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I'm not exactly sure what etc refers to. Is the set of accepted values here backed in or it can be the name of any previously declared function? Or even any identifier?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, from what I understand, you can set the allocation type to something totally custom, like "lasagna" as well, and if you that for all of your custom dynamic memory functions correctly, it should catch mismatch errors (you deallocated memory with "cheese", but it was allocated with "lasagna"). There is a single exception for "malloc" (and should be for new, new[], etc), MallocChecker will be sure that functions with "malloc" annotations will be treated the same as the standard "malloc" and "free".

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't clear to me from the proposed description. I think it deserves to be noted.


* Use ``ownership_returns`` to mark a function as an allocating function. Takes
1 parameter to denote the allocation type.
* Use ``ownership_takes`` to mark a function as a deallocating function. Takes 2
parameters: the allocation type, and the index of the parameter that is being
deallocated (counting from 1).
* Use ``ownership_holds`` to mark that a function takes over the ownership of a
piece of memory. The analyzer will assume that the memory is not leaked even
if it finds that the last pointer referencing it went out of scope (almost as
if it was freed). Takes 2 parameters: the allocation type, and the index of
the parameter whose ownership will be taken over (counting from 1).

Example:

.. code-block:: c

// Denotes that my_malloc will return with adynamically allocated piece of
// memory using malloc().
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);

// Denotes that my_free will deallocate its parameter using free().
void __attribute((ownership_takes(malloc, 1))) my_free(void *);

// Denotes that my_hold will take over the ownership of its parameter that was
// allocated via malloc().
void __attribute((ownership_holds(malloc, 1))) my_hold(void *);

Further reading about dynamic memory modeling in the Clang Static Analyzer is
found in these checker docs:
:ref:`unix.Malloc <unix-Malloc>`, :ref:`unix.MallocSizeof <unix-MallocSizeof>`,
:ref:`unix.MismatchedDeallocator <unix-MismatchedDeallocator>`,
:ref:`cplusplus.NewDelete <cplusplus-NewDelete>`,
:ref:`cplusplus.NewDeleteLeaks <cplusplus-NewDeleteLeaks>`,
:ref:`optin.taint.TaintedAlloc <optin-taint-TaintedAlloc>`.
Mind that many more checkers are affected by dynamic memory modeling changes to
some extent.

Further reading for other annotations:
`Source Annotations in the Clang Static Analyzer <https://clang-analyzer.llvm.org/annotations.html>`_.
}];
}

def ObjCMethodFamilyDocs : Documentation {
let Category = DocCatFunction;
let Content = [{
Expand Down
Loading