Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][analyzer] Support ownership_{returns,takes} attributes #98941

Merged
merged 9 commits into from
Jul 24, 2024
8 changes: 8 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,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 @@ -206,6 +209,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 @@ -3331,6 +3331,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
Loading