diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -10726,8 +10726,9 @@ 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 --- a/clang/test/Sema/warn-free-nonheap-object.cpp +++ b/clang/test/Sema/warn-free-nonheap-object.cpp @@ -10,23 +10,34 @@ 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 *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'}}