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 @@ -10714,8 +10714,9 @@ const UnaryOperator *UnaryExpr) { if (const auto *Lvalue = dyn_cast(UnaryExpr->getSubExpr())) { const Decl *D = Lvalue->getDecl(); - if (isa(D)) - return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D); + if (isa(D)) + if (!dyn_cast(D)->getType()->isReferenceType()) + return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, D); } if (const auto *Lvalue = dyn_cast(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(*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(*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(*P)); + } { int A[] = {0, 1, 2, 3}; std::free(A); // expected-warning {{attempt to call std::free on non-heap object 'A'}} diff --git a/mlir/lib/IR/OperationSupport.cpp b/mlir/lib/IR/OperationSupport.cpp --- a/mlir/lib/IR/OperationSupport.cpp +++ b/mlir/lib/IR/OperationSupport.cpp @@ -237,9 +237,7 @@ if (isDynamicStorage()) { TrailingOperandStorage &storage = getDynamicStorage(); storage.~TrailingOperandStorage(); - // Workaround false positive in -Wfree-nonheap-object - auto *mem = &storage; - free(mem); + free(&storage); } else { getInlineStorage().~TrailingOperandStorage(); } @@ -373,11 +371,8 @@ new (&newOperands[numOperands]) OpOperand(owner); // If the current storage is also dynamic, free it. - if (isDynamicStorage()) { - // Workaround false positive in -Wfree-nonheap-object - auto *mem = &storage; - free(mem); - } + if (isDynamicStorage()) + free(&storage); // Update the storage representation to use the new dynamic storage. dynamicStorage.setPointerAndInt(newStorage, true);