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'}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits