Skip to content

Commit

Permalink
[clang][analyzer] Support ownership_{returns,takes} attributes (#98941
Browse files Browse the repository at this point in the history
)

Add support for checking mismatched ownership_returns/ownership_takes attributes.

Closes #76861
  • Loading branch information
pskrgag authored Jul 24, 2024
1 parent 05e9506 commit 893a303
Show file tree
Hide file tree
Showing 20 changed files with 414 additions and 222 deletions.
8 changes: 8 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ Removed Compiler Flags
Attribute Changes in Clang
--------------------------

- Clang now disallows more than one ``__attribute__((ownership_returns(class, idx)))`` with
different class names attached to one function.

Improvements to Clang's diagnostics
-----------------------------------

Expand Down Expand Up @@ -217,6 +220,11 @@ Static Analyzer
New features
^^^^^^^^^^^^

- MallocChecker now checks for ``ownership_returns(class, idx)`` and ``ownership_takes(class, idx)``
attributes with class names different from "malloc". Clang static analyzer now reports an error
if class of allocation and deallocation function mismatches.
`Documentation <https://clang.llvm.org/docs/analyzer/checkers.html#unix-mismatcheddeallocator-c-c>`__.

Crash and bug fixes
^^^^^^^^^^^^^^^^^^^

Expand Down
10 changes: 10 additions & 0 deletions clang/docs/analyzer/checkers/mismatched_deallocator_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ void test() {

// C, C++
void __attribute((ownership_returns(malloc))) *user_malloc(size_t);
void __attribute((ownership_takes(malloc, 1))) *user_free(void *);

void __attribute((ownership_returns(malloc1))) *user_malloc1(size_t);
void __attribute((ownership_takes(malloc1, 1))) *user_free1(void *);

void test() {
int *p = (int *)user_malloc(sizeof(int));
Expand All @@ -24,6 +28,12 @@ void test() {
realloc(p, sizeof(long)); // warn
}

// C, C++
void test() {
int *p = user_malloc(10);
user_free1(p); // warn
}

// C, C++
template <typename T>
struct SimpleSmartPointer {
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -3334,6 +3334,10 @@ def err_ownership_returns_index_mismatch : Error<
"'ownership_returns' attribute index does not match; here it is %0">;
def note_ownership_returns_index_mismatch : Note<
"declared with index %0 here">;
def err_ownership_takes_class_mismatch : Error<
"'ownership_takes' attribute class does not match; here it is '%0'">;
def note_ownership_takes_class_mismatch : Note<
"declared with class '%0' here">;
def err_format_strftime_third_parameter : Error<
"strftime format attribute requires 3rd parameter to be 0">;
def err_format_attribute_not : Error<"format argument not a string type">;
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,16 @@ static void handleOwnershipAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
<< Idx.getSourceIndex() << Ex->getSourceRange();
return;
}
} else if (K == OwnershipAttr::Takes &&
I->getOwnKind() == OwnershipAttr::Takes) {
if (I->getModule()->getName() != ModuleName) {
S.Diag(I->getLocation(), diag::err_ownership_takes_class_mismatch)
<< I->getModule()->getName();
S.Diag(AL.getLoc(), diag::note_ownership_takes_class_mismatch)
<< ModuleName << Ex->getSourceRange();

return;
}
}
}
OwnershipArgs.push_back(Idx);
Expand Down
Loading

0 comments on commit 893a303

Please sign in to comment.