<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><br><div><div>On Apr 4, 2013, at 4:46 PM, Anton Yartsev <<a href="mailto:anton.yartsev@gmail.com">anton.yartsev@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Author: ayartsev<br>Date: Thu Apr  4 18:46:29 2013<br>New Revision: 178814<br><br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=178814&view=rev">http://llvm.org/viewvc/llvm-project?rev=178814&view=rev</a><br>Log:<br>[analyzer] Reduced the unwanted correlations between checkers living inside MallocChecker.cpp<br><br>This fixes an issue pointed to by Jordan: if unix.Malloc and unix.MismatchedDeallocator are both on, then we end up still tracking leaks of memory allocated by new.<br>Moved the guards right before emitting the bug reports to unify and simplify the logic of handling of multiple checkers. Now all the checkers perform their checks regardless of if they were enabled, or not, and it is decided just before the emitting of the report, if it should be emitted. (idea from Anna).<br><br>Additional changes:<span class="Apple-converted-space"> </span><br>improved test coverage for checker correlations;<br>refactoring: BadDealloc -> MismatchedDealloc<br><br>Added:<br>   cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp<br>   cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp<br>   cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp<br>   cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp<br>Modified:<br>   cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp<br>   cfe/trunk/test/Analysis/NewDelete-checker-test.cpp<br><br>Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=178814&r1=178813&r2=178814&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=178814&r1=178813&r2=178814&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)<br>+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Apr  4 18:46:29 2013<br>@@ -149,7 +149,7 @@ class MallocChecker : public Checker<che<br>  mutable OwningPtr<BugType> BT_Leak;<br>  mutable OwningPtr<BugType> BT_UseFree;<br>  mutable OwningPtr<BugType> BT_BadFree;<br>-  mutable OwningPtr<BugType> BT_BadDealloc;<br>+  mutable OwningPtr<BugType> BT_MismatchedDealloc;<br>  mutable OwningPtr<BugType> BT_OffsetFree;<br>  mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,<br>                         *II_valloc, *II_reallocf, *II_strndup, *II_strdup;<br>@@ -198,7 +198,7 @@ private:<br>  void initIdentifierInfo(ASTContext &C) const;<br><br>  /// \brief Determine family of a deallocation expression.<br>-  AllocationFamily getAllocationFamily(CheckerContext &C, const Expr *E) const;<br>+  AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;<br><br>  /// \brief Print names of allocators and deallocators.<br>  ///<br>@@ -282,12 +282,19 @@ private:<br>                                  PointerEscapeKind Kind,<br>                                  bool(*CheckRefState)(const RefState*)) const;<br><br>+  // Used to suppress warnings if they are not related to the tracked family<br>+  // (derived from AllocDeallocStmt).</div></blockquote><div><br></div>The comment should focus on what the function does not what it's used for. Also, the name is a bit misleading. isTrackedFamily sounds like "are we currently tracking this family in the state?".</div><div><br></div><div>Also, let's try to stick to doxygen comments.</div><div><br></div><div><br><blockquote type="cite"><div style="letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">+  bool isTrackedFamily(AllocationFamily Family) const;<br>+  bool isTrackedFamily(CheckerContext &C, const Stmt *AllocDeallocStmt) const;<br>+  bool isTrackedFamily(CheckerContext &C, SymbolRef Sym) const;<br>+<br>  static bool SummarizeValue(raw_ostream &os, SVal V);<br>  static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);<br>  void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range,<span class="Apple-converted-space"> </span><br>                     const Expr *DeallocExpr) const;<br>-  void ReportBadDealloc(CheckerContext &C, SourceRange Range,<br>-                        const Expr *DeallocExpr, const RefState *RS) const;<br>+  void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,<br>+                               const Expr *DeallocExpr,<span class="Apple-converted-space"> </span><br>+                               const RefState *RS) const;<br>  void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range,<span class="Apple-converted-space"> </span><br>                        const Expr *DeallocExpr,<span class="Apple-converted-space"> </span><br>                        const Expr *AllocExpr = 0) const;<br>@@ -558,45 +565,39 @@ void MallocChecker::checkPostStmt(const<br>    initIdentifierInfo(C.getASTContext());<br>    IdentifierInfo *FunI = FD->getIdentifier();<br><br>-    if (Filter.CMallocOptimistic || Filter.CMallocPessimistic ||<br>-        Filter.CMismatchedDeallocatorChecker) {<br>-      if (FunI == II_malloc || FunI == II_valloc) {<br>-        if (CE->getNumArgs() < 1)<br>-          return;<br>-        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);<br>-      } else if (FunI == II_realloc) {<br>-        State = ReallocMem(C, CE, false);<br>-      } else if (FunI == II_reallocf) {<br>-        State = ReallocMem(C, CE, true);<br>-      } else if (FunI == II_calloc) {<br>-        State = CallocMem(C, CE);<br>-      } else if (FunI == II_free) {<br>-        State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);<br>-      } else if (FunI == II_strdup) {<br>-        State = MallocUpdateRefState(C, CE, State);<br>-      } else if (FunI == II_strndup) {<br>-        State = MallocUpdateRefState(C, CE, State);<br>-      }<br>+    if (FunI == II_malloc || FunI == II_valloc) {<br>+      if (CE->getNumArgs() < 1)<br>+        return;<br>+      State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);<br>+    } else if (FunI == II_realloc) {<br>+      State = ReallocMem(C, CE, false);<br>+    } else if (FunI == II_reallocf) {<br>+      State = ReallocMem(C, CE, true);<br>+    } else if (FunI == II_calloc) {<br>+      State = CallocMem(C, CE);<br>+    } else if (FunI == II_free) {<br>+      State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);<br>+    } else if (FunI == II_strdup) {<br>+      State = MallocUpdateRefState(C, CE, State);<br>+    } else if (FunI == II_strndup) {<br>+      State = MallocUpdateRefState(C, CE, State);<br>    }<br>-<br>-    if (Filter.CNewDeleteChecker || Filter.CMismatchedDeallocatorChecker) {<br>-      if (isStandardNewDelete(FD, C.getASTContext())) {<br>-        // Process direct calls to operator new/new[]/delete/delete[] functions<br>-        // as distinct from new/new[]/delete/delete[] expressions that are<span class="Apple-converted-space"> </span><br>-        // processed by the checkPostStmt callbacks for CXXNewExpr and<span class="Apple-converted-space"> </span><br>-        // CXXDeleteExpr.<br>-        OverloadedOperatorKind K = FD->getOverloadedOperator();<br>-        if (K == OO_New)<br>-          State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,<br>-                               AF_CXXNew);<br>-        else if (K == OO_Array_New)<br>-          State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,<br>-                               AF_CXXNewArray);<br>-        else if (K == OO_Delete || K == OO_Array_Delete)<br>-          State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);<br>-        else<br>-          llvm_unreachable("not a new/delete operator");<br>-      }<br>+    else if (isStandardNewDelete(FD, C.getASTContext())) {<br>+      // Process direct calls to operator new/new[]/delete/delete[] functions<br>+      // as distinct from new/new[]/delete/delete[] expressions that are<span class="Apple-converted-space"> </span><br>+      // processed by the checkPostStmt callbacks for CXXNewExpr and<span class="Apple-converted-space"> </span><br>+      // CXXDeleteExpr.<br>+      OverloadedOperatorKind K = FD->getOverloadedOperator();<br>+      if (K == OO_New)<br>+        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,<br>+                             AF_CXXNew);<br>+      else if (K == OO_Array_New)<br>+        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,<br>+                             AF_CXXNewArray);<br>+      else if (K == OO_Delete || K == OO_Array_Delete)<br>+        State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);<br>+      else<br>+        llvm_unreachable("not a new/delete operator");<br>    }<br>  }<br><br>@@ -631,9 +632,6 @@ void MallocChecker::checkPostStmt(const<br>      if (SymbolRef Sym = C.getSVal(*I).getAsSymbol())<br>        checkUseAfterFree(Sym, C, *I);<br><br>-  if (!Filter.CNewDeleteChecker && !Filter.CMismatchedDeallocatorChecker)<br>-    return;<br>-<br>  if (!isStandardNewDelete(NE->getOperatorNew(), C.getASTContext()))<br>    return;<br><br>@@ -654,9 +652,6 @@ void MallocChecker::checkPreStmt(const C<br>    if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol())<br>      checkUseAfterFree(Sym, C, DE->getArgument());<br><br>-  if (!Filter.CNewDeleteChecker && !Filter.CMismatchedDeallocatorChecker)<br>-    return;<br>-<br>  if (!isStandardNewDelete(DE->getOperatorDelete(), C.getASTContext()))<br>    return;<br><br>@@ -838,32 +833,39 @@ static bool didPreviousFreeFail(ProgramS<br>}<br><br>AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C,<span class="Apple-converted-space"> </span><br>-                                                    const Expr *E) const {<br>-  if (!E)<br>+                                                    const Stmt *S) const {<br>+  if (!S)<br>    return AF_None;<br><br>-  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {<br>+  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {<br>    const FunctionDecl *FD = C.getCalleeDecl(CE);<br>+<br>+    if (!FD)<br>+      FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());<br>+<br>    ASTContext &Ctx = C.getASTContext();<br><br>-    if (isFreeFunction(FD, Ctx))<br>+    if (isAllocationFunction(FD, Ctx) || isFreeFunction(FD, Ctx))<br>      return AF_Malloc;<br><br>    if (isStandardNewDelete(FD, Ctx)) {<br>      OverloadedOperatorKind Kind = FD->getOverloadedOperator();<br>-      if (Kind == OO_Delete)<br>+      if (Kind == OO_New || Kind == OO_Delete)<br>        return AF_CXXNew;<br>-      else if (Kind == OO_Array_Delete)<br>+      else if (Kind == OO_Array_New || Kind == OO_Array_Delete)<br>        return AF_CXXNewArray;<br>    }<br><br>    return AF_None;<br>  }<br><br>-  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E))<br>+  if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))<br>+    return NE->isArray() ? AF_CXXNewArray : AF_CXXNew;<br>+<br>+  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(S))<br>    return DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew;<br><br>-  if (isa<ObjCMessageExpr>(E))<br>+  if (isa<ObjCMessageExpr>(S))<br>    return AF_Malloc;<br><br>  return AF_None;<br>@@ -1003,34 +1005,39 @@ ProgramStateRef MallocChecker::FreeMemAu<br>  const RefState *RsBase = State->get<RegionState>(SymBase);<br>  SymbolRef PreviousRetStatusSymbol = 0;<br><br>-  // Check double free.<br>-  if (RsBase &&<br>-      (RsBase->isReleased() || RsBase->isRelinquished()) &&<br>-      !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {<br>-    ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),<br>-                     SymBase, PreviousRetStatusSymbol);<br>-    return 0;<br>-  }<br>+  if (RsBase) {<br><br>-  // Check if an expected deallocation function matches the real one.<br>-  if (RsBase &&<span class="Apple-converted-space"> </span><br>-      RsBase->getAllocationFamily() != AF_None &&<br>-      RsBase->getAllocationFamily() != getAllocationFamily(C, ParentExpr) ) {<br>-    ReportBadDealloc(C, ArgExpr->getSourceRange(), ParentExpr, RsBase);<br>-    return 0;<br>-  }<br>+    bool DeallocMatchesAlloc =<span class="Apple-converted-space"> </span><br>+      RsBase->getAllocationFamily() == AF_None ||<br>+      RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);<br>+<br>+    // Check if an expected deallocation function matches the real one.<br>+    if (!DeallocMatchesAlloc && RsBase->isAllocated()) {<br>+      ReportMismatchedDealloc(C, ArgExpr->getSourceRange(), ParentExpr, RsBase);<br>+      return 0;<br>+    }<br><br>-  // Check if the memory location being freed is the actual location<br>-  // allocated, or an offset.<br>-  RegionOffset Offset = R->getAsOffset();<br>-  if (RsBase && RsBase->isAllocated() &&<br>-      Offset.isValid() &&<br>-      !Offset.hasSymbolicOffset() &&<br>-      Offset.getOffset() != 0) {<br>-    const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());<br>-    ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,<span class="Apple-converted-space"> </span><br>-                     AllocExpr);<br>-    return 0;<br>+    // Check double free.<br>+    if (DeallocMatchesAlloc &&<br>+        (RsBase->isReleased() || RsBase->isRelinquished()) &&<br>+        !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {<br>+      ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),<br>+                       SymBase, PreviousRetStatusSymbol);<br>+      return 0;<br>+    }<br>+<br>+    // Check if the memory location being freed is the actual location<br>+    // allocated, or an offset.<br>+    RegionOffset Offset = R->getAsOffset();<br>+    if (RsBase->isAllocated() &&<br>+        Offset.isValid() &&<br>+        !Offset.hasSymbolicOffset() &&<br>+        Offset.getOffset() != 0) {<br>+      const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());<br>+      ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr,<span class="Apple-converted-space"> </span><br>+                       AllocExpr);<br>+      return 0;<br>+    }<br>  }<br><br>  ReleasedAllocated = (RsBase != 0);<br>@@ -1060,6 +1067,30 @@ ProgramStateRef MallocChecker::FreeMemAu<br>                                 RefState::getReleased(Family, ParentExpr));<br>}<br><br>+bool MallocChecker::isTrackedFamily(AllocationFamily Family) const {<br>+  if (Family == AF_Malloc &&<br>+    (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic))<br>+    return false;<br>+<br>+  if ((Family == AF_CXXNew || Family == AF_CXXNewArray) &&<br>+    !Filter.CNewDeleteChecker)<br>+    return false;<br>+<br>+  return true;<br>+}<br>+<br>+bool MallocChecker::isTrackedFamily(CheckerContext &C,<span class="Apple-converted-space"> </span><br>+                                    const Stmt *AllocDeallocStmt) const {<br>+  return isTrackedFamily(getAllocationFamily(C, AllocDeallocStmt));<br>+}<br>+<br>+bool MallocChecker::isTrackedFamily(CheckerContext &C, SymbolRef Sym) const {<br>+  const RefState *RS = C.getState()->get<RegionState>(Sym);<br>+<br>+  return RS ? isTrackedFamily(RS->getAllocationFamily())<span class="Apple-converted-space"> </span><br>+            : isTrackedFamily(AF_None);<br>+}<br>+<br>bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {<br>  if (Optional<nonloc::ConcreteInt> IntVal = V.getAs<nonloc::ConcreteInt>())<br>    os << "an integer (" << IntVal->getValue() << ")";<br>@@ -1155,6 +1186,9 @@ void MallocChecker::ReportBadFree(Checke<br>      !Filter.CNewDeleteChecker)<br>    return;<br><br>+  if (!isTrackedFamily(C, DeallocExpr))<br>+    return;<br>+<br>  if (ExplodedNode *N = C.generateSink()) {<br>    if (!BT_BadFree)<br>      BT_BadFree.reset(new BugType("Bad free", "Memory Error"));<br>@@ -1191,16 +1225,18 @@ void MallocChecker::ReportBadFree(Checke<br>  }<br>}<br><br>-void MallocChecker::ReportBadDealloc(CheckerContext &C, SourceRange Range,<br>-                                     const Expr *DeallocExpr,<span class="Apple-converted-space"> </span><br>-                                     const RefState *RS) const {<br>+void MallocChecker::ReportMismatchedDealloc(CheckerContext &C,<span class="Apple-converted-space"> </span><br>+                                            SourceRange Range,<br>+                                            const Expr *DeallocExpr,<span class="Apple-converted-space"> </span><br>+                                            const RefState *RS) const {<br><br>  if (!Filter.CMismatchedDeallocatorChecker)<br>    return;<br><br>  if (ExplodedNode *N = C.generateSink()) {<br>-    if (!BT_BadDealloc)<br>-      BT_BadDealloc.reset(new BugType("Bad deallocator", "Memory Error"));<br>+    if (!BT_MismatchedDealloc)<br>+      BT_MismatchedDealloc.reset(new BugType("Bad deallocator",<br>+                                             "Memory Error"));<br><br>    SmallString<100> buf;<br>    llvm::raw_svector_ostream os(buf);<br>@@ -1221,7 +1257,7 @@ void MallocChecker::ReportBadDealloc(Che<br>    if (printAllocDeallocName(DeallocOs, C, DeallocExpr))<br>      os << ", not " << DeallocOs.str();<br><br>-    BugReport *R = new BugReport(*BT_BadDealloc, os.str(), N);<br>+    BugReport *R = new BugReport(*BT_MismatchedDealloc, os.str(), N);<br>    R->addRange(Range);<br>    C.emitReport(R);<br>  }<br>@@ -1235,6 +1271,9 @@ void MallocChecker::ReportOffsetFree(Che<br>      !Filter.CNewDeleteChecker)<br>    return;<br><br>+  if (!isTrackedFamily(C, AllocExpr))<br>+    return;<br>+<br>  ExplodedNode *N = C.generateSink();<br>  if (N == NULL)<br>    return;<br>@@ -1284,6 +1323,9 @@ void MallocChecker::ReportUseAfterFree(C<br>      !Filter.CNewDeleteChecker)<br>    return;<br><br>+  if (!isTrackedFamily(C, Sym))<br>+    return;<br>+<br>  if (ExplodedNode *N = C.generateSink()) {<br>    if (!BT_UseFree)<br>      BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));<br>@@ -1306,6 +1348,9 @@ void MallocChecker::ReportDoubleFree(Che<br>      !Filter.CNewDeleteChecker)<br>    return;<br><br>+  if (!isTrackedFamily(C, Sym))<br>+    return;<br>+<br>  if (ExplodedNode *N = C.generateSink()) {<br>    if (!BT_DoubleFree)<br>      BT_DoubleFree.reset(new BugType("Double free", "Memory Error"));<br>@@ -1507,10 +1552,13 @@ void MallocChecker::reportLeak(SymbolRef<br>    AllocationStmt = Exit->getCalleeContext()->getCallSite();<br>  else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())<br>    AllocationStmt = SP->getStmt();<br>-  if (AllocationStmt)<br>+  if (AllocationStmt) {<br>    LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,<br>                                              C.getSourceManager(),<br>                                              AllocNode->getLocationContext());<br>+    if (!isTrackedFamily(C, AllocationStmt))<br>+      return;<br>+  }<br><br>  SmallString<200> buf;<br>  llvm::raw_svector_ostream os(buf);<br><br>Added: cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator%2BNewDelete.cpp?rev=178814&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator%2BNewDelete.cpp?rev=178814&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp (added)<br>+++ cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp Thu Apr  4 18:46:29 2013<br>@@ -0,0 +1,71 @@<br>+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s<br>+<br>+typedef __typeof(sizeof(int)) size_t;<br>+void *malloc(size_t);<br>+void free(void *);<br>+<br>+//--------------------------------------------------<br>+// Check that unix.Malloc catches all types of bugs.<br>+//--------------------------------------------------<br>+void testMallocDoubleFree() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+  free(p);<br>+  free(p); // expected-warning{{Attempt to free released memory}}<br>+}<br>+<br>+void testMallocLeak() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}<br>+<br>+void testMallocUseAfterFree() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+  free(p);<br>+  int j = *p; // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testMallocBadFree() {<br>+  int i;<br>+  free(&i); // expected-warning{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}}<br>+}<br>+<br>+void testMallocOffsetFree() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+  free(++p); // expected-warning{{Argument to free() is offset by 4 bytes from the start of memory allocated by malloc()}}<br>+}<br>+<br>+//-----------------------------------------------------------------<br>+// Check that unix.MismatchedDeallocator catches all types of bugs.<br>+//-----------------------------------------------------------------<br>+void testMismatchedDeallocator() {<br>+  int *x = (int *)malloc(sizeof(int));<br>+  delete x; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}}<br>+}<br>+<br>+//----------------------------------------------------------------<br>+// Check that alpha.cplusplus.NewDelete catches all types of bugs.<br>+//----------------------------------------------------------------<br>+void testNewDoubleFree() {<br>+  int *p = new int;<br>+  delete p;<br>+  delete p; // expected-warning{{Attempt to free released memory}}<br>+}<br>+<br>+void testNewLeak() {<br>+  int *p = new int;<br>+} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}<br>+<br>+void testNewUseAfterFree() {<br>+  int *p = (int *)operator new(0);<br>+  delete p;<br>+  int j = *p; // expected-warning{{Use of memory after it is freed}}<br>+}<br>+<br>+void testNewBadFree() {<br>+  int i;<br>+  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}<br>+}<br>+<br>+void testNewOffsetFree() {<br>+  int *p = new int;<br>+  operator delete(++p); // expected-warning{{Argument to operator delete is offset by 4 bytes from the start of memory allocated by 'new'}}<br>+}<br><br>Added: cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp (added)<br>+++ cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp Thu Apr  4 18:46:29 2013<br>@@ -0,0 +1,28 @@<br>+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s<br>+// expected-no-diagnostics<br>+<br>+typedef __typeof(sizeof(int)) size_t;<br>+void *malloc(size_t);<br>+void free(void *);<br>+<br>+//--------------------------------------------------------------------<br>+// Check that unix.Malloc + unix.MismatchedDeallocator does not enable<br>+// warnings produced by the alpha.cplusplus.NewDelete checker.<br>+//--------------------------------------------------------------------<br>+void testNewDeleteNoWarn() {<br>+  int i;<br>+  delete &i; // no-warning<br>+<br>+  int *p1 = new int;<br>+  delete ++p1; // no-warning<br>+<br>+  int *p2 = new int;<br>+  delete p2;<br>+  delete p2; // no-warning<br>+<br>+  int *p3 = new int; // no-warning<br>+<br>+  int *p4 = new int;<br>+  delete p4;<br>+  int j = *p4; // no-warning  <br>+}<br><br>Added: cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BNewDelete_intersections.cpp?rev=178814&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BNewDelete_intersections.cpp?rev=178814&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp (added)<br>+++ cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp Thu Apr  4 18:46:29 2013<br>@@ -0,0 +1,14 @@<br>+// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s<br>+<br>+typedef __typeof(sizeof(int)) size_t;<br>+void *malloc(size_t);<br>+void free(void *);<br>+<br>+//-------------------------------------------------------------------<br>+// Check that unix.Malloc + alpha.cplusplus.NewDelete does not enable<br>+// warnings produced by unix.MismatchedDeallocator.<br>+//-------------------------------------------------------------------<br>+void testMismatchedDeallocator() {<br>+  int *p = (int *)malloc(sizeof(int));<br>+  delete p;<br>+} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}<br><br>Added: cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp (added)<br>+++ cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp Thu Apr  4 18:46:29 2013<br>@@ -0,0 +1,28 @@<br>+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s<br>+// expected-no-diagnostics<br>+<br>+typedef __typeof(sizeof(int)) size_t;<br>+void *malloc(size_t);<br>+void free(void *);<br>+<br>+//------------------------------------------------------------------<br>+// Check that alpha.cplusplus.NewDelete + unix.MismatchedDeallocator<span class="Apple-converted-space"> </span><br>+// does not enable warnings produced by the unix.Malloc checker.<br>+//------------------------------------------------------------------<br>+void testMallocFreeNoWarn() {<br>+  int i;<br>+  free(&i); // no warn<br>+<br>+  int *p1 = (int *)malloc(sizeof(int));<br>+  free(++p1); // no warn<br>+<br>+  int *p2 = (int *)malloc(sizeof(int));<br>+  free(p2);<br>+  free(p2); // no warn<br>+<br>+  int *p3 = (int *)malloc(sizeof(int)); // no warn<br>+<br>+  int *p4 = (int *)malloc(sizeof(int));<br>+  free(p4);<br>+  int j = *p4; // no warn<br>+}<br><br>Modified: cfe/trunk/test/Analysis/NewDelete-checker-test.cpp<br>URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=178814&r1=178813&r2=178814&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=178814&r1=178813&r2=178814&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/Analysis/NewDelete-checker-test.cpp (original)<br>+++ cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Thu Apr  4 18:46:29 2013<br>@@ -1,4 +1,4 @@<br>-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s<br>+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s<br>#include "Inputs/system-header-simulator-cxx.h"<br><br>typedef __typeof__(sizeof(int)) size_t;<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a></div></blockquote></div><br></body></html>