@@ -1096,7 +1096,7 @@ class VISIBILITY_HIDDEN RefVal {
1096
1096
1097
1097
static bool isError (Kind k) { return k >= ErrorUseAfterRelease; }
1098
1098
1099
- static bool isLeak (Kind k) { return k = = ErrorLeak; }
1099
+ static bool isLeak (Kind k) { return k > = ErrorLeak; }
1100
1100
1101
1101
bool isOwned () const {
1102
1102
return getKind () == Owned;
@@ -1266,7 +1266,8 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
1266
1266
1267
1267
typedef ReleasesNotOwnedTy UseAfterReleasesTy;
1268
1268
1269
- typedef llvm::DenseMap<GRExprEngine::NodeTy*, std::vector<SymbolID>*>
1269
+ typedef llvm::DenseMap<GRExprEngine::NodeTy*,
1270
+ std::vector<std::pair<SymbolID,bool > >*>
1270
1271
LeaksTy;
1271
1272
1272
1273
class BindingsPrinter : public GRState ::Printer {
@@ -1302,9 +1303,9 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals {
1302
1303
const GRState* St,
1303
1304
RefVal::Kind hasErr, SymbolID Sym);
1304
1305
1305
- const GRState* HandleSymbolDeath (GRStateManager& VMgr, const GRState* St,
1306
- const Decl* CD, SymbolID sid, RefVal V ,
1307
- bool & hasLeak);
1306
+ std::pair<GRStateRef, bool >
1307
+ HandleSymbolDeath (GRStateManager& VMgr, const GRState* St ,
1308
+ const Decl* CD, SymbolID sid, RefVal V, bool & hasLeak);
1308
1309
1309
1310
public:
1310
1311
@@ -1508,6 +1509,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
1508
1509
1509
1510
// Get the state.
1510
1511
GRStateRef state (Builder.GetState (Pred), Eng.getStateManager ());
1512
+ ASTContext& Ctx = Eng.getStateManager ().getContext ();
1511
1513
1512
1514
// Evaluate the effect of the arguments.
1513
1515
RefVal::Kind hasErr = (RefVal::Kind) 0 ;
@@ -1560,7 +1562,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
1560
1562
if (R) {
1561
1563
// Set the value of the variable to be a conjured symbol.
1562
1564
unsigned Count = Builder.getCurrentBlockCount ();
1563
- QualType T = R->getType ();
1565
+ QualType T = R->getType (Ctx );
1564
1566
1565
1567
// FIXME: handle structs.
1566
1568
if (T->isIntegerType () || Loc::IsLocType (T)) {
@@ -1743,7 +1745,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
1743
1745
}
1744
1746
1745
1747
Summ = Summaries.getMethodSummary (ME, ID);
1746
- # if 0
1748
+
1747
1749
// Special-case: are we sending a mesage to "self"?
1748
1750
// This is a hack. When we have full-IP this should be removed.
1749
1751
if (!Summ) {
@@ -1754,17 +1756,15 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst,
1754
1756
if (Expr* Receiver = ME->getReceiver ()) {
1755
1757
SVal X = Eng.getStateManager ().GetSVal (St, Receiver);
1756
1758
if (loc::MemRegionVal* L = dyn_cast<loc::MemRegionVal>(&X))
1757
- if (const VarRegion* R = dyn_cast<VarRegion>(L->getRegion()))
1758
- if (R->getDecl() == MD->getSelfDecl()) {
1759
- // Create a summmary where all of the arguments "StopTracking".
1760
- Summ = Summaries.getPersistentSummary(RetEffect::MakeNoRet(),
1761
- DoNothing,
1762
- StopTracking);
1763
- }
1759
+ if (L->getRegion () == Eng.getStateManager ().getSelfRegion (St)) {
1760
+ // Create a summmary where all of the arguments "StopTracking".
1761
+ Summ = Summaries.getPersistentSummary (RetEffect::MakeNoRet (),
1762
+ DoNothing,
1763
+ StopTracking);
1764
+ }
1764
1765
}
1765
1766
}
1766
1767
}
1767
- #endif
1768
1768
}
1769
1769
else
1770
1770
Summ = Summaries.getClassMethodSummary (ME->getClassName (),
@@ -1846,42 +1846,41 @@ void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst,
1846
1846
// or autorelease. Any other time you receive an object, you must
1847
1847
// not release it."
1848
1848
//
1849
- #if 0
1850
1849
static bool followsFundamentalRule (const char * s) {
1851
1850
return CStrInCStrNoCase (s, " create" ) || CStrInCStrNoCase (s, " copy" ) ||
1852
1851
CStrInCStrNoCase (s, " new" );
1853
1852
}
1854
- #endif
1855
1853
1856
- const GRState* CFRefCount::HandleSymbolDeath (GRStateManager& VMgr,
1857
- const GRState* St, const Decl* CD,
1858
- SymbolID sid,
1859
- RefVal V, bool & hasLeak) {
1854
+ std::pair<GRStateRef,bool >
1855
+ CFRefCount::HandleSymbolDeath (GRStateManager& VMgr,
1856
+ const GRState* St, const Decl* CD,
1857
+ SymbolID sid,
1858
+ RefVal V, bool & hasLeak) {
1860
1859
1861
1860
GRStateRef state (St, VMgr);
1862
1861
assert (!V.isReturnedOwned () || CD &&
1863
1862
" CodeDecl must be available for reporting ReturnOwned errors." );
1864
1863
1865
- #if 0
1866
1864
if (V.isReturnedOwned () && V.getCount () == 0 )
1867
1865
if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
1868
1866
std::string s = MD->getSelector ().getName ();
1869
1867
if (!followsFundamentalRule (s.c_str ())) {
1870
1868
hasLeak = true ;
1871
- return state.set<RefBindings>(sid, V ^ RefVal::ErrorLeakReturned);
1869
+ state = state.set <RefBindings>(sid, V ^ RefVal::ErrorLeakReturned);
1870
+ return std::make_pair (state, true );
1872
1871
}
1873
1872
}
1874
- #endif
1875
1873
1876
1874
// All other cases.
1877
1875
1878
1876
hasLeak = V.isOwned () ||
1879
1877
((V.isNotOwned () || V.isReturnedOwned ()) && V.getCount () > 0 );
1880
1878
1881
1879
if (!hasLeak)
1882
- return state.remove <RefBindings>(sid);
1880
+ return std::make_pair ( state.remove <RefBindings>(sid), false );
1883
1881
1884
- return state.set <RefBindings>(sid, V ^ RefVal::ErrorLeak);
1882
+ return std::make_pair (state.set <RefBindings>(sid, V ^ RefVal::ErrorLeak),
1883
+ false );
1885
1884
}
1886
1885
1887
1886
void CFRefCount::EvalEndPath (GRExprEngine& Eng,
@@ -1890,16 +1889,18 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
1890
1889
const GRState* St = Builder.getState ();
1891
1890
RefBindings B = St->get <RefBindings>();
1892
1891
1893
- llvm::SmallVector<SymbolID, 10 > Leaked;
1892
+ llvm::SmallVector<std::pair< SymbolID, bool > , 10 > Leaked;
1894
1893
const Decl* CodeDecl = &Eng.getGraph ().getCodeDecl ();
1895
1894
1896
1895
for (RefBindings::iterator I = B.begin (), E = B.end (); I != E; ++I) {
1897
1896
bool hasLeak = false ;
1898
1897
1899
- St = HandleSymbolDeath (Eng.getStateManager (), St, CodeDecl,
1900
- (*I).first , (*I).second , hasLeak);
1898
+ std::pair<GRStateRef, bool > X =
1899
+ HandleSymbolDeath (Eng.getStateManager (), St, CodeDecl,
1900
+ (*I).first , (*I).second , hasLeak);
1901
1901
1902
- if (hasLeak) Leaked.push_back ((*I).first );
1902
+ St = X.first ;
1903
+ if (hasLeak) Leaked.push_back (std::make_pair ((*I).first , X.second ));
1903
1904
}
1904
1905
1905
1906
if (Leaked.empty ())
@@ -1910,12 +1911,12 @@ void CFRefCount::EvalEndPath(GRExprEngine& Eng,
1910
1911
if (!N)
1911
1912
return ;
1912
1913
1913
- std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1914
+ std::vector<std::pair< SymbolID, bool > >*& LeaksAtNode = Leaks[N];
1914
1915
assert (!LeaksAtNode);
1915
- LeaksAtNode = new std::vector<SymbolID>();
1916
+ LeaksAtNode = new std::vector<std::pair< SymbolID, bool > >();
1916
1917
1917
- for (llvm::SmallVector<SymbolID, 10 >::iterator I=Leaked. begin (),
1918
- E = Leaked.end (); I != E; ++I)
1918
+ for (llvm::SmallVector<std::pair< SymbolID,bool >, 10 >::iterator
1919
+ I = Leaked. begin (), E = Leaked.end (); I != E; ++I)
1919
1920
(*LeaksAtNode).push_back (*I);
1920
1921
}
1921
1922
@@ -1932,7 +1933,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
1932
1933
// FIXME: a lot of copy-and-paste from EvalEndPath. Refactor.
1933
1934
1934
1935
RefBindings B = St->get <RefBindings>();
1935
- llvm::SmallVector<SymbolID, 10 > Leaked;
1936
+ llvm::SmallVector<std::pair< SymbolID, bool > , 10 > Leaked;
1936
1937
1937
1938
for (GRStateManager::DeadSymbolsTy::const_iterator
1938
1939
I=Dead.begin (), E=Dead.end (); I!=E; ++I) {
@@ -1944,10 +1945,13 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
1944
1945
1945
1946
bool hasLeak = false ;
1946
1947
1947
- St = HandleSymbolDeath (Eng.getStateManager (), St, 0 , *I, *T, hasLeak);
1948
+ std::pair<GRStateRef, bool > X
1949
+ = HandleSymbolDeath (Eng.getStateManager (), St, 0 , *I, *T, hasLeak);
1950
+
1951
+ St = X.first ;
1948
1952
1949
1953
if (hasLeak)
1950
- Leaked.push_back (*I );
1954
+ Leaked.push_back (std::make_pair (*I,X. second ) );
1951
1955
}
1952
1956
1953
1957
if (Leaked.empty ())
@@ -1958,12 +1962,12 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<GRState>& Dst,
1958
1962
if (!N)
1959
1963
return ;
1960
1964
1961
- std::vector<SymbolID>*& LeaksAtNode = Leaks[N];
1965
+ std::vector<std::pair< SymbolID, bool > >*& LeaksAtNode = Leaks[N];
1962
1966
assert (!LeaksAtNode);
1963
- LeaksAtNode = new std::vector<SymbolID>();
1967
+ LeaksAtNode = new std::vector<std::pair< SymbolID, bool > >();
1964
1968
1965
- for (llvm::SmallVector<SymbolID, 10 >::iterator I=Leaked. begin (),
1966
- E = Leaked.end (); I != E; ++I)
1969
+ for (llvm::SmallVector<std::pair< SymbolID,bool >, 10 >::iterator
1970
+ I = Leaked. begin (), E = Leaked.end (); I != E; ++I)
1967
1971
(*LeaksAtNode).push_back (*I);
1968
1972
}
1969
1973
@@ -2196,19 +2200,34 @@ namespace {
2196
2200
};
2197
2201
2198
2202
class VISIBILITY_HIDDEN Leak : public CFRefBug {
2203
+ bool isReturn;
2199
2204
public:
2200
2205
Leak (CFRefCount& tf) : CFRefBug(tf) {}
2201
2206
2207
+ void setIsReturn (bool x) { isReturn = x; }
2208
+
2202
2209
virtual const char * getName () const {
2203
2210
2204
- if (getTF ().isGCEnabled ())
2205
- return " leak (GC)" ;
2206
-
2207
- if (getTF ().getLangOptions ().getGCMode () == LangOptions::HybridGC)
2208
- return " leak (hybrid MM, non-GC)" ;
2209
-
2210
- assert (getTF ().getLangOptions ().getGCMode () == LangOptions::NonGC);
2211
- return " leak" ;
2211
+ if (!isReturn) {
2212
+ if (getTF ().isGCEnabled ())
2213
+ return " leak (GC)" ;
2214
+
2215
+ if (getTF ().getLangOptions ().getGCMode () == LangOptions::HybridGC)
2216
+ return " leak (hybrid MM, non-GC)" ;
2217
+
2218
+ assert (getTF ().getLangOptions ().getGCMode () == LangOptions::NonGC);
2219
+ return " leak" ;
2220
+ }
2221
+ else {
2222
+ if (getTF ().isGCEnabled ())
2223
+ return " leak of returned object (GC)" ;
2224
+
2225
+ if (getTF ().getLangOptions ().getGCMode () == LangOptions::HybridGC)
2226
+ return " leak of returned object (hybrid MM, non-GC)" ;
2227
+
2228
+ assert (getTF ().getLangOptions ().getGCMode () == LangOptions::NonGC);
2229
+ return " leak of returned object" ;
2230
+ }
2212
2231
}
2213
2232
2214
2233
virtual const char * getDescription () const {
@@ -2410,8 +2429,8 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<GRState>* N,
2410
2429
break ;
2411
2430
2412
2431
case RefVal::ReturnedOwned:
2413
- Msg = " Object returned to caller as owning reference (single retain count "
2414
- " transferred to caller)." ;
2432
+ Msg = " Object returned to caller as an owning reference (single retain "
2433
+ " count transferred to caller)." ;
2415
2434
break ;
2416
2435
2417
2436
case RefVal::ReturnedNotOwned:
@@ -2630,11 +2649,12 @@ void Leak::EmitWarnings(BugReporter& BR) {
2630
2649
for (CFRefCount::leaks_iterator I = TF.leaks_begin (),
2631
2650
E = TF.leaks_end (); I != E; ++I) {
2632
2651
2633
- std::vector<SymbolID>& SymV = *(I->second );
2652
+ std::vector<std::pair< SymbolID, bool > >& SymV = *(I->second );
2634
2653
unsigned n = SymV.size ();
2635
2654
2636
2655
for (unsigned i = 0 ; i < n; ++i) {
2637
- CFRefReport report (*this , I->first , SymV[i]);
2656
+ setIsReturn (SymV[i].second );
2657
+ CFRefReport report (*this , I->first , SymV[i].first );
2638
2658
BR.EmitWarning (report);
2639
2659
}
2640
2660
}
@@ -2650,7 +2670,7 @@ bool Leak::isCached(BugReport& R) {
2650
2670
2651
2671
// Most bug reports are cached at the location where they occured.
2652
2672
// With leaks, we want to unique them by the location where they were
2653
- // allocated, and only report only a single path.
2673
+ // allocated, and only report a single path.
2654
2674
2655
2675
SymbolID Sym = static_cast <CFRefReport&>(R).getSymbol ();
2656
2676
0 commit comments