[clang] 9a72580 - [clang][Sema] removes -Wfree-nonheap-object reference param false positive
Christopher Di Bella via cfe-commits
cfe-commits at lists.llvm.org
Wed Jul 21 14:30:44 PDT 2021
Author: Christopher Di Bella
Date: 2021-07-21T21:30:16Z
New Revision: 9a72580a548da8008dca479ec50e4eb75e56db71
URL: https://github.com/llvm/llvm-project/commit/9a72580a548da8008dca479ec50e4eb75e56db71
DIFF: https://github.com/llvm/llvm-project/commit/9a72580a548da8008dca479ec50e4eb75e56db71.diff
LOG: [clang][Sema] removes -Wfree-nonheap-object reference param false positive
Taking the address of a reference parameter might be valid, and without
CFA, false positives are going to be more trouble than they're worth.
Differential Revision: https://reviews.llvm.org/D102728
Added:
Modified:
clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/warn-free-nonheap-object.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 075fad6476ef..242c2968da45 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -10726,8 +10726,9 @@ void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
const UnaryOperator *UnaryExpr) {
if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr())) {
const Decl *D = Lvalue->getDecl();
- if (isa<VarDecl, FunctionDecl>(D))
- return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
+ if (isa<DeclaratorDecl>(D))
+ if (!dyn_cast<DeclaratorDecl>(D)->getType()->isReferenceType())
+ return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D);
}
if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
diff --git a/clang/test/Sema/warn-free-nonheap-object.cpp b/clang/test/Sema/warn-free-nonheap-object.cpp
index 9347709a23ca..37dc0fdaad93 100644
--- a/clang/test/Sema/warn-free-nonheap-object.cpp
+++ b/clang/test/Sema/warn-free-nonheap-object.cpp
@@ -10,23 +10,34 @@ void free(void *p);
int GI;
+void free_reference(char &x) { ::free(&x); }
+void free_reference(char &&x) { ::free(&x); }
+void std_free_reference(char &x) { std::free(&x); }
+void std_free_reference(char &&x) { std::free(&x); }
+
struct S {
- operator char *() { return ptr; }
+ operator char *() { return ptr1; }
void CFree() {
- ::free(&ptr); // expected-warning {{attempt to call free on non-heap object 'ptr'}}
- ::free(&I); // expected-warning {{attempt to call free on non-heap object 'I'}}
- ::free(ptr);
+ ::free(&ptr1); // expected-warning {{attempt to call free on non-heap object 'ptr1'}}
+ ::free(&I); // expected-warning {{attempt to call free on non-heap object 'I'}}
+ ::free(ptr1);
+ free_reference(*ptr2);
+ free_reference(static_cast<char&&>(*ptr3));
}
void CXXFree() {
- std::free(&ptr); // expected-warning {{attempt to call std::free on non-heap object 'ptr'}}
- std::free(&I); // expected-warning {{attempt to call std::free on non-heap object 'I'}}
- std::free(ptr);
+ std::free(&ptr1); // expected-warning {{attempt to call std::free on non-heap object 'ptr1'}}
+ std::free(&I); // expected-warning {{attempt to call std::free on non-heap object 'I'}}
+ std::free(ptr1);
+ std_free_reference(*ptr2);
+ std_free_reference(static_cast<char&&>(*ptr3));
}
private:
- char *ptr = (char *)std::malloc(10);
+ char *ptr1 = (char *)std::malloc(10);
+ char *ptr2 = (char *)std::malloc(10);
+ char *ptr3 = (char *)std::malloc(10);
static int I;
};
@@ -93,6 +104,14 @@ void test2() {
void *P = std::malloc(8);
std::free(P);
}
+ {
+ char* P = (char *)std::malloc(2);
+ std_free_reference(*P);
+ }
+ {
+ char* P = (char *)std::malloc(2);
+ std_free_reference(static_cast<char&&>(*P));
+ }
{
int A[] = {0, 1, 2, 3};
std::free(A); // expected-warning {{attempt to call std::free on non-heap object 'A'}}
More information about the cfe-commits
mailing list