[clang] ba18bc4 - [Sema] adds -Wfree-nonheap-object member var checks

George Burgess IV via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 2 11:07:35 PST 2020


Author: Christopher Di Bella
Date: 2020-11-02T11:03:28-08:00
New Revision: ba18bc4925d8cbd4a9354629617cbcafbbd48941

URL: https://github.com/llvm/llvm-project/commit/ba18bc4925d8cbd4a9354629617cbcafbbd48941
DIFF: https://github.com/llvm/llvm-project/commit/ba18bc4925d8cbd4a9354629617cbcafbbd48941.diff

LOG: [Sema] adds -Wfree-nonheap-object member var checks

Checks to make sure that stdlib's (std::)free is being appropriately
used for member variables.

Differential Revision: https://reviews.llvm.org/D90269

Added: 
    

Modified: 
    clang/lib/Sema/SemaChecking.cpp
    clang/test/Sema/warn-free-nonheap-object.c
    clang/test/Sema/warn-free-nonheap-object.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 3d5e2d70d8ca..bad9b14c1fa2 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -10107,19 +10107,9 @@ void Sema::CheckStrncatArguments(const CallExpr *CE,
 }
 
 namespace {
-void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
-                                 const UnaryOperator *UnaryExpr) {
-  if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
-    return;
-
-  const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr());
-  if (Lvalue == nullptr)
-    return;
-
-  const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl());
-  if (Var == nullptr)
-    return;
-
+void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
+                                const UnaryOperator *UnaryExpr,
+                                const VarDecl *Var) {
   StorageClass Class = Var->getStorageClass();
   if (Class == StorageClass::SC_Extern ||
       Class == StorageClass::SC_PrivateExtern ||
@@ -10130,6 +10120,27 @@ void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
       << CalleeName << Var;
 }
 
+void CheckFreeArgumentsOnLvalue(Sema &S, const std::string &CalleeName,
+                                const UnaryOperator *UnaryExpr, const Decl *D) {
+  if (const auto *Field = dyn_cast<FieldDecl>(D))
+    S.Diag(UnaryExpr->getBeginLoc(), diag::warn_free_nonheap_object)
+        << CalleeName << Field;
+}
+
+void CheckFreeArgumentsAddressof(Sema &S, const std::string &CalleeName,
+                                 const UnaryOperator *UnaryExpr) {
+  if (UnaryExpr->getOpcode() != UnaryOperator::Opcode::UO_AddrOf)
+    return;
+
+  if (const auto *Lvalue = dyn_cast<DeclRefExpr>(UnaryExpr->getSubExpr()))
+    if (const auto *Var = dyn_cast<VarDecl>(Lvalue->getDecl()))
+      return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr, Var);
+
+  if (const auto *Lvalue = dyn_cast<MemberExpr>(UnaryExpr->getSubExpr()))
+    return CheckFreeArgumentsOnLvalue(S, CalleeName, UnaryExpr,
+                                      Lvalue->getMemberDecl());
+}
+
 void CheckFreeArgumentsStackArray(Sema &S, const std::string &CalleeName,
                                   const DeclRefExpr *Lvalue) {
   if (!Lvalue->getType()->isArrayType())

diff  --git a/clang/test/Sema/warn-free-nonheap-object.c b/clang/test/Sema/warn-free-nonheap-object.c
index e149e8349571..1618a559b431 100644
--- a/clang/test/Sema/warn-free-nonheap-object.c
+++ b/clang/test/Sema/warn-free-nonheap-object.c
@@ -4,6 +4,11 @@ typedef __SIZE_TYPE__ size_t;
 void *malloc(size_t);
 void free(void *);
 
+struct S {
+  int I;
+  char *P;
+};
+
 int GI;
 void test() {
   {
@@ -31,4 +36,9 @@ void test() {
     free(A);  // expected-warning {{attempt to call free on non-heap object 'A'}}
     free(&A); // expected-warning {{attempt to call free on non-heap object 'A'}}
   }
+  {
+    struct S s;
+    free(&s.I); // expected-warning {{attempt to call free on non-heap object 'I'}}
+    free(s.P);
+  }
 }

diff  --git a/clang/test/Sema/warn-free-nonheap-object.cpp b/clang/test/Sema/warn-free-nonheap-object.cpp
index 0578d9e9cd66..9347709a23ca 100644
--- a/clang/test/Sema/warn-free-nonheap-object.cpp
+++ b/clang/test/Sema/warn-free-nonheap-object.cpp
@@ -13,10 +13,25 @@ int GI;
 struct S {
   operator char *() { return ptr; }
 
+  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);
+  }
+
+  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);
+  }
+
 private:
   char *ptr = (char *)std::malloc(10);
+  static int I;
 };
 
+int S::I = 0;
+
 void test1() {
   {
     free(&GI); // expected-warning {{attempt to call free on non-heap object 'GI'}}
@@ -51,6 +66,10 @@ void test1() {
     free(s);
     free(&s); // expected-warning {{attempt to call free on non-heap object 's'}}
   }
+  {
+    S s;
+    s.CFree();
+  }
 }
 
 void test2() {
@@ -87,4 +106,8 @@ void test2() {
     std::free(s);
     std::free(&s); // expected-warning {{attempt to call std::free on non-heap object 's'}}
   }
+  {
+    S s;
+    s.CXXFree();
+  }
 }


        


More information about the cfe-commits mailing list