From 0c153cb277ce78d88c7457170d5260982c9d4e6a Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Fri, 2 Nov 2012 01:54:06 +0000 Subject: [PATCH] [analyzer] Use nice macros for the common ProgramStateTraits (map, set, list). Also, move the REGISTER_*_WITH_PROGRAMSTATE macros to ProgramStateTrait.h. This doesn't get rid of /all/ explicit uses of ProgramStatePartialTrait, but it does get a lot of them. llvm-svn: 167276 --- .../Core/PathSensitive/CheckerContext.h | 16 -------- .../Core/PathSensitive/ProgramStateTrait.h | 47 ++++++++++++++++++++++ .../lib/StaticAnalyzer/Checkers/CStringChecker.cpp | 32 +++++---------- .../Checkers/GenericTaintChecker.cpp | 10 +---- .../Checkers/MacOSKeychainAPIChecker.cpp | 21 ++++------ .../lib/StaticAnalyzer/Checkers/MallocChecker.cpp | 35 +++++----------- .../Checkers/ObjCContainersChecker.cpp | 12 +----- .../StaticAnalyzer/Checkers/PthreadLockChecker.cpp | 12 +----- .../StaticAnalyzer/Checkers/RetainCountChecker.cpp | 35 +++++----------- .../Core/ExprEngineCallAndReturn.cpp | 36 +++++++---------- clang/lib/StaticAnalyzer/Core/ProgramState.cpp | 13 ++---- .../StaticAnalyzer/Core/RangeConstraintManager.cpp | 15 +------ 12 files changed, 110 insertions(+), 174 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index ede4dba..3a14e64 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -16,22 +16,6 @@ #define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" -#include "llvm/ADT/ImmutableMap.h" - -/// Declares an immutable map of type NameTy, suitable for placement into -/// the ProgramState. The macro should not be used inside namespaces. -#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \ - class Name {}; \ - typedef llvm::ImmutableMap Name ## Ty; \ - namespace clang { \ - namespace ento { \ - template <> \ - struct ProgramStateTrait \ - : public ProgramStatePartialTrait { \ - static void *GDMIndex() { static int Index; return &Index; } \ - }; \ - } \ - } namespace clang { namespace ento { diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index 1c7bedb..8a80561 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -31,6 +31,26 @@ namespace clang { namespace ento { template struct ProgramStatePartialTrait; + /// Declares a program state trait for type \p Type called \p Name, and + /// introduce a typedef named \c NameTy. + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ + namespace { \ + class Name {}; \ + typedef Type Name ## Ty; \ + } \ + namespace clang { \ + namespace ento { \ + template <> \ + struct ProgramStateTrait \ + : public ProgramStatePartialTrait { \ + static void *GDMIndex() { static int Index; return &Index; } \ + }; \ + } \ + } + + // Partial-specialization for ImmutableMap. template @@ -71,6 +91,17 @@ namespace ento { } }; + /// Helper for REGISTER_MAP_WITH_PROGRAMSTATE. + #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap + + /// Declares an immutable map of type \p NameTy, suitable for placement into + /// the ProgramState. + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \ + CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value)) + // Partial-specialization for ImmutableSet. @@ -113,6 +144,14 @@ namespace ento { } }; + /// Declares an immutable list of type \p NameTy, suitable for placement into + /// the ProgramState. + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet) + + // Partial-specialization for ImmutableList. template @@ -151,6 +190,14 @@ namespace ento { } }; + /// Declares an immutable list of type \p NameTy, suitable for placement into + /// the ProgramState. + /// The macro should not be used inside namespaces, or for traits that must + /// be accessible from more than one translation unit. + #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \ + REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList) + + // Partial specialization for bool. template <> struct ProgramStatePartialTrait { typedef bool data_type; diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 6119d7e..eae9ddf 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -188,21 +188,9 @@ public: NonLoc right) const; }; -class CStringLength { -public: - typedef llvm::ImmutableMap EntryMap; -}; } //end anonymous namespace -namespace clang { -namespace ento { - template <> - struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { return CStringChecker::getTag(); } - }; -} -} +REGISTER_MAP_WITH_PROGRAMSTATE(CStringLength, const MemRegion *, SVal) //===----------------------------------------------------------------------===// // Individual checks and utility methods. @@ -1878,7 +1866,7 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { } bool CStringChecker::wantsRegionChangeUpdate(ProgramStateRef state) const { - CStringLength::EntryMap Entries = state->get(); + CStringLengthTy Entries = state->get(); return !Entries.isEmpty(); } @@ -1888,7 +1876,7 @@ CStringChecker::checkRegionChanges(ProgramStateRef state, ArrayRef ExplicitRegions, ArrayRef Regions, const CallEvent *Call) const { - CStringLength::EntryMap Entries = state->get(); + CStringLengthTy Entries = state->get(); if (Entries.isEmpty()) return state; @@ -1908,10 +1896,10 @@ CStringChecker::checkRegionChanges(ProgramStateRef state, } } - CStringLength::EntryMap::Factory &F = state->get_context(); + CStringLengthTy::Factory &F = state->get_context(); // Then loop over the entries in the current state. - for (CStringLength::EntryMap::iterator I = Entries.begin(), + for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end(); I != E; ++I) { const MemRegion *MR = I.getKey(); @@ -1938,9 +1926,9 @@ CStringChecker::checkRegionChanges(ProgramStateRef state, void CStringChecker::checkLiveSymbols(ProgramStateRef state, SymbolReaper &SR) const { // Mark all symbols in our string length map as valid. - CStringLength::EntryMap Entries = state->get(); + CStringLengthTy Entries = state->get(); - for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); + for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end(); I != E; ++I) { SVal Len = I.getData(); @@ -1956,12 +1944,12 @@ void CStringChecker::checkDeadSymbols(SymbolReaper &SR, return; ProgramStateRef state = C.getState(); - CStringLength::EntryMap Entries = state->get(); + CStringLengthTy Entries = state->get(); if (Entries.isEmpty()) return; - CStringLength::EntryMap::Factory &F = state->get_context(); - for (CStringLength::EntryMap::iterator I = Entries.begin(), E = Entries.end(); + CStringLengthTy::Factory &F = state->get_context(); + for (CStringLengthTy::iterator I = Entries.begin(), E = Entries.end(); I != E; ++I) { SVal Len = I.getData(); if (SymbolRef Sym = Len.getAsSymbol()) { diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index 455fb64..a9e0217 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -192,13 +192,7 @@ const char GenericTaintChecker::MsgTaintedBufferSize[] = /// to the call post-visit. The values are unsigned integers, which are either /// ReturnValueIndex, or indexes of the pointer/reference argument, which /// points to data, which should be tainted on return. -namespace { struct TaintArgsOnPostVisit{}; } -namespace clang { namespace ento { -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait > { - static void *GDMIndex() { return GenericTaintChecker::getTag(); } -}; -}} +REGISTER_SET_WITH_PROGRAMSTATE(TaintArgsOnPostVisit, unsigned) GenericTaintChecker::TaintPropagationRule GenericTaintChecker::TaintPropagationRule::getTaintPropagationRule( @@ -337,7 +331,7 @@ bool GenericTaintChecker::propagateFromPre(const CallExpr *CE, // Depending on what was tainted at pre-visit, we determined a set of // arguments which should be tainted after the function returns. These are // stored in the state as TaintArgsOnPostVisit set. - llvm::ImmutableSet TaintArgs = State->get(); + TaintArgsOnPostVisitTy TaintArgs = State->get(); if (TaintArgs.isEmpty()) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index ff0683e..76f20b6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -158,16 +158,9 @@ private: /// ProgramState traits to store the currently allocated (and not yet freed) /// symbols. This is a map from the allocated content symbol to the /// corresponding AllocationState. -typedef llvm::ImmutableMap AllocatedSetTy; - -namespace { struct AllocatedData {}; } -namespace clang { namespace ento { -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { static int index = 0; return &index; } -}; -}} +REGISTER_MAP_WITH_PROGRAMSTATE(AllocatedData, + SymbolRef, + MacOSKeychainAPIChecker::AllocationState) static bool isEnclosingFunctionParam(const Expr *E) { E = E->IgnoreParenCasts(); @@ -571,13 +564,13 @@ BugReport *MacOSKeychainAPIChecker:: void MacOSKeychainAPIChecker::checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const { ProgramStateRef State = C.getState(); - AllocatedSetTy ASet = State->get(); + AllocatedDataTy ASet = State->get(); if (ASet.isEmpty()) return; bool Changed = false; AllocationPairVec Errors; - for (AllocatedSetTy::iterator I = ASet.begin(), E = ASet.end(); I != E; ++I) { + for (AllocatedDataTy::iterator I = ASet.begin(), E = ASet.end(); I != E; ++I) { if (SR.isLive(I->first)) continue; @@ -619,7 +612,7 @@ void MacOSKeychainAPIChecker::checkEndPath(CheckerContext &C) const { if (C.getLocationContext()->getParent() != 0) return; - AllocatedSetTy AS = state->get(); + AllocatedDataTy AS = state->get(); if (AS.isEmpty()) return; @@ -627,7 +620,7 @@ void MacOSKeychainAPIChecker::checkEndPath(CheckerContext &C) const { // found here, so report it. bool Changed = false; AllocationPairVec Errors; - for (AllocatedSetTy::iterator I = AS.begin(), E = AS.end(); I != E; ++I ) { + for (AllocatedDataTy::iterator I = AS.begin(), E = AS.end(); I != E; ++I ) { Changed = true; state = state->remove(I->first); // If the allocated symbol is null or if error code was returned at diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index 6fc2e56..b1cce85 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -338,25 +338,8 @@ private: }; } // end anonymous namespace -typedef llvm::ImmutableMap RegionStateTy; -typedef llvm::ImmutableMap ReallocMap; -class RegionState {}; -class ReallocPairs {}; -namespace clang { -namespace ento { - template <> - struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { static int x; return &x; } - }; - - template <> - struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { static int x; return &x; } - }; -} -} +REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState) +REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair) namespace { class StopTrackingCallback : public SymbolVisitor { @@ -1073,8 +1056,8 @@ void MallocChecker::checkDeadSymbols(SymbolReaper &SymReaper, } // Cleanup the Realloc Pairs Map. - ReallocMap RP = state->get(); - for (ReallocMap::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { + ReallocPairsTy RP = state->get(); + for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { if (SymReaper.isDead(I->first) || SymReaper.isDead(I->second.ReallocatedSym)) { state = state->remove(I->first); @@ -1300,8 +1283,8 @@ ProgramStateRef MallocChecker::evalAssume(ProgramStateRef state, // Realloc returns 0 when reallocation fails, which means that we should // restore the state of the pointer being reallocated. - ReallocMap RP = state->get(); - for (ReallocMap::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { + ReallocPairsTy RP = state->get(); + for (ReallocPairsTy::iterator I = RP.begin(), E = RP.end(); I != E; ++I) { // If the symbol is assumed to be NULL, remove it from consideration. ConstraintManager &CMgr = state->getConstraintManager(); ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey()); @@ -1513,10 +1496,10 @@ MallocChecker::checkRegionChanges(ProgramStateRef State, static SymbolRef findFailedReallocSymbol(ProgramStateRef currState, ProgramStateRef prevState) { - ReallocMap currMap = currState->get(); - ReallocMap prevMap = prevState->get(); + ReallocPairsTy currMap = currState->get(); + ReallocPairsTy prevMap = prevState->get(); - for (ReallocMap::iterator I = prevMap.begin(), E = prevMap.end(); + for (ReallocPairsTy::iterator I = prevMap.begin(), E = prevMap.end(); I != E; ++I) { SymbolRef sym = I.getKey(); if (!currMap.lookup(sym)) diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp index e392a80..999c994 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCContainersChecker.cpp @@ -55,16 +55,8 @@ public: }; } // end anonymous namespace -// ProgramState trait - a map from array symbol to it's state. -typedef llvm::ImmutableMap ArraySizeM; - -namespace { struct ArraySizeMap {}; } -namespace clang { namespace ento { -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { return ObjCContainersChecker::getTag(); } -}; -}} +// ProgramState trait - a map from array symbol to its state. +REGISTER_MAP_WITH_PROGRAMSTATE(ArraySizeMap, SymbolRef, DefinedSVal) void ObjCContainersChecker::addSizeInfo(const Expr *Array, const Expr *Size, CheckerContext &C) const { diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 33ab8aa..d9b6384 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -43,15 +43,7 @@ public: } // end anonymous namespace // GDM Entry for tracking lock state. -namespace { class LockSet {}; } -namespace clang { -namespace ento { -template <> struct ProgramStateTrait : - public ProgramStatePartialTrait > { - static void *GDMIndex() { static int x = 0; return &x; } -}; -} // end of ento (ProgramState) namespace -} // end clang namespace +REGISTER_LIST_WITH_PROGRAMSTATE(LockSet, const MemRegion *) void PthreadLockChecker::checkPostStmt(const CallExpr *CE, @@ -163,7 +155,7 @@ void PthreadLockChecker::ReleaseLock(CheckerContext &C, const CallExpr *CE, return; ProgramStateRef state = C.getState(); - llvm::ImmutableList LS = state->get(); + LockSetTy LS = state->get(); // FIXME: Better analysis requires IPA for wrappers. // FIXME: check for double unlocks diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 862be6e..d716f57 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -342,20 +342,7 @@ void RefVal::print(raw_ostream &Out) const { // RefBindings - State used to track object reference counts. //===----------------------------------------------------------------------===// -typedef llvm::ImmutableMap RefBindings; - -namespace clang { -namespace ento { -template<> -struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { - static int RefBIndex = 0; - return &RefBIndex; - } -}; -} -} +REGISTER_MAP_WITH_PROGRAMSTATE(RefBindings, SymbolRef, RefVal) static inline const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym) { @@ -3438,15 +3425,15 @@ ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state, // too bad since the number of symbols we will track in practice are // probably small and evalAssume is only called at branches and a few // other places. - RefBindings B = state->get(); + RefBindingsTy B = state->get(); if (B.isEmpty()) return state; bool changed = false; - RefBindings::Factory &RefBFactory = state->get_context(); + RefBindingsTy::Factory &RefBFactory = state->get_context(); - for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { + for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { // Check if the symbol is null stop tracking the symbol. ConstraintManager &CMgr = state->getConstraintManager(); ConditionTruthVal AllocFailed = CMgr.isNull(state, I.getKey()); @@ -3607,10 +3594,10 @@ RetainCountChecker::processLeaks(ProgramStateRef state, void RetainCountChecker::checkEndPath(CheckerContext &Ctx) const { ProgramStateRef state = Ctx.getState(); - RefBindings B = state->get(); + RefBindingsTy B = state->get(); ExplodedNode *Pred = Ctx.getPredecessor(); - for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { + for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { llvm::tie(Pred, state) = handleAutoreleaseCounts(state, Pred, /*Tag=*/0, Ctx, I->first, I->second); if (!state) @@ -3627,7 +3614,7 @@ void RetainCountChecker::checkEndPath(CheckerContext &Ctx) const { B = state->get(); SmallVector Leaked; - for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) + for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) state = handleSymbolDeath(state, I->first, I->second, Leaked); processLeaks(state, Leaked, Ctx, Pred); @@ -3651,7 +3638,7 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, ExplodedNode *Pred = C.getPredecessor(); ProgramStateRef state = C.getState(); - RefBindings B = state->get(); + RefBindingsTy B = state->get(); // Update counts from autorelease pools for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), @@ -3684,7 +3671,7 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, return; // Now generate a new node that nukes the old bindings. - RefBindings::Factory &F = state->get_context(); + RefBindingsTy::Factory &F = state->get_context(); for (SymbolReaper::dead_iterator I = SymReaper.dead_begin(), E = SymReaper.dead_end(); I != E; ++I) @@ -3697,12 +3684,12 @@ void RetainCountChecker::checkDeadSymbols(SymbolReaper &SymReaper, void RetainCountChecker::printState(raw_ostream &Out, ProgramStateRef State, const char *NL, const char *Sep) const { - RefBindings B = State->get(); + RefBindingsTy B = State->get(); if (!B.isEmpty()) Out << Sep << NL; - for (RefBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) { + for (RefBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { Out << I->first << " : "; I->second.print(Out); Out << NL; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index d4abbdc..438fbdf 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -406,26 +406,20 @@ bool ExprEngine::shouldInlineDecl(const Decl *D, ExplodedNode *Pred) { return true; } -/// The GDM component containing the dynamic dispatch bifurcation info. When -/// the exact type of the receiver is not known, we want to explore both paths - -/// one on which we do inline it and the other one on which we don't. This is -/// done to ensure we do not drop coverage. -/// This is the map from the receiver region to a bool, specifying either we -/// consider this region's information precise or not along the given path. -namespace clang { -namespace ento { -enum DynamicDispatchMode { DynamicDispatchModeInlined = 1, - DynamicDispatchModeConservative }; - -struct DynamicDispatchBifurcationMap {}; -typedef llvm::ImmutableMap DynamicDispatchBifur; -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { static int index; return &index; } -}; - -}} +// The GDM component containing the dynamic dispatch bifurcation info. When +// the exact type of the receiver is not known, we want to explore both paths - +// one on which we do inline it and the other one on which we don't. This is +// done to ensure we do not drop coverage. +// This is the map from the receiver region to a bool, specifying either we +// consider this region's information precise or not along the given path. +namespace { + enum DynamicDispatchMode { + DynamicDispatchModeInlined = 1, + DynamicDispatchModeConservative + }; +} +REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap, + const MemRegion *, unsigned) bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, @@ -734,7 +728,7 @@ void ExprEngine::BifurcateCall(const MemRegion *BifurReg, // Check if we've performed the split already - note, we only want // to split the path once per memory region. ProgramStateRef State = Pred->getState(); - const unsigned int *BState = + const unsigned *BState = State->get(BifurReg); if (BState) { // If we are on "inline path", keep inlining if possible. diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index af047d1..fc57ead 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -713,15 +713,10 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const { } /// The GDM component containing the dynamic type info. This is a map from a -/// symbol to it's most likely type. -namespace clang { -namespace ento { -typedef llvm::ImmutableMap DynamicTypeMap; -template<> struct ProgramStateTrait - : public ProgramStatePartialTrait { - static void *GDMIndex() { static int index; return &index; } -}; -}} +/// symbol to its most likely type. +REGISTER_MAP_WITH_PROGRAMSTATE(DynamicTypeMap, + const MemRegion *, + DynamicTypeInfo) DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const { Reg = Reg->StripCasts(); diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp index 467abd0..981be9a 100644 --- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp @@ -24,9 +24,6 @@ using namespace clang; using namespace ento; -namespace { class ConstraintRange {}; } -static int ConstraintRangeIndex = 0; - /// A Range represents the closed range [from, to]. The caller must /// guarantee that from <= to. Note that Range is immutable, so as not /// to subvert RangeSet's immutability. @@ -280,17 +277,7 @@ public: }; } // end anonymous namespace -typedef llvm::ImmutableMap ConstraintRangeTy; - -namespace clang { -namespace ento { -template<> -struct ProgramStateTrait - : public ProgramStatePartialTrait { - static inline void *GDMIndex() { return &ConstraintRangeIndex; } -}; -} -} +REGISTER_MAP_WITH_PROGRAMSTATE(ConstraintRange, SymbolRef, RangeSet) namespace { class RangeConstraintManager : public SimpleConstraintManager{ -- 2.7.4