r178814 - [analyzer] Reduced the unwanted correlations between checkers living inside MallocChecker.cpp

Anna Zaks ganna at apple.com
Fri Apr 5 17:00:05 PDT 2013


On Apr 4, 2013, at 4:46 PM, Anton Yartsev <anton.yartsev at gmail.com> wrote:

> Author: ayartsev
> Date: Thu Apr  4 18:46:29 2013
> New Revision: 178814
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=178814&view=rev
> Log:
> [analyzer] Reduced the unwanted correlations between checkers living inside MallocChecker.cpp
> 
> 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.
> 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).
> 
> Additional changes: 
> improved test coverage for checker correlations;
> refactoring: BadDealloc -> MismatchedDealloc
> 
> Added:
>    cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
>    cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp
>    cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp
>    cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
> Modified:
>    cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
>    cfe/trunk/test/Analysis/NewDelete-checker-test.cpp
> 
> Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp?rev=178814&r1=178813&r2=178814&view=diff
> ==============================================================================
> --- cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp (original)
> +++ cfe/trunk/lib/StaticAnalyzer/Checkers/MallocChecker.cpp Thu Apr  4 18:46:29 2013
> @@ -149,7 +149,7 @@ class MallocChecker : public Checker<che
>   mutable OwningPtr<BugType> BT_Leak;
>   mutable OwningPtr<BugType> BT_UseFree;
>   mutable OwningPtr<BugType> BT_BadFree;
> -  mutable OwningPtr<BugType> BT_BadDealloc;
> +  mutable OwningPtr<BugType> BT_MismatchedDealloc;
>   mutable OwningPtr<BugType> BT_OffsetFree;
>   mutable IdentifierInfo *II_malloc, *II_free, *II_realloc, *II_calloc,
>                          *II_valloc, *II_reallocf, *II_strndup, *II_strdup;
> @@ -198,7 +198,7 @@ private:
>   void initIdentifierInfo(ASTContext &C) const;
> 
>   /// \brief Determine family of a deallocation expression.
> -  AllocationFamily getAllocationFamily(CheckerContext &C, const Expr *E) const;
> +  AllocationFamily getAllocationFamily(CheckerContext &C, const Stmt *S) const;
> 
>   /// \brief Print names of allocators and deallocators.
>   ///
> @@ -282,12 +282,19 @@ private:
>                                   PointerEscapeKind Kind,
>                                   bool(*CheckRefState)(const RefState*)) const;
> 
> +  // Used to suppress warnings if they are not related to the tracked family
> +  // (derived from AllocDeallocStmt).

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?".

Also, let's try to stick to doxygen comments.


