https://github.com/vidur2 created 
https://github.com/llvm/llvm-project/pull/155131

Hi, I am working on a PR for issue #153300. Currently I dont have a regression 
test or anything for this yet. This is just the initial fix.

>From f903652135758b6a7a20d15565177304add16e2c Mon Sep 17 00:00:00 2001
From: vidur2 <vmod2...@gmail.com>
Date: Thu, 14 Aug 2025 17:28:36 -0400
Subject: [PATCH 1/3] initial malloc change check

---
 .../StaticAnalyzer/Checkers/MallocChecker.cpp | 36 +++++++++++++++++++
 1 file changed, 36 insertions(+)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index efb980962e811..40d13b4597d79 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -3074,6 +3074,42 @@ void MallocChecker::checkPostCall(const CallEvent &Call,
     (*PostFN)(this, C.getState(), Call, C);
     return;
   }
+
+  ProgramStateRef State = C.getState();
+
+  if (const auto *Ctor = dyn_cast<CXXConstructorCall>(&Call)) {
+    // Ensure we are constructing a concrete object/subobject.
+    if (const MemRegion *ObjUnderConstr = Ctor->getCXXThisVal().getAsRegion()) 
{
+      ProgramStateRef NewState = State;
+
+      for (unsigned I = 0, E = Call.getNumArgs(); I != E; ++I) {
+        SVal ArgV = Call.getArgSVal(I);
+
+        SymbolRef Sym = ArgV.getAsSymbol();
+        if (!Sym)
+          continue;
+
+        // Look up current ref-state for this symbol in the RegionState map.
+        if (const RefState *RS = State->get<RegionState>(Sym)) {
+          // Only re-label symbols that are still owned allocations from C++ 
new/new[].
+          if (RS->isAllocated() &&
+              (RS->getAllocationFamily().Kind == AF_CXXNew ||
+               RS->getAllocationFamily().Kind == AF_CXXNewArray)) {
+
+            // Mark as Relinquished at the constructor site: ownership moves
+            // into the constructed subobject. Pass the ctor's origin expr as
+            // the statement associated with this transition.
+            NewState = NewState->set<RegionState>(
+                Sym, RefState::getRelinquished(RS->getAllocationFamily(),
+                                               Ctor->getOriginExpr()));
+          }
+        }
+      }
+
+      if (NewState != State)
+        C.addTransition(NewState);
+    }
+  }
 }
 
 void MallocChecker::checkPreCall(const CallEvent &Call,

>From debfddd77c6f988cf50600f22ffad8a197d41298 Mon Sep 17 00:00:00 2001
From: vidur2 <vmod2...@gmail.com>
Date: Thu, 14 Aug 2025 18:01:23 -0400
Subject: [PATCH 2/3] added tests

---
 clang/test/Analysis/NewDeleteLeaks.cpp | 140 +++++++++++++++++++++++++
 1 file changed, 140 insertions(+)

diff --git a/clang/test/Analysis/NewDeleteLeaks.cpp 
b/clang/test/Analysis/NewDeleteLeaks.cpp
index b2bad7e76fad0..3e54aa900f5cc 100644
--- a/clang/test/Analysis/NewDeleteLeaks.cpp
+++ b/clang/test/Analysis/NewDeleteLeaks.cpp
@@ -14,6 +14,8 @@
 
 #include "Inputs/system-header-simulator-for-malloc.h"
 
+#include <utility>
+
 
//===----------------------------------------------------------------------===//
 // Report for which we expect NoOwnershipChangeVisitor to add a new note.
 
//===----------------------------------------------------------------------===//
@@ -218,3 +220,141 @@ void caller() {
   (void)n;
 } // no-warning: No potential memory leak here, because that's been already 
reported.
 } // namespace symbol_reaper_lifetime
+
+
+// RUN: %clang_analyze_cc1 -std=c++20 
-analyzer-checker=cplusplus.NewDeleteLeaks -verify %s
+
+
+// Minimal RAII class that properly deletes its pointer.
+class Bar {
+public:
+  explicit Bar(int *ptr) : ptr_(ptr) {}
+  ~Bar() {
+    if (ptr_) {
+      delete ptr_;
+      ptr_ = nullptr;
+    }
+  }
+
+  Bar(const Bar &) = delete;
+  Bar &operator=(const Bar &) = delete;
+
+  Bar(Bar &&other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; }
+  Bar &operator=(Bar &&other) noexcept {
+    if (this != &other) {
+      delete ptr_;
+      ptr_ = other.ptr_;
+      other.ptr_ = nullptr;
+    }
+    return *this;
+  }
+
+  int operator*() const { return *ptr_; }
+
+private:
+  int *ptr_;
+};
+
+// Factory returning a prvalue Bar that owns a freshly allocated int.
+static Bar make_bar(int v) { return Bar(new int(v)); }
+
+struct Foo {
+  Bar a;
+  Bar b;
+};
+
+struct FooWithConstructor {
+  Bar a;
+  Bar b;
+  FooWithConstructor(Bar &&original_a, Bar &&original_b)
+      : a(std::move(original_a)), b(std::move(original_b)) {}
+};
+
+//===----------------------------------------------------------------------===//
+// No-false-positive regression tests: these must be silent
+//===----------------------------------------------------------------------===//
+
+namespace prvalue_aggregate_transfer {
+
+void ok_aggregate_from_factory() {
+  Foo foo = {make_bar(1), make_bar(2)}; // expected-no-diagnostics
+}
+
+void ok_aggregate_from_temporary_exprs() {
+  Foo foo = {Bar(new int(1)), Bar(new int(2))}; // expected-no-diagnostics
+}
+
+void ok_ctor_from_factory_rvalues() {
+  FooWithConstructor foo = {make_bar(1), make_bar(2)}; // 
expected-no-diagnostics
+}
+
+} // namespace prvalue_aggregate_transfer
+
+//===----------------------------------------------------------------------===//
+// True-positive regression tests: these should still warn
+//===----------------------------------------------------------------------===//
+
+class BarNoDelete {
+public:
+  explicit BarNoDelete(int *ptr) : ptr_(ptr) {}
+  ~BarNoDelete() {} // intentionally missing delete -> leak
+
+  BarNoDelete(const BarNoDelete &) = delete;
+  BarNoDelete &operator=(const BarNoDelete &) = delete;
+
+  BarNoDelete(BarNoDelete &&other) noexcept : ptr_(other.ptr_) {
+    other.ptr_ = nullptr;
+  }
+  BarNoDelete &operator=(BarNoDelete &&other) noexcept {
+    if (this != &other) {
+      // no delete of old ptr_ on purpose
+      ptr_ = other.ptr_;
+      other.ptr_ = nullptr;
+    }
+    return *this;
+  }
+
+private:
+  int *ptr_;
+};
+
+static BarNoDelete make_bar_nd(int v) { return BarNoDelete(new int(v)); }
+
+struct FooND {
+  BarNoDelete a;
+  BarNoDelete b;
+};
+
+namespace prvalue_aggregate_positive {
+
+void leak_aggregate_from_factory() {
+  FooND f = {make_bar_nd(1), make_bar_nd(2)};
+  // expected-warning@-1 {{Potential memory leak}}
+}
+
+void leak_direct_member() {
+  BarNoDelete b(new int(3));
+  // expected-warning@-1 {{Potential memory leak}}
+}
+
+} // namespace prvalue_aggregate_positive
+
+//===----------------------------------------------------------------------===//
+// Guard tests: neighboring behaviors that must remain intact
+// These ensure we didn't weaken unrelated diagnostics 
(mismatch/double-delete).
+//===----------------------------------------------------------------------===//
+
+namespace guards {
+
+void mismatch_array_delete() {
+  int *p = new int[4];
+  delete p; // expected-warning {{mismatched deallocation: 'delete' should be 
'delete[]'}}
+}
+
+void double_delete() {
+  int *p = new int(1);
+  delete p;
+  delete p; // expected-warning {{Attempt to free released memory}}
+}
+
+} // namespace guards

>From 499ed6745e77a09860fa791063c346eeb31cd478 Mon Sep 17 00:00:00 2001
From: vidur2 <vmod2...@gmail.com>
Date: Thu, 14 Aug 2025 18:07:25 -0400
Subject: [PATCH 3/3] ran formatter

---
 .../StaticAnalyzer/Checkers/MallocChecker.cpp | 261 +++++++++---------
 1 file changed, 125 insertions(+), 136 deletions(-)

diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 40d13b4597d79..eda1c73b6e029 100644
--- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -231,12 +231,15 @@ class RefState {
 
   LLVM_DUMP_METHOD void dump(raw_ostream &OS) const {
     switch (K) {
-#define CASE(ID) case ID: OS << #ID; break;
-    CASE(Allocated)
-    CASE(AllocatedOfSizeZero)
-    CASE(Released)
-    CASE(Relinquished)
-    CASE(Escaped)
+#define CASE(ID)                                                               
\
+  case ID:                                                                     
\
+    OS << #ID;                                                                 
\
+    break;
+      CASE(Allocated)
+      CASE(AllocatedOfSizeZero)
+      CASE(Released)
+      CASE(Relinquished)
+      CASE(Escaped)
     }
   }
 
@@ -304,8 +307,7 @@ struct ReallocPair {
     ID.AddPointer(ReallocatedSym);
   }
   bool operator==(const ReallocPair &X) const {
-    return ReallocatedSym == X.ReallocatedSym &&
-           Kind == X.Kind;
+    return ReallocatedSym == X.ReallocatedSym && Kind == X.Kind;
   }
 };
 
@@ -422,27 +424,28 @@ class MallocChecker
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
   bool evalCall(const CallEvent &Call, CheckerContext &C) const;
   void checkNewAllocator(const CXXAllocatorCall &Call, CheckerContext &C) 
const;
-  void checkPostObjCMessage(const ObjCMethodCall &Call, CheckerContext &C) 
const;
+  void checkPostObjCMessage(const ObjCMethodCall &Call,
+                            CheckerContext &C) const;
   void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
   void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
   void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
   void checkEndFunction(const ReturnStmt *S, CheckerContext &C) const;
   ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
-                            bool Assumption) const;
+                             bool Assumption) const;
   void checkLocation(SVal l, bool isLoad, const Stmt *S,
                      CheckerContext &C) const;
 
   ProgramStateRef checkPointerEscape(ProgramStateRef State,
-                                    const InvalidatedSymbols &Escaped,
-                                    const CallEvent *Call,
-                                    PointerEscapeKind Kind) const;
+                                     const InvalidatedSymbols &Escaped,
+                                     const CallEvent *Call,
+                                     PointerEscapeKind Kind) const;
   ProgramStateRef checkConstPointerEscape(ProgramStateRef State,
                                           const InvalidatedSymbols &Escaped,
                                           const CallEvent *Call,
                                           PointerEscapeKind Kind) const;
 
-  void printState(raw_ostream &Out, ProgramStateRef State,
-                  const char *NL, const char *Sep) const override;
+  void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
+                  const char *Sep) const override;
 
   StringRef getDebugTag() const override { return "MallocChecker"; }
 
@@ -789,9 +792,10 @@ class MallocChecker
   ///
   /// We assume that pointers do not escape through calls to system functions
   /// not handled by this checker.
-  bool mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call,
-                                   ProgramStateRef State,
-                                   SymbolRef &EscapingSymbol) const;
+  bool
+  mayFreeAnyEscapedMemoryOrIsModeledExplicitly(const CallEvent *Call,
+                                               ProgramStateRef State,
+                                               SymbolRef &EscapingSymbol) 
const;
 
   /// Implementation of the checkPointerEscape callbacks.
   [[nodiscard]] ProgramStateRef
