diff options
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 21 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h | 12 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 3 | ||||
-rw-r--r-- | include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h | 16 | ||||
-rw-r--r-- | lib/Analysis/ProgramPoint.cpp | 2 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 49 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 21 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/MemRegion.cpp | 13 | ||||
-rw-r--r-- | test/Analysis/malloc-annotations.c | 8 | ||||
-rw-r--r-- | test/Analysis/malloc-interprocedural.c | 8 | ||||
-rw-r--r-- | test/Analysis/malloc-plist.c | 221 | ||||
-rw-r--r-- | test/Analysis/malloc.c | 32 |
12 files changed, 334 insertions, 72 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 78a4f8928b..413b3cf4ea 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -76,6 +76,7 @@ protected: protected: const void *getData1() const { return Data.first; } const void *getData2() const { return Data.second; } + void setData2(const void *d) { Data.second = d; } public: /// Create a new ProgramPoint object that is the same as the original @@ -195,7 +196,7 @@ public: class PostStmt : public StmtPoint { protected: PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, - const ProgramPointTag *tag =0) + const ProgramPointTag *tag = 0) : StmtPoint(S, data, k, L, tag) {} public: @@ -270,15 +271,29 @@ public: } }; +/// \class Represents a program point after a store evaluation. class PostStore : public PostStmt { public: - PostStore(const Stmt *S, const LocationContext *L, + /// Construct the post store point. + /// \param Loc can be used to store the information about the location + /// used in the form it was uttered in the code. + PostStore(const Stmt *S, const LocationContext *L, const void *Loc, const ProgramPointTag *tag = 0) - : PostStmt(S, PostStoreKind, L, tag) {} + : PostStmt(S, PostStoreKind, L, tag) { + assert(getData2() == 0); + setData2(Loc); + } static bool classof(const ProgramPoint* Location) { return Location->getKind() == PostStoreKind; } + + /// \brief Returns the information about the location used in the store, + /// how it was uttered in the code. + const void *getLocationValue() const { + return getData2(); + } + }; class PostLValue : public PostStmt { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 3bed6daf7c..052916177f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -114,6 +114,18 @@ public: return Pred->getLocationContext()->getAnalysisDeclContext(); } + /// \brief If the given node corresponds to a PostStore program point, retrieve + /// the location region as it was uttered in the code. + /// + /// This utility can be useful for generating extensive diagnostics, for + /// example, for finding variables that the given symbol was assigned to. + static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) { + ProgramPoint L = N->getLocation(); + if (const PostStore *PSL = dyn_cast<PostStore>(&L)) + return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); + return 0; + } + /// \brief Generates a new transition in the program state graph /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 52c1a2a41c..e8c4688293 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -426,8 +426,7 @@ protected: /// evalBind - Handle the semantics of binding a value to a specific location. /// This method is used by evalStore, VisitDeclStmt, and others. void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, - SVal location, SVal Val, bool atDeclInit = false, - ProgramPoint::Kind PP = ProgramPoint::PostStmtKind); + SVal location, SVal Val, bool atDeclInit = false); public: // FIXME: 'tag' should be removed, and a LocationContext should be used diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 420231ad0e..87bc0df090 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -123,8 +123,6 @@ public: virtual MemRegionManager* getMemRegionManager() const = 0; - std::string getString() const; - const MemSpaceRegion *getMemorySpace() const; const MemRegion *getBaseRegion() const; @@ -142,10 +140,16 @@ public: /// Compute the offset within the top level memory object. RegionOffset getAsOffset() const; + /// \brief Get a string representation of a region for debug use. + std::string getString() const; + virtual void dumpToStream(raw_ostream &os) const; void dump() const; + /// \brief Print the region for use in diagnostics. + virtual void dumpPretty(raw_ostream &os) const; + Kind getKind() const { return kind; } template<typename RegionTy> const RegionTy* getAs() const; @@ -814,6 +818,8 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == VarRegionKind; } + + void dumpPretty(raw_ostream &os) const; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -853,9 +859,6 @@ class FieldRegion : public DeclRegion { : DeclRegion(fd, sReg, FieldRegionKind) {} public: - - void dumpToStream(raw_ostream &os) const; - const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } QualType getValueType() const { @@ -873,6 +876,9 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == FieldRegionKind; } + + void dumpToStream(raw_ostream &os) const; + void dumpPretty(raw_ostream &os) const; }; class ObjCIvarRegion : public DeclRegion { diff --git a/lib/Analysis/ProgramPoint.cpp b/lib/Analysis/ProgramPoint.cpp index 3a0bbd5640..3f711b447a 100644 --- a/lib/Analysis/ProgramPoint.cpp +++ b/lib/Analysis/ProgramPoint.cpp @@ -34,8 +34,6 @@ ProgramPoint ProgramPoint::getProgramPoint(const Stmt *S, ProgramPoint::Kind K, return PostLoad(S, LC, tag); case ProgramPoint::PreStoreKind: return PreStore(S, LC, tag); - case ProgramPoint::PostStoreKind: - return PostStore(S, LC, tag); case ProgramPoint::PostLValueKind: return PostLValue(S, LC, tag); case ProgramPoint::PostPurgeDeadSymbolsKind: diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 99b84897a5..84366f434b 100644 --- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -82,6 +82,8 @@ struct ReallocPair { } }; +typedef std::pair<const Stmt*, const MemRegion*> LeakInfo; + class MallocChecker : public Checker<check::DeadSymbols, check::EndPath, check::PreStmt<ReturnStmt>, @@ -185,8 +187,8 @@ private: /// Find the location of the allocation for Sym on the path leading to the /// exploded node N. - const Stmt *getAllocationSite(const ExplodedNode *N, SymbolRef Sym, - CheckerContext &C) const; + LeakInfo getAllocationSite(const ExplodedNode *N, SymbolRef Sym, + CheckerContext &C) const; void reportLeak(SymbolRef Sym, ExplodedNode *N, CheckerContext &C) const; @@ -797,17 +799,32 @@ ProgramStateRef MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE){ return MallocMemAux(C, CE, TotalSize, zeroVal, state); } -const Stmt * +LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, CheckerContext &C) const { const LocationContext *LeakContext = N->getLocationContext(); // Walk the ExplodedGraph backwards and find the first node that referred to // the tracked symbol. const ExplodedNode *AllocNode = N; + const MemRegion *ReferenceRegion = 0; while (N) { - if (!N->getState()->get<RegionState>(Sym)) + ProgramStateRef State = N->getState(); + if (!State->get<RegionState>(Sym)) break; + + // Find the most recent expression bound to the symbol in the current + // context. + ProgramPoint L = N->getLocation(); + if (!ReferenceRegion) { + const MemRegion *MR = C.getLocationRegionIfPostStore(N); + if (MR) { + SVal Val = State->getSVal(MR); + if (Val.getAsLocSymbol() == Sym) + ReferenceRegion = MR; + } + } + // Allocation node, is the last node in the current context in which the // symbol was tracked. if (N->getLocationContext() == LeakContext) @@ -816,10 +833,11 @@ MallocChecker::getAllocationSite(const ExplodedNode *N, SymbolRef Sym, } ProgramPoint P = AllocNode->getLocation(); - if (!isa<StmtPoint>(P)) - return 0; + const Stmt *AllocationStmt = 0; + if (isa<StmtPoint>(P)) + AllocationStmt = cast<StmtPoint>(P).getStmt(); - return cast<StmtPoint>(P).getStmt(); + return LeakInfo(AllocationStmt, ReferenceRegion); } void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, @@ -839,12 +857,23 @@ void MallocChecker::reportLeak(SymbolRef Sym, ExplodedNode *N, // With leaks, we want to unique them by the location where they were // allocated, and only report a single path. PathDiagnosticLocation LocUsedForUniqueing; - if (const Stmt *AllocStmt = getAllocationSite(N, Sym, C)) + const Stmt *AllocStmt = 0; + const MemRegion *Region = 0; + llvm::tie(AllocStmt, Region) = getAllocationSite(N, Sym, C); + if (AllocStmt) LocUsedForUniqueing = PathDiagnosticLocation::createBegin(AllocStmt, C.getSourceManager(), N->getLocationContext()); - BugReport *R = new BugReport(*BT_Leak, - "Memory is never released; potential memory leak", N, LocUsedForUniqueing); + SmallString<200> buf; + llvm::raw_svector_ostream os(buf); + os << "Memory is never released; potential leak"; + if (Region) { + os << " of memory pointed to by '"; + Region->dumpPretty(os); + os <<'\''; + } + + BugReport *R = new BugReport(*BT_Leak, os.str(), N, LocUsedForUniqueing); R->markInteresting(Sym); // FIXME: This is a hack to make sure the MallocBugVisitor gets to look at // the ExplodedNode chain first, in order to mark any failed realloc symbols diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index fa52beea2a..a1be56426e 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1454,21 +1454,22 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, /// This method is used by evalStore and (soon) VisitDeclStmt, and others. void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred, - SVal location, SVal Val, bool atDeclInit, - ProgramPoint::Kind PointKind) { + SVal location, SVal Val, bool atDeclInit) { // Do a previsit of the bind. ExplodedNodeSet CheckedSet; getCheckerManager().runCheckersForBind(CheckedSet, Pred, location, Val, - StoreE, *this, PointKind); + StoreE, *this, + ProgramPoint::PostStmtKind); - // TODO:AZ Remove TmpDst after NB refactoring is done. ExplodedNodeSet TmpDst; StmtNodeBuilder Bldr(CheckedSet, TmpDst, *currentBuilderContext); + const LocationContext *LC = Pred->getLocationContext(); for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); I!=E; ++I) { - ProgramStateRef state = (*I)->getState(); + ExplodedNode *PredI = *I; + ProgramStateRef state = PredI->getState(); if (atDeclInit) { const VarRegion *VR = @@ -1479,7 +1480,12 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, state = state->bindLoc(location, Val); } - Bldr.generateNode(StoreE, *I, state, false, 0, PointKind); + const MemRegion *LocReg = 0; + if (loc::MemRegionVal *LocRegVal = dyn_cast<loc::MemRegionVal>(&location)) + LocReg = LocRegVal->getRegion(); + + const ProgramPoint L = PostStore(StoreE, LC, LocReg, 0); + Bldr.generateNode(L, PredI, state, false); } Dst.insert(TmpDst); @@ -1517,8 +1523,7 @@ void ExprEngine::evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, return; for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) - evalBind(Dst, StoreE, *NI, location, Val, false, - ProgramPoint::PostStoreKind); + evalBind(Dst, StoreE, *NI, location, Val, false); } void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, diff --git a/lib/StaticAnalyzer/Core/MemRegion.cpp b/lib/StaticAnalyzer/Core/MemRegion.cpp index 501fd41cdf..ed94c79df1 100644 --- a/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -534,6 +534,19 @@ void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const { os << "GlobalImmutableSpaceRegion"; } +void MemRegion::dumpPretty(raw_ostream &os) const { + return; +} + +void VarRegion::dumpPretty(raw_ostream &os) const { + os << getDecl()->getName(); +} + +void FieldRegion::dumpPretty(raw_ostream &os) const { + superRegion->dumpPretty(os); + os << "->" << getDecl(); +} + //===----------------------------------------------------------------------===// // MemRegionManager methods. //===----------------------------------------------------------------------===// diff --git a/test/Analysis/malloc-annotations.c b/test/Analysis/malloc-annotations.c index fbc6391ea5..a0c145279d 100644 --- a/test/Analysis/malloc-annotations.c +++ b/test/Analysis/malloc-annotations.c @@ -26,7 +26,7 @@ struct stuff myglobalstuff; void f1() { int *p = malloc(12); - return; // expected-warning{{Memory is never released; potential memory leak}} + return; // expected-warning{{Memory is never released; potential leak}} } void f2() { @@ -54,16 +54,16 @@ void naf1() { void n2af1() { int *p = my_malloc2(12); - return; // expected-warning{{Memory is never released; potential memory leak}} + return; // expected-warning{{Memory is never released; potential leak}} } void af1() { int *p = my_malloc(12); - return; // expected-warning{{Memory is never released; potential memory leak}} + return; // expected-warning{{Memory is never released; potential leak}} } void af1_b() { - int *p = my_malloc(12); // expected-warning{{Memory is never released; potential memory leak}} + int *p = my_malloc(12); // expected-warning{{Memory is never released; potential leak}} } void af1_c() { diff --git a/test/Analysis/malloc-interprocedural.c b/test/Analysis/malloc-interprocedural.c index eae8342795..589bc4fdef 100644 --- a/test/Analysis/malloc-interprocedural.c +++ b/test/Analysis/malloc-interprocedural.c @@ -29,7 +29,7 @@ static void my_free1(void *p) { static void test1() { void *data = 0; - my_malloc1(&data, 4); // expected-warning {{Memory is never released; potential memory leak}} + my_malloc1(&data, 4); // expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} } static void test11() { @@ -41,8 +41,8 @@ static void test11() { static void testUniqueingByallocationSiteInTopLevelFunction() { void *data = my_malloc2(1, 4); data = 0; - int x = 5;// expected-warning {{Memory is never released; potential memory leak}} - data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential memory leak}} + int x = 5;// expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} + data = my_malloc2(1, 4);// expected-warning {{Memory is never released; potential leak of memory pointed to by 'data'}} } static void test3() { @@ -79,7 +79,7 @@ static char *reshape(char *in) { void testThatRemoveDeadBindingsRunBeforeEachCall() { char *v = malloc(12); v = reshape(v); - v = reshape(v);// expected-warning {{Memory is never released; potential memory leak}} + v = reshape(v);// expected-warning {{Memory is never released; potential leak of memory pointed to by 'v'}} } // Test that we keep processing after 'return;' diff --git a/test/Analysis/malloc-plist.c b/test/Analysis/malloc-plist.c index b08c3fba48..1e8193021d 100644 --- a/test/Analysis/malloc-plist.c +++ b/test/Analysis/malloc-plist.c @@ -85,6 +85,17 @@ void use_ret() { v = malloc_wrapper_ret(); } +// Test that we refer to the last symbol used in the leak diagnostic. +void LeakedSymbol(int in) { + int *m = 0; + int *p; + p = (int*)malloc(12); + (*p)++; + m = p; + p = 0; + (*m)++; + in++; +} // CHECK: <?xml version="1.0" encoding="UTF-8"?> // CHECK: <plist version="1.0"> @@ -287,12 +298,12 @@ void use_ret() { // CHECK: </array> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'p'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'p'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'p'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -446,12 +457,12 @@ void use_ret() { // CHECK: </dict> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'A'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'A'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'A'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -843,12 +854,12 @@ void use_ret() { // CHECK: </array> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -1239,12 +1250,12 @@ void use_ret() { // CHECK: </dict> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -2327,12 +2338,12 @@ void use_ret() { // CHECK: </array> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'buf'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -2592,12 +2603,12 @@ void use_ret() { // CHECK: </dict> // CHECK: <key>depth</key><integer>0</integer> // CHECK: <key>extended_message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'v'</string> // CHECK: <key>message</key> -// CHECK: <string>Memory is never released; potential memory leak</string> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'v'</string> // CHECK: </dict> // CHECK: </array> -// CHECK: <key>description</key><string>Memory is never released; potential memory leak</string> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'v'</string> // CHECK: <key>category</key><string>Memory Error</string> // CHECK: <key>type</key><string>Memory leak</string> // CHECK: <key>location</key> @@ -2607,6 +2618,180 @@ void use_ret() { // CHECK: <key>file</key><integer>0</integer> // CHECK: </dict> // CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>path</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>kind</key><string>control</string> +// CHECK: <key>edges</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>start</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>90</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>90</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: <key>end</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>kind</key><string>control</string> +// CHECK: <key>edges</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>start</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: <key>end</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>15</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>24</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>kind</key><string>event</string> +// CHECK: <key>location</key> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>15</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <key>ranges</key> +// CHECK: <array> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>15</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>24</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </array> +// CHECK: <key>depth</key><integer>0</integer> +// CHECK: <key>extended_message</key> +// CHECK: <string>Memory is allocated</string> +// CHECK: <key>message</key> +// CHECK: <string>Memory is allocated</string> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>kind</key><string>control</string> +// CHECK: <key>edges</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>start</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>15</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>92</integer> +// CHECK: <key>col</key><integer>24</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: <key>end</key> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>8</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>kind</key><string>event</string> +// CHECK: <key>location</key> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <key>ranges</key> +// CHECK: <array> +// CHECK: <array> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>8</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </array> +// CHECK: </array> +// CHECK: <key>depth</key><integer>0</integer> +// CHECK: <key>extended_message</key> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'm'</string> +// CHECK: <key>message</key> +// CHECK: <string>Memory is never released; potential leak of memory pointed to by 'm'</string> +// CHECK: </dict> +// CHECK: </array> +// CHECK: <key>description</key><string>Memory is never released; potential leak of memory pointed to by 'm'</string> +// CHECK: <key>category</key><string>Memory Error</string> +// CHECK: <key>type</key><string>Memory leak</string> +// CHECK: <key>location</key> +// CHECK: <dict> +// CHECK: <key>line</key><integer>97</integer> +// CHECK: <key>col</key><integer>5</integer> +// CHECK: <key>file</key><integer>0</integer> +// CHECK: </dict> +// CHECK: </dict> // CHECK: </array> // CHECK: </dict> // CHECK: </plist> diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c index 0bc09ead6b..3b4712320b 100644 --- a/test/Analysis/malloc.c +++ b/test/Analysis/malloc.c @@ -15,7 +15,7 @@ char *fooRetPtr(); void f1() { int *p = malloc(12); - return; // expected-warning{{Memory is never released; potential memory leak}} + return; // expected-warning{{Memory is never released; potential leak}} } void f2() { @@ -40,7 +40,7 @@ void reallocNotNullPtr(unsigned sizeIn) { char *p = (char*)malloc(size); if (p) { char *q = (char*)realloc(p, sizeIn); - char x = *q; // expected-warning {{Memory is never released; potential memory leak}} + char x = *q; // expected-warning {{Memory is never released; potential leak}} } } @@ -98,7 +98,7 @@ void reallocSizeZero5() { } void reallocPtrZero1() { - char *r = realloc(0, 12); // expected-warning {{Memory is never released; potential memory leak}} + char *r = realloc(0, 12); // expected-warning {{Memory is never released; potential leak}} } void reallocPtrZero2() { @@ -116,7 +116,7 @@ void reallocRadar6337483_1() { char *buf = malloc(100); |