r178518 - [analyzer] Teach invalidateRegions that regions within LazyCompoundVal need to be invalidated
Anna Zaks
ganna at apple.com
Mon Apr 1 18:28:24 PDT 2013
Author: zaks
Date: Mon Apr 1 20:28:24 2013
New Revision: 178518
URL: http://llvm.org/viewvc/llvm-project?rev=178518&view=rev
Log:
[analyzer] Teach invalidateRegions that regions within LazyCompoundVal need to be invalidated
Refactor invalidateRegions to take SVals instead of Regions as input and teach RegionStore
about processing LazyCompoundVal as a top-level “escaping” value.
This addresses several false positives that get triggered by the NewDelete checker, but the
underlying issue is reproducible with other checkers as well (for example, MallocChecker).
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/test/Analysis/malloc.cpp
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h Mon Apr 1 20:28:24 2013
@@ -162,11 +162,11 @@ protected:
}
- typedef SmallVectorImpl<const MemRegion *> RegionList;
+ typedef SmallVectorImpl<SVal> ValueList;
/// \brief Used to specify non-argument regions that will be invalidated as a
/// result of this call.
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const {}
+ virtual void getExtraInvalidatedValues(ValueList &Values) const {}
public:
virtual ~CallEvent() {}
@@ -504,7 +504,7 @@ protected:
BlockCall(const BlockCall &Other) : SimpleCall(Other) {}
virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
public:
/// \brief Returns the region associated with this instance of the block.
@@ -548,7 +548,7 @@ public:
/// it is written.
class CXXInstanceCall : public AnyFunctionCall {
protected:
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
const LocationContext *LCtx)
@@ -731,7 +731,7 @@ protected:
CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
public:
virtual const CXXConstructExpr *getOriginExpr() const {
@@ -830,7 +830,7 @@ protected:
ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); }
- virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+ virtual void getExtraInvalidatedValues(ValueList &Values) const;
/// Check if the selector may have multiple definitions (may have overrides).
virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Mon Apr 1 20:28:24 2013
@@ -250,6 +250,13 @@ public:
ArrayRef<const MemRegion *> ConstRegions =
ArrayRef<const MemRegion *>()) const;
+ ProgramStateRef
+ invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
+ unsigned BlockCount, const LocationContext *LCtx,
+ bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
+ const CallEvent *Call = 0,
+ ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const;
+
/// enterStackFrame - Returns the state for entry to the given stack frame,
/// preserving the current state.
ProgramStateRef enterStackFrame(const CallEvent &Call,
@@ -419,15 +426,16 @@ private:
friend void ProgramStateRetain(const ProgramState *state);
friend void ProgramStateRelease(const ProgramState *state);
+ /// \sa invalidateValues()
/// \sa invalidateRegions()
ProgramStateRef
- invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
+ invalidateRegionsImpl(ArrayRef<SVal> Values,
const Expr *E, unsigned BlockCount,
const LocationContext *LCtx,
bool ResultsInSymbolEscape,
InvalidatedSymbols &IS,
const CallEvent *Call,
- ArrayRef<const MemRegion *> ConstRegions) const;
+ ArrayRef<SVal> ConstValues) const;
};
//===----------------------------------------------------------------------===//
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h Mon Apr 1 20:28:24 2013
@@ -544,7 +544,8 @@ private:
};
} // end ento::loc namespace
-} // end GR namespace
+
+} // end ento namespace
} // end clang namespace
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Mon Apr 1 20:28:24 2013
@@ -178,30 +178,40 @@ public:
/// invalidate additional regions that may have changed based on accessing
/// the given regions. Optionally, invalidates non-static globals as well.
/// \param[in] store The initial store
- /// \param[in] Regions The regions to invalidate.
+ /// \param[in] Values The values to invalidate.
+ /// \param[in] ConstValues The values to invalidate; these are known to be
+ /// const, so only regions accesible from them should be invalidated.
/// \param[in] E The current statement being evaluated. Used to conjure
/// symbols to mark the values of invalidated regions.
/// \param[in] Count The current block count. Used to conjure
/// symbols to mark the values of invalidated regions.
- /// \param[in,out] IS A set to fill with any symbols that are no longer
- /// accessible. Pass \c NULL if this information will not be used.
/// \param[in] Call The call expression which will be used to determine which
/// globals should get invalidated.
+ /// \param[in,out] IS A set to fill with any symbols that are no longer
+ /// accessible. Pass \c NULL if this information will not be used.
/// \param[in,out] ConstIS A set to fill with any symbols corresponding to
- /// the ConstRegions.
+ /// the ConstValues.
+ /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
+ //// explicitely being invalidated. Pass \c NULL if this
+ /// information will not be used.
+ /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const
+ //// regions explicitely being invalidated. Pass \c NULL if this
+ /// information will not be used.
/// \param[in,out] Invalidated A vector to fill with any regions being
/// invalidated. This should include any regions explicitly invalidated
/// even if they do not currently have bindings. Pass \c NULL if this
/// information will not be used.
virtual StoreRef invalidateRegions(Store store,
- ArrayRef<const MemRegion *> Regions,
- const Expr *E, unsigned Count,
- const LocationContext *LCtx,
- InvalidatedSymbols &IS,
- const CallEvent *Call,
- ArrayRef<const MemRegion *> ConstRegions,
- InvalidatedSymbols &ConstIS,
- InvalidatedRegions *Invalidated) = 0;
+ ArrayRef<SVal> Values,
+ ArrayRef<SVal> ConstValues,
+ const Expr *E, unsigned Count,
+ const LocationContext *LCtx,
+ const CallEvent *Call,
+ InvalidatedSymbols &IS,
+ InvalidatedSymbols &ConstIS,
+ InvalidatedRegions *InvalidatedTopLevel,
+ InvalidatedRegions *InvalidatedTopLevelConst,
+ InvalidatedRegions *Invalidated) = 0;
/// enterStackFrame - Let the StoreManager to do something when execution
/// engine is about to execute into a callee.
Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Mon Apr 1 20:28:24 2013
@@ -140,9 +140,10 @@ ProgramStateRef CallEvent::invalidateReg
ProgramStateRef Orig) const {
ProgramStateRef Result = (Orig ? Orig : getState());
- SmallVector<const MemRegion *, 8> ConstRegions;
- SmallVector<const MemRegion *, 8> RegionsToInvalidate;
- getExtraInvalidatedRegions(RegionsToInvalidate);
+ SmallVector<SVal, 8> ConstValues;
+ SmallVector<SVal, 8> ValuesToInvalidate;
+
+ getExtraInvalidatedValues(ValuesToInvalidate);
// Indexes of arguments whose values will be preserved by the call.
llvm::SmallSet<unsigned, 4> PreserveArgs;
@@ -150,25 +151,21 @@ ProgramStateRef CallEvent::invalidateReg
findPtrToConstParams(PreserveArgs, *this);
for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
- const MemRegion *R = getArgSVal(Idx).getAsRegion();
- if (!R)
- continue;
-
// Mark this region for invalidation. We batch invalidate regions
// below for efficiency.
if (PreserveArgs.count(Idx))
- ConstRegions.push_back(R);
+ ConstValues.push_back(getArgSVal(Idx));
else
- RegionsToInvalidate.push_back(R);
+ ValuesToInvalidate.push_back(getArgSVal(Idx));
}
// Invalidate designated regions using the batch invalidation API.
// NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
// global variables.
- return Result->invalidateRegions(RegionsToInvalidate, getOriginExpr(),
+ return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
BlockCount, getLocationContext(),
/*CausedByPointerEscape*/ true,
- /*Symbols=*/0, this, ConstRegions);
+ /*Symbols=*/0, this, ConstValues);
}
ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
@@ -374,9 +371,8 @@ const FunctionDecl *CXXInstanceCall::get
return getSVal(CE->getCallee()).getAsFunctionDecl();
}
-void CXXInstanceCall::getExtraInvalidatedRegions(RegionList &Regions) const {
- if (const MemRegion *R = getCXXThisVal().getAsRegion())
- Regions.push_back(R);
+void CXXInstanceCall::getExtraInvalidatedValues(ValueList &Values) const {
+ Values.push_back(getCXXThisVal());
}
SVal CXXInstanceCall::getCXXThisVal() const {
@@ -529,10 +525,10 @@ CallEvent::param_iterator BlockCall::par
return D->param_end();
}
-void BlockCall::getExtraInvalidatedRegions(RegionList &Regions) const {
+void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
// FIXME: This also needs to invalidate captured globals.
if (const MemRegion *R = getBlockRegion())
- Regions.push_back(R);
+ Values.push_back(loc::MemRegionVal(R));
}
void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -550,9 +546,9 @@ SVal CXXConstructorCall::getCXXThisVal()
return UnknownVal();
}
-void CXXConstructorCall::getExtraInvalidatedRegions(RegionList &Regions) const {
+void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values) const {
if (Data)
- Regions.push_back(static_cast<const MemRegion *>(Data));
+ Values.push_back(loc::MemRegionVal(static_cast<const MemRegion *>(Data)));
}
void CXXConstructorCall::getInitialStackFrameContents(
@@ -604,9 +600,8 @@ CallEvent::param_iterator ObjCMethodCall
}
void
-ObjCMethodCall::getExtraInvalidatedRegions(RegionList &Regions) const {
- if (const MemRegion *R = getReceiverSVal().getAsRegion())
- Regions.push_back(R);
+ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values) const {
+ Values.push_back(getReceiverSVal());
}
SVal ObjCMethodCall::getSelfSVal() const {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Mon Apr 1 20:28:24 2013
@@ -141,6 +141,7 @@ ProgramStateRef ProgramState::bindDefaul
}
typedef ArrayRef<const MemRegion *> RegionList;
+typedef ArrayRef<SVal> ValueList;
ProgramStateRef
ProgramState::invalidateRegions(RegionList Regions,
@@ -150,54 +151,92 @@ ProgramState::invalidateRegions(RegionLi
InvalidatedSymbols *IS,
const CallEvent *Call,
RegionList ConstRegions) const {
+ SmallVector<SVal, 8> Values;
+ for (RegionList::const_iterator I = Regions.begin(),
+ E = Regions.end(); I != E; ++I)
+ Values.push_back(loc::MemRegionVal(*I));
+
+ SmallVector<SVal, 8> ConstValues;
+ for (RegionList::const_iterator I = ConstRegions.begin(),
+ E = ConstRegions.end(); I != E; ++I)
+ ConstValues.push_back(loc::MemRegionVal(*I));
+
if (!IS) {
InvalidatedSymbols invalidated;
- return invalidateRegionsImpl(Regions, E, Count, LCtx,
+ return invalidateRegionsImpl(Values, E, Count, LCtx,
CausedByPointerEscape,
- invalidated, Call, ConstRegions);
+ invalidated, Call, ConstValues);
}
- return invalidateRegionsImpl(Regions, E, Count, LCtx, CausedByPointerEscape,
- *IS, Call, ConstRegions);
+ return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
+ *IS, Call, ConstValues);
}
-ProgramStateRef
-ProgramState::invalidateRegionsImpl(RegionList Regions,
+ProgramStateRef
+ProgramState::invalidateRegions(ValueList Values,
+ const Expr *E, unsigned Count,
+ const LocationContext *LCtx,
+ bool CausedByPointerEscape,
+ InvalidatedSymbols *IS,
+ const CallEvent *Call,
+ ValueList ConstValues) const {
+ if (!IS) {
+ InvalidatedSymbols invalidated;
+ return invalidateRegionsImpl(Values, E, Count, LCtx,
+ CausedByPointerEscape,
+ invalidated, Call, ConstValues);
+ }
+ return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
+ *IS, Call, ConstValues);
+}
+
+ProgramStateRef
+ProgramState::invalidateRegionsImpl(ValueList Values,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
bool CausedByPointerEscape,
InvalidatedSymbols &IS,
const CallEvent *Call,
- RegionList ConstRegions) const {
+ ValueList ConstValues) const {
ProgramStateManager &Mgr = getStateManager();
SubEngine* Eng = Mgr.getOwningEngine();
InvalidatedSymbols ConstIS;
if (Eng) {
+ StoreManager::InvalidatedRegions TopLevelInvalidated;
+ StoreManager::InvalidatedRegions TopLevelConstInvalidated;
StoreManager::InvalidatedRegions Invalidated;
const StoreRef &newStore
- = Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS,
- Call, ConstRegions, ConstIS,
- &Invalidated);
+ = Mgr.StoreMgr->invalidateRegions(getStore(), Values, ConstValues,
+ E, Count, LCtx, Call,
+ IS, ConstIS,
+ &TopLevelInvalidated,
+ &TopLevelConstInvalidated,
+ &Invalidated);
ProgramStateRef newState = makeWithStore(newStore);
if (CausedByPointerEscape) {
- newState = Eng->notifyCheckersOfPointerEscape(newState,
- &IS, Regions, Invalidated, Call);
- if (!ConstRegions.empty()) {
+ newState = Eng->notifyCheckersOfPointerEscape(newState, &IS,
+ TopLevelInvalidated,
+ Invalidated, Call);
+ if (!ConstValues.empty()) {
StoreManager::InvalidatedRegions Empty;
newState = Eng->notifyCheckersOfPointerEscape(newState, &ConstIS,
- ConstRegions, Empty, Call,
+ TopLevelConstInvalidated,
+ Empty, Call,
true);
}
}
- return Eng->processRegionChanges(newState, &IS, Regions, Invalidated, Call);
+ return Eng->processRegionChanges(newState, &IS,
+ TopLevelInvalidated, Invalidated,
+ Call);
}
const StoreRef &newStore =
- Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS,
- Call, ConstRegions, ConstIS, NULL);
+ Mgr.StoreMgr->invalidateRegions(getStore(), Values, ConstValues,
+ E, Count, LCtx, Call,
+ IS, ConstIS, NULL, NULL, NULL);
return makeWithStore(newStore);
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Mon Apr 1 20:28:24 2013
@@ -318,6 +318,7 @@ public:
//===----------------------------------------------------------------------===//
namespace {
+class invalidateRegionsWorker;
class RegionStoreManager : public StoreManager {
public:
@@ -331,6 +332,13 @@ private:
SValListTy> LazyBindingsMapTy;
LazyBindingsMapTy LazyBindingsMap;
+ /// \brief A helper used to populate the work list with the given set of
+ /// regions.
+ void populateWorkList(invalidateRegionsWorker &W,
+ ArrayRef<SVal> Values,
+ bool IsArrayOfConstRegions,
+ InvalidatedRegions *TopLevelRegions);
+
public:
RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
: StoreManager(mgr), Features(f),
@@ -365,14 +373,17 @@ public:
RegionBindingsRef B,
InvalidatedRegions *Invalidated);
- StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions,
+ StoreRef invalidateRegions(Store store,
+ ArrayRef<SVal> Values,
+ ArrayRef<SVal> ConstValues,
const Expr *E, unsigned Count,
const LocationContext *LCtx,
- InvalidatedSymbols &IS,
const CallEvent *Call,
- ArrayRef<const MemRegion *> ConstRegions,
+ InvalidatedSymbols &IS,
InvalidatedSymbols &ConstIS,
- InvalidatedRegions *Invalidated);
+ InvalidatedRegions *Invalidated,
+ InvalidatedRegions *InvalidatedTopLevel,
+ InvalidatedRegions *InvalidatedTopLevelConst);
bool scanReachableSymbols(Store S, const MemRegion *R,
ScanReachableSymbols &Callbacks);
@@ -1062,15 +1073,48 @@ RegionStoreManager::invalidateGlobalRegi
return B;
}
+void RegionStoreManager::populateWorkList(invalidateRegionsWorker &W,
+ ArrayRef<SVal> Values,
+ bool IsArrayOfConstRegions,
+ InvalidatedRegions *TopLevelRegions) {
+ for (ArrayRef<SVal>::iterator I = Values.begin(),
+ E = Values.end(); I != E; ++I) {
+ SVal V = *I;
+ if (Optional<nonloc::LazyCompoundVal> LCS =
+ V.getAs<nonloc::LazyCompoundVal>()) {
+
+ const SValListTy &Vals = getInterestingValues(*LCS);
+
+ for (SValListTy::const_iterator I = Vals.begin(),
+ E = Vals.end(); I != E; ++I) {
+ // Note: the last argumet is false here because these are
+ // non-top-level regions.
+ if (const MemRegion *R = (*I).getAsRegion())
+ W.AddToWorkList(R, /*IsConst=*/ false);
+ }
+ continue;
+ }
+
+ if (const MemRegion *R = V.getAsRegion()) {
+ if (TopLevelRegions)
+ TopLevelRegions->push_back(R);
+ W.AddToWorkList(R, /*IsConst=*/ IsArrayOfConstRegions);
+ continue;
+ }
+ }
+}
+
StoreRef
RegionStoreManager::invalidateRegions(Store store,
- ArrayRef<const MemRegion *> Regions,
+ ArrayRef<SVal> Values,
+ ArrayRef<SVal> ConstValues,
const Expr *Ex, unsigned Count,
const LocationContext *LCtx,
- InvalidatedSymbols &IS,
const CallEvent *Call,
- ArrayRef<const MemRegion *> ConstRegions,
+ InvalidatedSymbols &IS,
InvalidatedSymbols &ConstIS,
+ InvalidatedRegions *TopLevelRegions,
+ InvalidatedRegions *TopLevelConstRegions,
InvalidatedRegions *Invalidated) {
RegionBindingsRef B = RegionStoreManager::getRegionBindings(store);
invalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ConstIS,
@@ -1080,15 +1124,10 @@ RegionStoreManager::invalidateRegions(St
W.GenerateClusters();
// Add the regions to the worklist.
- for (ArrayRef<const MemRegion *>::iterator
- I = Regions.begin(), E = Regions.end(); I != E; ++I)
- W.AddToWorkList(*I, /*IsConst=*/false);
-
- for (ArrayRef<const MemRegion *>::iterator I = ConstRegions.begin(),
- E = ConstRegions.end();
- I != E; ++I) {
- W.AddToWorkList(*I, /*IsConst=*/true);
- }
+ populateWorkList(W, Values, /*IsArrayOfConstRegions*/ false,
+ TopLevelRegions);
+ populateWorkList(W, ConstValues, /*IsArrayOfConstRegions*/ true,
+ TopLevelConstRegions);
W.RunWorkList();
Modified: cfe/trunk/test/Analysis/malloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.cpp (original)
+++ cfe/trunk/test/Analysis/malloc.cpp Mon Apr 1 20:28:24 2013
@@ -5,7 +5,7 @@ void *malloc(size_t);
void free(void *);
void *realloc(void *ptr, size_t size);
void *calloc(size_t nmemb, size_t size);
-
+char *strdup(const char *s);
void checkThatMallocCheckerIsRunning() {
malloc(4);
@@ -67,3 +67,36 @@ struct X get() {
result.a = malloc(4);
return result; // no-warning
}
+
+// Ensure that regions accessible through a LazyCompoundVal trigger region escape.
+// Malloc checker used to report leaks for the following two test cases.
+struct Property {
+ char* getterName;
+ Property(char* n)
+ : getterName(n) {}
+
+};
+void append(Property x);
+
+void appendWrapper(char *getterName) {
+ append(Property(getterName));
+}
+void foo(const char* name) {
+ char* getterName = strdup(name);
+ appendWrapper(getterName); // no-warning
+}
+
+struct NestedProperty {
+ Property prop;
+ NestedProperty(Property p)
+ : prop(p) {}
+};
+void appendNested(NestedProperty x);
+
+void appendWrapperNested(char *getterName) {
+ appendNested(NestedProperty(Property(getterName)));
+}
+void fooNested(const char* name) {
+ char* getterName = strdup(name);
+ appendWrapperNested(getterName); // no-warning
+}
\ No newline at end of file
More information about the cfe-commits
mailing list