@@ -1253,9 +1257,8 @@ MallocChecker::performKernelMalloc(const CallEvent &Call, 
CheckerContext &C,
   NonLoc ZeroFlag = C.getSValBuilder()
                         .makeIntVal(*KernelZeroFlagVal, FlagsEx->getType())
                         .castAs<NonLoc>();
-  SVal MaskedFlagsUC = C.getSValBuilder().evalBinOpNN(State, BO_And,
-                                                      Flags, ZeroFlag,
-                                                      FlagsEx->getType());
+  SVal MaskedFlagsUC = C.getSValBuilder().evalBinOpNN(
+      State, BO_And, Flags, ZeroFlag, FlagsEx->getType());
   if (MaskedFlagsUC.isUnknownOrUndef())
     return std::nullopt;
   DefinedSVal MaskedFlags = MaskedFlagsUC.castAs<DefinedSVal>();
@@ -1485,7 +1488,8 @@ void MallocChecker::checkGMemdup(ProgramStateRef State, 
const CallEvent &Call,
 void MallocChecker::checkGMallocN(ProgramStateRef State, const CallEvent &Call,
                                   CheckerContext &C) const {
   SVal Init = UndefinedVal();
-  SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), 
Call.getArgExpr(1));
+  SVal TotalSize =
+      evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
   State = MallocMemAux(C, Call, TotalSize, Init, State,
                        AllocationFamily(AF_Malloc));
   State = ProcessZeroAllocCheck(C, Call, 0, State);
@@ -1497,7 +1501,8 @@ void MallocChecker::checkGMallocN0(ProgramStateRef State, 
const CallEvent &Call,
                                    CheckerContext &C) const {
   SValBuilder &SB = C.getSValBuilder();
   SVal Init = SB.makeZeroVal(SB.getContext().CharTy);
-  SVal TotalSize = evalMulForBufferSize(C, Call.getArgExpr(0), 
Call.getArgExpr(1));
+  SVal TotalSize =
+      evalMulForBufferSize(C, Call.getArgExpr(0), Call.getArgExpr(1));
   State = MallocMemAux(C, Call, TotalSize, Init, State,
                        AllocationFamily(AF_Malloc));
   State = ProcessZeroAllocCheck(C, Call, 0, State);
@@ -2061,8 +2066,8 @@ ProgramStateRef MallocChecker::FreeMemAux(CheckerContext 
&C,
 
 /// Checks if the previous call to free on the given symbol failed - if free
 /// failed, returns true. Also, returns the corresponding return value symbol.
-static bool didPreviousFreeFail(ProgramStateRef State,
-                                SymbolRef Sym, SymbolRef &RetStatusSymbol) {
+static bool didPreviousFreeFail(ProgramStateRef State, SymbolRef Sym,
+                                SymbolRef &RetStatusSymbol) {
   const SymbolRef *Ret = State->get<FreeReturnValue>(Sym);
   if (Ret) {
     assert(*Ret && "We should not store the null return symbol");
@@ -2318,8 +2323,7 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr 
*ArgExpr,
       // Check if the memory location being freed is the actual location
       // allocated, or an offset.
       RegionOffset Offset = R->getAsOffset();
-      if (Offset.isValid() &&
-          !Offset.hasSymbolicOffset() &&
+      if (Offset.isValid() && !Offset.hasSymbolicOffset() &&
           Offset.getOffset() != 0) {
         const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
         HandleOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,
@@ -2365,9 +2369,8 @@ MallocChecker::FreeMemAux(CheckerContext &C, const Expr 
*ArgExpr,
 
   // Normal free.
   if (Hold)
-    return State->set<RegionState>(SymBase,
-                                   RefState::getRelinquished(Family,
-                                                             ParentExpr));
+    return State->set<RegionState>(
+        SymBase, RefState::getRelinquished(Family, ParentExpr));
 
   return State->set<RegionState>(SymBase,
                                  RefState::getReleased(Family, ParentExpr));
@@ -2606,12 +2609,12 @@ void 
MallocChecker::HandleMismatchedDealloc(CheckerContext &C,
         os << " allocated by " << AllocOs.str();
 
       os << " should be deallocated by ";
-        printExpectedDeallocName(os, RS->getAllocationFamily());
+      printExpectedDeallocName(os, RS->getAllocationFamily());
 
-        if (printMemFnName(DeallocOs, C, DeallocExpr))
-          os << ", not " << DeallocOs.str();
+      if (printMemFnName(DeallocOs, C, DeallocExpr))
+        os << ", not " << DeallocOs.str();
 
-        printOwnershipTakesList(os, C, DeallocExpr);
+      printOwnershipTakesList(os, C, DeallocExpr);
     }
 
     auto R = std::make_unique<PathSensitiveBugReport>(
@@ -2648,8 +2651,7 @@ void MallocChecker::HandleOffsetFree(CheckerContext &C, 
SVal ArgVal,
   assert(MR && "Only MemRegion based symbols can have offset free errors");
 
   RegionOffset Offset = MR->getAsOffset();
-  assert((Offset.isValid() &&
-          !Offset.hasSymbolicOffset() &&
+  assert((Offset.isValid() && !Offset.hasSymbolicOffset() &&
           Offset.getOffset() != 0) &&
          "Only symbols with a valid offset can have offset free errors");
 
@@ -2658,11 +2660,8 @@ void MallocChecker::HandleOffsetFree(CheckerContext &C, 
SVal ArgVal,
   os << "Argument to ";
   if (!printMemFnName(os, C, DeallocExpr))
     os << "deallocator";
-  os << " is offset by "
-     << offsetBytes
-     << " "
-     << ((abs(offsetBytes) > 1) ? "bytes" : "byte")
-     << " from the start of ";
+  os << " is offset by " << offsetBytes << " "
+     << ((abs(offsetBytes) > 1) ? "bytes" : "byte") << " from the start of ";
   if (AllocExpr && printMemFnName(AllocNameOs, C, AllocExpr))
     os << "memory allocated by " << AllocNameOs.str();
   else
@@ -2892,8 +2891,8 @@ MallocChecker::ReallocMemAux(CheckerContext &C, const 
CallEvent &Call,
 
     // Record the info about the reallocated symbol so that we could properly
     // process failed reallocation.
-    stateRealloc = stateRealloc->set<ReallocPairs>(ToPtr,
-                                                   ReallocPair(FromPtr, Kind));
+    stateRealloc =
+        stateRealloc->set<ReallocPairs>(ToPtr, ReallocPair(FromPtr, Kind));
     // The reallocated symbol should stay alive for as long as the new symbol.
     C.getSymbolManager().addSymbolDependency(ToPtr, FromPtr);
     return stateRealloc;
@@ -2951,8 +2950,7 @@ MallocChecker::LeakInfo 
MallocChecker::getAllocationSite(const ExplodedNode *N,
     // Allocation node, is the last node in the current or parent context in
     // which the symbol was tracked.
     const LocationContext *NContext = N->getLocationContext();
-    if (NContext == LeakContext ||
-        NContext->isParentOf(LeakContext))
+    if (NContext == LeakContext || NContext->isParentOf(LeakContext))
       AllocNode = N;
     N = N->pred_empty() ? nullptr : *(N->pred_begin());
   }
@@ -2988,9 +2986,8 @@ void MallocChecker::HandleLeak(SymbolRef Sym, 
ExplodedNode *N,
 
   const Stmt *AllocationStmt = AllocNode->getStmtForDiagnostics();
   if (AllocationStmt)
-    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
-                                              C.getSourceManager(),
-                                              AllocNode->getLocationContext());
+    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
+        AllocationStmt, C.getSourceManager(), AllocNode->getLocationContext());
 
   SmallString<200> buf;
   llvm::raw_svector_ostream os(buf);
@@ -3012,8 +3009,7 @@ void MallocChecker::HandleLeak(SymbolRef Sym, 
ExplodedNode *N,
 }
 
 void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper,
-                                     CheckerContext &C) const
-{
+                                     CheckerContext &C) const {
   ProgramStateRef state = C.getState();
   RegionStateTy OldRS = state->get<RegionState>();
   RegionStateTy::Factory &F = state->get_context<RegionState>();
@@ -3031,8 +3027,7 @@ void MallocChecker::checkDeadSymbols(SymbolReaper 
&SymReaper,
 
   if (RS == OldRS) {
     // We shouldn't have touched other maps yet.
-    assert(state->get<ReallocPairs>() ==
-           C.getState()->get<ReallocPairs>());
+    assert(state->get<ReallocPairs>() == C.getState()->get<ReallocPairs>());
     assert(state->get<FreeReturnValue>() ==
            C.getState()->get<FreeReturnValue>());
     return;
@@ -3091,7 +3086,8 @@ void MallocChecker::checkPostCall(const CallEvent &Call,
 
         // Look up current ref-state for this symbol in the RegionState map.
         if (const RefState *RS = State->get<RegionState>(Sym)) {
-          // Only re-label symbols that are still owned allocations from C++ 
new/new[].
+          // Only re-label symbols that are still owned allocations from C++
+          // new/new[].
           if (RS->isAllocated() &&
               (RS->getAllocationFamily().Kind == AF_CXXNew ||
                RS->getAllocationFamily().Kind == AF_CXXNewArray)) {
@@ -3201,8 +3197,7 @@ void MallocChecker::checkPreCall(const CallEvent &Call,
   }
 }
 
-void MallocChecker::checkPreStmt(const ReturnStmt *S,
-                                 CheckerContext &C) const {
+void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const 
{
   checkEscapeOnReturn(S, C);
 }
 
@@ -3234,7 +3229,7 @@ void MallocChecker::checkEscapeOnReturn(const ReturnStmt 
*S,
     if (const MemRegion *MR = RetVal.getAsRegion())
       if (isa<FieldRegion, ElementRegion>(MR))
         if (const SymbolicRegion *BMR =
-              dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
+                dyn_cast<SymbolicRegion>(MR->getBaseRegion()))
           Sym = BMR->getSymbol();
 
   // Check if we are returning freed memory.
@@ -3254,14 +3249,13 @@ void MallocChecker::checkPostStmt(const BlockExpr *BE,
     return;
 
   ProgramStateRef state = C.getState();
-  const BlockDataRegion *R =
-    cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
+  const BlockDataRegion *R = 
cast<BlockDataRegion>(C.getSVal(BE).getAsRegion());
 
   auto ReferencedVars = R->referenced_vars();
   if (ReferencedVars.empty())
     return;
 
-  SmallVector<const MemRegion*, 10> Regions;
+  SmallVector<const MemRegion *, 10> Regions;
   const LocationContext *LC = C.getLocationContext();
   MemRegionManager &MemMgr = C.getSValBuilder().getRegionManager();
 
@@ -3273,8 +3267,7 @@ void MallocChecker::checkPostStmt(const BlockExpr *BE,
     Regions.push_back(VR);
   }
 
-  state =
-    state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
+  state = 
state->scanReachableSymbols<StopTrackingCallback>(Regions).getState();
   C.addTransition(state);
 }
 
@@ -3331,8 +3324,7 @@ void MallocChecker::checkUseZeroAllocated(SymbolRef Sym, 
CheckerContext &C,
   if (const RefState *RS = C.getState()->get<RegionState>(Sym)) {
     if (RS->isAllocatedOfSizeZero())
       HandleUseZeroAlloc(C, RS->getStmt()->getSourceRange(), Sym);
-  }
-  else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
+  } else if (C.getState()->contains<ReallocSizeZeroSymbols>(Sym)) {
     HandleUseZeroAlloc(C, S->getSourceRange(), Sym);
   }
 }
@@ -3349,9 +3341,8 @@ void MallocChecker::checkLocation(SVal l, bool isLoad, 
const Stmt *S,
 
 // If a symbolic region is assumed to NULL (or another constant), stop tracking
 // it - assuming that allocation failed on this path.
-ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state,
-                                              SVal Cond,
-                                              bool Assumption) const {
+ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state, SVal Cond,
+                                          bool Assumption) const {
   RegionStateTy RS = state->get<RegionState>();
   for (SymbolRef Sym : llvm::make_first_range(RS)) {
     // If the symbol is assumed to be NULL, remove it from consideration.
@@ -3376,7 +3367,8 @@ ProgramStateRef MallocChecker::evalAssume(ProgramStateRef 
state,
       if (RS->isReleased()) {
         switch (ReallocPair.Kind) {
         case OAR_ToBeFreedAfterFailure:
-          state = state->set<RegionState>(ReallocSym,
+          state = state->set<RegionState>(
+              ReallocSym,
               RefState::getAllocated(RS->getAllocationFamily(), 
RS->getStmt()));
           break;
         case OAR_DoNotTrackAfterFailure:
@@ -3394,9 +3386,8 @@ ProgramStateRef MallocChecker::evalAssume(ProgramStateRef 
state,
 }
 
 bool MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
-                                              const CallEvent *Call,
-                                              ProgramStateRef State,
-                                              SymbolRef &EscapingSymbol) const 
{
+    const CallEvent *Call, ProgramStateRef State,
+    SymbolRef &EscapingSymbol) const {
   assert(Call);
   EscapingSymbol = nullptr;
 
@@ -3506,8 +3497,8 @@ bool 
MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
   // Do not warn on pointers passed to 'setbuf' when used with std streams,
   // these leaks might be intentional when setting the buffer for stdio.
   // http://stackoverflow.com/questions/2671151/who-frees-setvbuf-buffer
-  if (FName == "setbuf" || FName =="setbuffer" ||
-      FName == "setlinebuf" || FName == "setvbuf") {
+  if (FName == "setbuf" || FName == "setbuffer" || FName == "setlinebuf" ||
+      FName == "setvbuf") {
     if (Call->getNumArgs() >= 1) {
       const Expr *ArgE = Call->getArgExpr(0)->IgnoreParenCasts();
       if (const DeclRefExpr *ArgDRE = dyn_cast<DeclRefExpr>(ArgE))
@@ -3557,18 +3548,16 @@ bool 
MallocChecker::mayFreeAnyEscapedMemoryOrIsModeledExplicitly(
   return false;
 }
 
-ProgramStateRef MallocChecker::checkPointerEscape(ProgramStateRef State,
-                                             const InvalidatedSymbols &Escaped,
-                                             const CallEvent *Call,
-                                             PointerEscapeKind Kind) const {
+ProgramStateRef MallocChecker::checkPointerEscape(
+    ProgramStateRef State, const InvalidatedSymbols &Escaped,
+    const CallEvent *Call, PointerEscapeKind Kind) const {
   return checkPointerEscapeAux(State, Escaped, Call, Kind,
                                /*IsConstPointerEscape*/ false);
 }
 
-ProgramStateRef MallocChecker::checkConstPointerEscape(ProgramStateRef State,
-                                              const InvalidatedSymbols 
&Escaped,
-                                              const CallEvent *Call,
-                                              PointerEscapeKind Kind) const {
+ProgramStateRef MallocChecker::checkConstPointerEscape(
+    ProgramStateRef State, const InvalidatedSymbols &Escaped,
+    const CallEvent *Call, PointerEscapeKind Kind) const {
   // If a const pointer escapes, it may not be freed(), but it could be 
deleted.
   return checkPointerEscapeAux(State, Escaped, Call, Kind,
                                /*IsConstPointerEscape*/ true);
@@ -3760,61 +3749,61 @@ PathDiagnosticPieceRef 
MallocBugVisitor::VisitNode(const ExplodedNode *N,
         }
         Msg = OS.str();
         break;
-        }
-        case AF_None:
-          assert(false && "Unhandled allocation family!");
-          return nullptr;
-        }
+      }
+      case AF_None:
+        assert(false && "Unhandled allocation family!");
+        return nullptr;
+      }
 
-        // Record the stack frame that is _responsible_ for this memory release
-        // event. This will be used by the false positive suppression 
heuristics
-        // that recognize the release points of reference-counted objects.
-        //
-        // Usually (e.g. in C) we say that the _responsible_ stack frame is the
-        // current innermost stack frame:
-        ReleaseFunctionLC = CurrentLC->getStackFrame();
-        // ...but if the stack contains a destructor call, then we say that the
-        // outermost destructor stack frame is the _responsible_ one:
-        for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
-          if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
-            if (isReferenceCountingPointerDestructor(DD)) {
-              // This immediately looks like a reference-counting destructor.
-              // We're bad at guessing the original reference count of the
-              // object, so suppress the report for now.
-              BR.markInvalid(getTag(), DD);
-
-              // After report is considered invalid there is no need to proceed
-              // futher.
-              return nullptr;
-            }
-
-            // Switch suspection to outer destructor to catch patterns like:
-            // (note that class name is distorted to bypass
-            // isReferenceCountingPointerDestructor() logic)
-            //
-            // SmartPointr::~SmartPointr() {
-            //  if (refcount.fetch_sub(1) == 1)
-            //    release_resources();
-            // }
-            // void SmartPointr::release_resources() {
-            //   free(buffer);
-            // }
-            //
-            // This way ReleaseFunctionLC will point to outermost destructor 
and
-            // it would be possible to catch wider range of FP.
-            //
-            // NOTE: it would be great to support smth like that in C, since
-            // currently patterns like following won't be supressed:
-            //
-            // void doFree(struct Data *data) { free(data); }
-            // void putData(struct Data *data)
-            // {
-            //   if (refPut(data))
-            //     doFree(data);
-            // }
-            ReleaseFunctionLC = LC->getStackFrame();
+      // Record the stack frame that is _responsible_ for this memory release
+      // event. This will be used by the false positive suppression heuristics
+      // that recognize the release points of reference-counted objects.
+      //
+      // Usually (e.g. in C) we say that the _responsible_ stack frame is the
+      // current innermost stack frame:
+      ReleaseFunctionLC = CurrentLC->getStackFrame();
+      // ...but if the stack contains a destructor call, then we say that the
+      // outermost destructor stack frame is the _responsible_ one:
+      for (const LocationContext *LC = CurrentLC; LC; LC = LC->getParent()) {
+        if (const auto *DD = dyn_cast<CXXDestructorDecl>(LC->getDecl())) {
+          if (isReferenceCountingPointerDestructor(DD)) {
+            // This immediately looks like a reference-counting destructor.
+            // We're bad at guessing the original reference count of the
+            // object, so suppress the report for now.
+            BR.markInvalid(getTag(), DD);
+
+            // After report is considered invalid there is no need to proceed
+            // futher.
+            return nullptr;
           }
+
+          // Switch suspection to outer destructor to catch patterns like:
+          // (note that class name is distorted to bypass
+          // isReferenceCountingPointerDestructor() logic)
+          //
+          // SmartPointr::~SmartPointr() {
+          //  if (refcount.fetch_sub(1) == 1)
+          //    release_resources();
+          // }
+          // void SmartPointr::release_resources() {
+          //   free(buffer);
+          // }
+          //
+          // This way ReleaseFunctionLC will point to outermost destructor and
+          // it would be possible to catch wider range of FP.
+          //
+          // NOTE: it would be great to support smth like that in C, since
+          // currently patterns like following won't be supressed:
+          //
+          // void doFree(struct Data *data) { free(data); }
+          // void putData(struct Data *data)
+          // {
+          //   if (refPut(data))
+          //     doFree(data);
+          // }
+          ReleaseFunctionLC = LC->getStackFrame();
         }
+      }
 
     } else if (isRelinquished(RSCurr, RSPrev, S)) {
       Msg = "Memory ownership is transferred";
@@ -3828,13 +3817,13 @@ PathDiagnosticPieceRef 
MallocBugVisitor::VisitNode(const ExplodedNode *N,
       if (SymbolRef sym = findFailedReallocSymbol(state, statePrev)) {
         // Is it possible to fail two reallocs WITHOUT testing in between?
         assert((!FailedReallocSymbol || FailedReallocSymbol == sym) &&
-          "We only support one failed realloc at a time.");
+               "We only support one failed realloc at a time.");
         BR.markInteresting(sym);
         FailedReallocSymbol = sym;
       }
     }
 
-  // We are in a special mode if a reallocation failed later in the path.
+    // We are in a special mode if a reallocation failed later in the path.
   } else if (Mode == ReallocationFailed) {
     assert(FailedReallocSymbol && "No symbol to look for.");
 
@@ -3903,8 +3892,8 @@ namespace clang {
 namespace ento {
 namespace allocation_state {
 
-ProgramStateRef
-markReleased(ProgramStateRef State, SymbolRef Sym, const Expr *Origin) {
+ProgramStateRef markReleased(ProgramStateRef State, SymbolRef Sym,
+                             const Expr *Origin) {
   AllocationFamily Family(AF_InnerBuffer);
   return State->set<RegionState>(Sym, RefState::getReleased(Family, Origin));
 }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to