> +  bool isTrackedFamily(AllocationFamily Family) const;
> +  bool isTrackedFamily(CheckerContext &C, const Stmt *AllocDeallocStmt) const;
> +  bool isTrackedFamily(CheckerContext &C, SymbolRef Sym) const;
> +
>   static bool SummarizeValue(raw_ostream &os, SVal V);
>   static bool SummarizeRegion(raw_ostream &os, const MemRegion *MR);
>   void ReportBadFree(CheckerContext &C, SVal ArgVal, SourceRange Range, 
>                      const Expr *DeallocExpr) const;
> -  void ReportBadDealloc(CheckerContext &C, SourceRange Range,
> -                        const Expr *DeallocExpr, const RefState *RS) const;
> +  void ReportMismatchedDealloc(CheckerContext &C, SourceRange Range,
> +                               const Expr *DeallocExpr, 
> +                               const RefState *RS) const;
>   void ReportOffsetFree(CheckerContext &C, SVal ArgVal, SourceRange Range, 
>                         const Expr *DeallocExpr, 
>                         const Expr *AllocExpr = 0) const;
> @@ -558,45 +565,39 @@ void MallocChecker::checkPostStmt(const
>     initIdentifierInfo(C.getASTContext());
>     IdentifierInfo *FunI = FD->getIdentifier();
> 
> -    if (Filter.CMallocOptimistic || Filter.CMallocPessimistic ||
> -        Filter.CMismatchedDeallocatorChecker) {
> -      if (FunI == II_malloc || FunI == II_valloc) {
> -        if (CE->getNumArgs() < 1)
> -          return;
> -        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
> -      } else if (FunI == II_realloc) {
> -        State = ReallocMem(C, CE, false);
> -      } else if (FunI == II_reallocf) {
> -        State = ReallocMem(C, CE, true);
> -      } else if (FunI == II_calloc) {
> -        State = CallocMem(C, CE);
> -      } else if (FunI == II_free) {
> -        State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
> -      } else if (FunI == II_strdup) {
> -        State = MallocUpdateRefState(C, CE, State);
> -      } else if (FunI == II_strndup) {
> -        State = MallocUpdateRefState(C, CE, State);
> -      }
> +    if (FunI == II_malloc || FunI == II_valloc) {
> +      if (CE->getNumArgs() < 1)
> +        return;
> +      State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State);
> +    } else if (FunI == II_realloc) {
> +      State = ReallocMem(C, CE, false);
> +    } else if (FunI == II_reallocf) {
> +      State = ReallocMem(C, CE, true);
> +    } else if (FunI == II_calloc) {
> +      State = CallocMem(C, CE);
> +    } else if (FunI == II_free) {
> +      State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
> +    } else if (FunI == II_strdup) {
> +      State = MallocUpdateRefState(C, CE, State);
> +    } else if (FunI == II_strndup) {
> +      State = MallocUpdateRefState(C, CE, State);
>     }
> -
> -    if (Filter.CNewDeleteChecker || Filter.CMismatchedDeallocatorChecker) {
> -      if (isStandardNewDelete(FD, C.getASTContext())) {
> -        // Process direct calls to operator new/new[]/delete/delete[] functions
> -        // as distinct from new/new[]/delete/delete[] expressions that are 
> -        // processed by the checkPostStmt callbacks for CXXNewExpr and 
> -        // CXXDeleteExpr.
> -        OverloadedOperatorKind K = FD->getOverloadedOperator();
> -        if (K == OO_New)
> -          State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
> -                               AF_CXXNew);
> -        else if (K == OO_Array_New)
> -          State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
> -                               AF_CXXNewArray);
> -        else if (K == OO_Delete || K == OO_Array_Delete)
> -          State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
> -        else
> -          llvm_unreachable("not a new/delete operator");
> -      }
> +    else if (isStandardNewDelete(FD, C.getASTContext())) {
> +      // Process direct calls to operator new/new[]/delete/delete[] functions
> +      // as distinct from new/new[]/delete/delete[] expressions that are 
> +      // processed by the checkPostStmt callbacks for CXXNewExpr and 
> +      // CXXDeleteExpr.
> +      OverloadedOperatorKind K = FD->getOverloadedOperator();
> +      if (K == OO_New)
> +        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
> +                             AF_CXXNew);
> +      else if (K == OO_Array_New)
> +        State = MallocMemAux(C, CE, CE->getArg(0), UndefinedVal(), State,
> +                             AF_CXXNewArray);
> +      else if (K == OO_Delete || K == OO_Array_Delete)
> +        State = FreeMemAux(C, CE, State, 0, false, ReleasedAllocatedMemory);
> +      else
> +        llvm_unreachable("not a new/delete operator");
>     }
>   }
> 
> @@ -631,9 +632,6 @@ void MallocChecker::checkPostStmt(const
>       if (SymbolRef Sym = C.getSVal(*I).getAsSymbol())
>         checkUseAfterFree(Sym, C, *I);
> 
> -  if (!Filter.CNewDeleteChecker && !Filter.CMismatchedDeallocatorChecker)
> -    return;
> -
>   if (!isStandardNewDelete(NE->getOperatorNew(), C.getASTContext()))
>     return;
> 
> @@ -654,9 +652,6 @@ void MallocChecker::checkPreStmt(const C
>     if (SymbolRef Sym = C.getSVal(DE->getArgument()).getAsSymbol())
>       checkUseAfterFree(Sym, C, DE->getArgument());
> 
> -  if (!Filter.CNewDeleteChecker && !Filter.CMismatchedDeallocatorChecker)
> -    return;
> -
>   if (!isStandardNewDelete(DE->getOperatorDelete(), C.getASTContext()))
>     return;
> 
> @@ -838,32 +833,39 @@ static bool didPreviousFreeFail(ProgramS
> }
> 
> AllocationFamily MallocChecker::getAllocationFamily(CheckerContext &C, 
> -                                                    const Expr *E) const {
> -  if (!E)
> +                                                    const Stmt *S) const {
> +  if (!S)
>     return AF_None;
> 
> -  if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
> +  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
>     const FunctionDecl *FD = C.getCalleeDecl(CE);
> +
> +    if (!FD)
> +      FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
> +
>     ASTContext &Ctx = C.getASTContext();
> 
> -    if (isFreeFunction(FD, Ctx))
> +    if (isAllocationFunction(FD, Ctx) || isFreeFunction(FD, Ctx))
>       return AF_Malloc;
> 
>     if (isStandardNewDelete(FD, Ctx)) {
>       OverloadedOperatorKind Kind = FD->getOverloadedOperator();
> -      if (Kind == OO_Delete)
> +      if (Kind == OO_New || Kind == OO_Delete)
>         return AF_CXXNew;
> -      else if (Kind == OO_Array_Delete)
> +      else if (Kind == OO_Array_New || Kind == OO_Array_Delete)
>         return AF_CXXNewArray;
>     }
> 
>     return AF_None;
>   }
> 
> -  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(E))
> +  if (const CXXNewExpr *NE = dyn_cast<CXXNewExpr>(S))
> +    return NE->isArray() ? AF_CXXNewArray : AF_CXXNew;
> +
> +  if (const CXXDeleteExpr *DE = dyn_cast<CXXDeleteExpr>(S))
>     return DE->isArrayForm() ? AF_CXXNewArray : AF_CXXNew;
> 
> -  if (isa<ObjCMessageExpr>(E))
> +  if (isa<ObjCMessageExpr>(S))
>     return AF_Malloc;
> 
>   return AF_None;
> @@ -1003,34 +1005,39 @@ ProgramStateRef MallocChecker::FreeMemAu
>   const RefState *RsBase = State->get<RegionState>(SymBase);
>   SymbolRef PreviousRetStatusSymbol = 0;
> 
> -  // Check double free.
> -  if (RsBase &&
> -      (RsBase->isReleased() || RsBase->isRelinquished()) &&
> -      !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
> -    ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
> -                     SymBase, PreviousRetStatusSymbol);
> -    return 0;
> -  }
> +  if (RsBase) {
> 
> -  // Check if an expected deallocation function matches the real one.
> -  if (RsBase && 
> -      RsBase->getAllocationFamily() != AF_None &&
> -      RsBase->getAllocationFamily() != getAllocationFamily(C, ParentExpr) ) {
> -    ReportBadDealloc(C, ArgExpr->getSourceRange(), ParentExpr, RsBase);
> -    return 0;
> -  }
> +    bool DeallocMatchesAlloc = 
> +      RsBase->getAllocationFamily() == AF_None ||
> +      RsBase->getAllocationFamily() == getAllocationFamily(C, ParentExpr);
> +
> +    // Check if an expected deallocation function matches the real one.
> +    if (!DeallocMatchesAlloc && RsBase->isAllocated()) {
> +      ReportMismatchedDealloc(C, ArgExpr->getSourceRange(), ParentExpr, RsBase);
> +      return 0;
> +    }
> 
> -  // Check if the memory location being freed is the actual location
> -  // allocated, or an offset.
> -  RegionOffset Offset = R->getAsOffset();
> -  if (RsBase && RsBase->isAllocated() &&
> -      Offset.isValid() &&
> -      !Offset.hasSymbolicOffset() &&
> -      Offset.getOffset() != 0) {
> -    const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
> -    ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, 
> -                     AllocExpr);
> -    return 0;
> +    // Check double free.
> +    if (DeallocMatchesAlloc &&
> +        (RsBase->isReleased() || RsBase->isRelinquished()) &&
> +        !didPreviousFreeFail(State, SymBase, PreviousRetStatusSymbol)) {
> +      ReportDoubleFree(C, ParentExpr->getSourceRange(), RsBase->isReleased(),
> +                       SymBase, PreviousRetStatusSymbol);
> +      return 0;
> +    }
> +
> +    // Check if the memory location being freed is the actual location
> +    // allocated, or an offset.
> +    RegionOffset Offset = R->getAsOffset();
> +    if (RsBase->isAllocated() &&
> +        Offset.isValid() &&
> +        !Offset.hasSymbolicOffset() &&
> +        Offset.getOffset() != 0) {
> +      const Expr *AllocExpr = cast<Expr>(RsBase->getStmt());
> +      ReportOffsetFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr, 
> +                       AllocExpr);
> +      return 0;
> +    }
>   }
> 
>   ReleasedAllocated = (RsBase != 0);
> @@ -1060,6 +1067,30 @@ ProgramStateRef MallocChecker::FreeMemAu
>                                  RefState::getReleased(Family, ParentExpr));
> }
> 
> +bool MallocChecker::isTrackedFamily(AllocationFamily Family) const {
> +  if (Family == AF_Malloc &&
> +    (!Filter.CMallocOptimistic && !Filter.CMallocPessimistic))
> +    return false;
> +
> +  if ((Family == AF_CXXNew || Family == AF_CXXNewArray) &&
> +    !Filter.CNewDeleteChecker)
> +    return false;
> +
> +  return true;
> +}
> +
> +bool MallocChecker::isTrackedFamily(CheckerContext &C, 
> +                                    const Stmt *AllocDeallocStmt) const {
> +  return isTrackedFamily(getAllocationFamily(C, AllocDeallocStmt));
> +}
> +
> +bool MallocChecker::isTrackedFamily(CheckerContext &C, SymbolRef Sym) const {
> +  const RefState *RS = C.getState()->get<RegionState>(Sym);
> +
> +  return RS ? isTrackedFamily(RS->getAllocationFamily()) 
> +            : isTrackedFamily(AF_None);
> +}
> +
> bool MallocChecker::SummarizeValue(raw_ostream &os, SVal V) {
>   if (Optional<nonloc::ConcreteInt> IntVal = V.getAs<nonloc::ConcreteInt>())
>     os << "an integer (" << IntVal->getValue() << ")";
> @@ -1155,6 +1186,9 @@ void MallocChecker::ReportBadFree(Checke
>       !Filter.CNewDeleteChecker)
>     return;
> 
> +  if (!isTrackedFamily(C, DeallocExpr))
> +    return;
> +
>   if (ExplodedNode *N = C.generateSink()) {
>     if (!BT_BadFree)
>       BT_BadFree.reset(new BugType("Bad free", "Memory Error"));
> @@ -1191,16 +1225,18 @@ void MallocChecker::ReportBadFree(Checke
>   }
> }
> 
> -void MallocChecker::ReportBadDealloc(CheckerContext &C, SourceRange Range,
> -                                     const Expr *DeallocExpr, 
> -                                     const RefState *RS) const {
> +void MallocChecker::ReportMismatchedDealloc(CheckerContext &C, 
> +                                            SourceRange Range,
> +                                            const Expr *DeallocExpr, 
> +                                            const RefState *RS) const {
> 
>   if (!Filter.CMismatchedDeallocatorChecker)
>     return;
> 
>   if (ExplodedNode *N = C.generateSink()) {
> -    if (!BT_BadDealloc)
> -      BT_BadDealloc.reset(new BugType("Bad deallocator", "Memory Error"));
> +    if (!BT_MismatchedDealloc)
> +      BT_MismatchedDealloc.reset(new BugType("Bad deallocator",
> +                                             "Memory Error"));
> 
>     SmallString<100> buf;
>     llvm::raw_svector_ostream os(buf);
> @@ -1221,7 +1257,7 @@ void MallocChecker::ReportBadDealloc(Che
>     if (printAllocDeallocName(DeallocOs, C, DeallocExpr))
>       os << ", not " << DeallocOs.str();
> 
> -    BugReport *R = new BugReport(*BT_BadDealloc, os.str(), N);
> +    BugReport *R = new BugReport(*BT_MismatchedDealloc, os.str(), N);
>     R->addRange(Range);
>     C.emitReport(R);
>   }
> @@ -1235,6 +1271,9 @@ void MallocChecker::ReportOffsetFree(Che
>       !Filter.CNewDeleteChecker)
>     return;
> 
> +  if (!isTrackedFamily(C, AllocExpr))
> +    return;
> +
>   ExplodedNode *N = C.generateSink();
>   if (N == NULL)
>     return;
> @@ -1284,6 +1323,9 @@ void MallocChecker::ReportUseAfterFree(C
>       !Filter.CNewDeleteChecker)
>     return;
> 
> +  if (!isTrackedFamily(C, Sym))
> +    return;
> +
>   if (ExplodedNode *N = C.generateSink()) {
>     if (!BT_UseFree)
>       BT_UseFree.reset(new BugType("Use-after-free", "Memory Error"));
> @@ -1306,6 +1348,9 @@ void MallocChecker::ReportDoubleFree(Che
>       !Filter.CNewDeleteChecker)
>     return;
> 
> +  if (!isTrackedFamily(C, Sym))
> +    return;
> +
>   if (ExplodedNode *N = C.generateSink()) {
>     if (!BT_DoubleFree)
>       BT_DoubleFree.reset(new BugType("Double free", "Memory Error"));
> @@ -1507,10 +1552,13 @@ void MallocChecker::reportLeak(SymbolRef
>     AllocationStmt = Exit->getCalleeContext()->getCallSite();
>   else if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
>     AllocationStmt = SP->getStmt();
> -  if (AllocationStmt)
> +  if (AllocationStmt) {
>     LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocationStmt,
>                                               C.getSourceManager(),
>                                               AllocNode->getLocationContext());
> +    if (!isTrackedFamily(C, AllocationStmt))
> +      return;
> +  }
> 
>   SmallString<200> buf;
>   llvm::raw_svector_ostream os(buf);
> 
> Added: cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator%2BNewDelete.cpp?rev=178814&view=auto
> ==============================================================================
> --- cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp (added)
> +++ cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator+NewDelete.cpp Thu Apr  4 18:46:29 2013
> @@ -0,0 +1,71 @@
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
> +
> +typedef __typeof(sizeof(int)) size_t;
> +void *malloc(size_t);
> +void free(void *);
> +
> +//--------------------------------------------------
> +// Check that unix.Malloc catches all types of bugs.
> +//--------------------------------------------------
> +void testMallocDoubleFree() {
> +  int *p = (int *)malloc(sizeof(int));
> +  free(p);
> +  free(p); // expected-warning{{Attempt to free released memory}}
> +}
> +
> +void testMallocLeak() {
> +  int *p = (int *)malloc(sizeof(int));
> +} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
> +
> +void testMallocUseAfterFree() {
> +  int *p = (int *)malloc(sizeof(int));
> +  free(p);
> +  int j = *p; // expected-warning{{Use of memory after it is freed}}
> +}
> +
> +void testMallocBadFree() {
> +  int i;
> +  free(&i); // expected-warning{{Argument to free() is the address of the local variable 'i', which is not memory allocated by malloc()}}
> +}
> +
> +void testMallocOffsetFree() {
> +  int *p = (int *)malloc(sizeof(int));
> +  free(++p); // expected-warning{{Argument to free() is offset by 4 bytes from the start of memory allocated by malloc()}}
> +}
> +
> +//-----------------------------------------------------------------
> +// Check that unix.MismatchedDeallocator catches all types of bugs.
> +//-----------------------------------------------------------------
> +void testMismatchedDeallocator() {
> +  int *x = (int *)malloc(sizeof(int));
> +  delete x; // expected-warning{{Memory allocated by malloc() should be deallocated by free(), not 'delete'}}
> +}
> +
> +//----------------------------------------------------------------
> +// Check that alpha.cplusplus.NewDelete catches all types of bugs.
> +//----------------------------------------------------------------
> +void testNewDoubleFree() {
> +  int *p = new int;
> +  delete p;
> +  delete p; // expected-warning{{Attempt to free released memory}}
> +}
> +
> +void testNewLeak() {
> +  int *p = new int;
> +} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
> +
> +void testNewUseAfterFree() {
> +  int *p = (int *)operator new(0);
> +  delete p;
> +  int j = *p; // expected-warning{{Use of memory after it is freed}}
> +}
> +
> +void testNewBadFree() {
> +  int i;
> +  delete &i; // expected-warning{{Argument to 'delete' is the address of the local variable 'i', which is not memory allocated by 'new'}}
> +}
> +
> +void testNewOffsetFree() {
> +  int *p = new int;
> +  operator delete(++p); // expected-warning{{Argument to operator delete is offset by 4 bytes from the start of memory allocated by 'new'}}
> +}
> 
> Added: cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto
> ==============================================================================
> --- cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp (added)
> +++ cfe/trunk/test/Analysis/Malloc+MismatchedDeallocator_intersections.cpp Thu Apr  4 18:46:29 2013
> @@ -0,0 +1,28 @@
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s
> +// expected-no-diagnostics
> +
> +typedef __typeof(sizeof(int)) size_t;
> +void *malloc(size_t);
> +void free(void *);
> +
> +//--------------------------------------------------------------------
> +// Check that unix.Malloc + unix.MismatchedDeallocator does not enable
> +// warnings produced by the alpha.cplusplus.NewDelete checker.
> +//--------------------------------------------------------------------
> +void testNewDeleteNoWarn() {
> +  int i;
> +  delete &i; // no-warning
> +
> +  int *p1 = new int;
> +  delete ++p1; // no-warning
> +
> +  int *p2 = new int;
> +  delete p2;
> +  delete p2; // no-warning
> +
> +  int *p3 = new int; // no-warning
> +
> +  int *p4 = new int;
> +  delete p4;
> +  int j = *p4; // no-warning  
> +}
> 
> Added: cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/Malloc%2BNewDelete_intersections.cpp?rev=178814&view=auto
> ==============================================================================
> --- cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp (added)
> +++ cfe/trunk/test/Analysis/Malloc+NewDelete_intersections.cpp Thu Apr  4 18:46:29 2013
> @@ -0,0 +1,14 @@
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core,unix.Malloc,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -verify %s
> +
> +typedef __typeof(sizeof(int)) size_t;
> +void *malloc(size_t);
> +void free(void *);
> +
> +//-------------------------------------------------------------------
> +// Check that unix.Malloc + alpha.cplusplus.NewDelete does not enable
> +// warnings produced by unix.MismatchedDeallocator.
> +//-------------------------------------------------------------------
> +void testMismatchedDeallocator() {
> +  int *p = (int *)malloc(sizeof(int));
> +  delete p;
> +} // expected-warning{{Memory is never released; potential leak of memory pointed to by 'p'}}
> 
> Added: cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete%2BMismatchedDeallocator_intersections.cpp?rev=178814&view=auto
> ==============================================================================
> --- cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp (added)
> +++ cfe/trunk/test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp Thu Apr  4 18:46:29 2013
> @@ -0,0 +1,28 @@
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.MismatchedDeallocator -analyzer-store region -std=c++11 -verify %s
> +// expected-no-diagnostics
> +
> +typedef __typeof(sizeof(int)) size_t;
> +void *malloc(size_t);
> +void free(void *);
> +
> +//------------------------------------------------------------------
> +// Check that alpha.cplusplus.NewDelete + unix.MismatchedDeallocator 
> +// does not enable warnings produced by the unix.Malloc checker.
> +//------------------------------------------------------------------
> +void testMallocFreeNoWarn() {
> +  int i;
> +  free(&i); // no warn
> +
> +  int *p1 = (int *)malloc(sizeof(int));
> +  free(++p1); // no warn
> +
> +  int *p2 = (int *)malloc(sizeof(int));
> +  free(p2);
> +  free(p2); // no warn
> +
> +  int *p3 = (int *)malloc(sizeof(int)); // no warn
> +
> +  int *p4 = (int *)malloc(sizeof(int));
> +  free(p4);
> +  int j = *p4; // no warn
> +}
> 
> Modified: cfe/trunk/test/Analysis/NewDelete-checker-test.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/NewDelete-checker-test.cpp?rev=178814&r1=178813&r2=178814&view=diff
> ==============================================================================
> --- cfe/trunk/test/Analysis/NewDelete-checker-test.cpp (original)
> +++ cfe/trunk/test/Analysis/NewDelete-checker-test.cpp Thu Apr  4 18:46:29 2013
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete,unix.Malloc -analyzer-store region -std=c++11 -fblocks -verify %s
> +// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.cplusplus.NewDelete -analyzer-store region -std=c++11 -fblocks -verify %s
> #include "Inputs/system-header-simulator-cxx.h"
> 
> typedef __typeof__(sizeof(int)) size_t;
> 
> 
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130405/26659ca4/attachment.html>


More information about the cfe-commits mailing list