[clang] Diagnose misuse of the cleanup attribute (PR #80040)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jan 30 09:55:54 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Bhuminjay Soni (11happy)

<details>
<summary>Changes</summary>

**Overview:**
This pull request fixes #<!-- -->79443 when the cleanup attribute is intended to be applied to a variable declaration, passing its address to a specified function. The problem arises when standard functions like free, closedir, fclose, etc., are used incorrectly with this attribute, leading to incorrect behavior. 

**Testing:**
- Tested the updated code.
- Verified that other functionalities remain unaffected.

![Screenshot from 2024-01-30 23-15-51](https://github.com/llvm/llvm-project/assets/76656712/5d6dad20-2c8c-48e4-b6d6-dcabefe378ad)

![Screenshot from 2024-01-30 23-22-17](https://github.com/llvm/llvm-project/assets/76656712/e046e308-f93b-4ea2-abe2-ac7630a64a89)



**Dependencies:**
- No dependencies on other pull requests.

**CC:**
- @<!-- -->AaronBallman 

---
Full diff: https://github.com/llvm/llvm-project/pull/80040.diff


4 Files Affected:

- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+4) 
- (modified) clang/include/clang/Sema/Sema.h (+2) 
- (modified) clang/lib/Sema/SemaDeclAttr.cpp (+7) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+17) 


``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 24d32cb87c89e..99ef803b1e0ec 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8265,6 +8265,10 @@ def warn_condition_is_assignment : Warning<"using the result of an "
 def warn_free_nonheap_object
   : Warning<"attempt to call %0 on non-heap %select{object %2|object: block expression|object: lambda-to-function-pointer conversion}1">,
     InGroup<FreeNonHeapObject>;
+def warn_free_called_on_unallocated_object : Warning<
+  "'%0' called on unallocated object '%1'">,
+  InGroup<FreeNonHeapObject>;
+  
 
 // Completely identical except off by default.
 def warn_condition_is_idiomatic_assignment : Warning<"using the result "
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index b5946e3f3178f..535c479aeb7c5 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12932,6 +12932,8 @@ class Sema final {
 
   bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType);
 
+  bool IsPointerToPointer(QualType LHSType, QualType RHSType);
+
   bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType);
 
   ExprResult PerformImplicitConversion(Expr *From, QualType ToType,
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 069571fcf7864..e149f745cc2f9 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3782,6 +3782,13 @@ static void handleCleanupAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   }
 
   D->addAttr(::new (S.Context) CleanupAttr(S.Context, AL, FD));
+
+  if (S.IsPointerToPointer(ParamTy, Ty)) {
+    VarDecl *VD = cast<VarDecl>(D);
+    S.Diag(Loc, diag::warn_free_called_on_unallocated_object)
+        << NI.getName() << VD;
+    return;
+  }
 }
 
 static void handleEnumExtensibilityAttr(Sema &S, Decl *D,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 2f1ddfb215116..255e0be3cc842 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -10098,6 +10098,23 @@ static bool isVector(QualType QT, QualType ElementType) {
   return false;
 }
 
+bool Sema::IsPointerToPointer(QualType LHSType, QualType RHSType) {
+  if (const PointerType *LHSPointer = dyn_cast<PointerType>(LHSType)) {
+    // Check if LHS is a single pointer, not a pointer to a pointer.
+    if (!isa<PointerType>(LHSPointer->getPointeeType())) {
+      if (isa<PointerType>(RHSType)) {
+        if (const PointerType *RHSPtr = dyn_cast<PointerType>(RHSType)) {
+          // If RHSType is a pointer to a pointer type, return True
+          if (isa<PointerType>(RHSPtr->getPointeeType())) {
+            return true;
+          }
+        }
+      }
+    }
+  }
+  return false;
+}
+
 /// CheckAssignmentConstraints (C99 6.5.16) - This routine currently
 /// has code to accommodate several GCC extensions when type checking
 /// pointers. Here are some objectionable examples that GCC considers warnings:

``````````

</details>


https://github.com/llvm/llvm-project/pull/80040


More information about the cfe-commits mailing list