diff options
5 files changed, 101 insertions, 83 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index e342dd6bb7c..6ee75b73846 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -21,52 +21,6 @@ namespace clang { namespace ento { - /// Declares an immutable map of type \p NameTy, suitable for placement into - /// the ProgramState. This is implementing using llvm::ImmutableMap. - /// - /// \code - /// State = State->set<Name>(K, V); - /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map. - /// State = State->remove<Name>(K); - /// NameTy Map = State->get<Name>(); - /// \endcode - /// - /// 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)) - - /// Declares an immutable set of type \p NameTy, suitable for placement into - /// the ProgramState. This is implementing using llvm::ImmutableSet. - /// - /// \code - /// State = State->add<Name>(E); - /// State = State->remove<Name>(E); - /// bool Present = State->contains<Name>(E); - /// NameTy Set = State->get<Name>(); - /// \endcode - /// - /// 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<Elem>) - - /// Declares an immutable list of type \p NameTy, suitable for placement into - /// the ProgramState. This is implementing using llvm::ImmutableList. - /// - /// \code - /// State = State->add<Name>(E); // Adds to the /end/ of the list. - /// bool Present = State->contains<Name>(E); - /// NameTy List = State->get<Name>(); - /// \endcode - /// - /// 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<Elem>) - - class CheckerContext { ExprEngine &Eng; /// The current exploded(symbolic execution) graph node. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index 5555b292534..64de736c7e9 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -30,8 +30,7 @@ namespace ento { /// Declares a program state trait for type \p Type called \p Name, and /// introduce a type named \c NameTy. - /// The macro should not be used inside namespaces, or for traits that must - /// be accessible from more than one translation unit. + /// The macro should not be used inside namespaces. #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ namespace { \ class Name {}; \ @@ -47,6 +46,102 @@ namespace ento { } \ } + /// Declares a factory for objects of type \p Type in the program state + /// manager. The type must provide a ::Factory sub-class. Commonly used for + /// ImmutableMap, ImmutableSet, ImmutableList. The macro should not be used + /// inside namespaces. + #define REGISTER_FACTORY_WITH_PROGRAMSTATE(Type) \ + namespace clang { \ + namespace ento { \ + template <> \ + struct ProgramStateTrait<Type> \ + : public ProgramStatePartialTrait<Type> { \ + static void *GDMIndex() { static int Index; return &Index; } \ + }; \ + } \ + } + + /// Helper for registering a map trait. + /// + /// If the map type were written directly in the invocation of + /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments + /// would be treated as a macro argument separator, which is wrong. + /// This allows the user to specify a map type in a way that the preprocessor + /// can deal with. + #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> + + /// Declares an immutable map of type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableMap. + /// + /// \code + /// State = State->set<Name>(K, V); + /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map. + /// State = State->remove<Name>(K); + /// NameTy Map = State->get<Name>(); + /// \endcode + /// + /// 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)) + + /// Declares an immutable map type \p Name and registers the factory + /// for such maps in the program state, but does not add the map itself + /// to the program state. Useful for managing lifetime of maps that are used + /// as elements of other program state data structures. + #define REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(Name, Key, Value) \ + using Name = llvm::ImmutableMap<Key, Value>; \ + REGISTER_FACTORY_WITH_PROGRAMSTATE(Name) + + + /// Declares an immutable set of type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableSet. + /// + /// \code + /// State = State->add<Name>(E); + /// State = State->remove<Name>(E); + /// bool Present = State->contains<Name>(E); + /// NameTy Set = State->get<Name>(); + /// \endcode + /// + /// 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<Elem>) + + /// Declares an immutable set type \p Name and registers the factory + /// for such sets in the program state, but does not add the set itself + /// to the program state. Useful for managing lifetime of sets that are used + /// as elements of other program state data structures. + #define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \ + using Name = llvm::ImmutableSet<Elem>; \ + REGISTER_FACTORY_WITH_PROGRAMSTATE(Name) + + + /// Declares an immutable list type \p NameTy, suitable for placement into + /// the ProgramState. This is implementing using llvm::ImmutableList. + /// + /// \code + /// State = State->add<Name>(E); // Adds to the /end/ of the list. + /// bool Present = State->contains<Name>(E); + /// NameTy List = State->get<Name>(); + /// \endcode + /// + /// 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<Elem>) + + /// Declares an immutable list of type \p Name and registers the factory + /// for such lists in the program state, but does not add the list itself + /// to the program state. Useful for managing lifetime of lists that are used + /// as elements of other program state data structures. + #define REGISTER_LIST_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \ + using Name = llvm::ImmutableList<Elem>; \ + REGISTER_FACTORY_WITH_PROGRAMSTATE(Name) + + // Partial-specialization for ImmutableMap. template <typename Key, typename Data, typename Info> struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> { @@ -95,15 +190,6 @@ namespace ento { } }; - /// Helper for registering a map trait. - /// - /// If the map type were written directly in the invocation of - /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments - /// would be treated as a macro argument separator, which is wrong. - /// This allows the user to specify a map type in a way that the preprocessor - /// can deal with. - #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> - // Partial-specialization for ImmutableSet. template <typename Key, typename Info> struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> { diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp index f4d2e32cef1..c330d7504b9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp @@ -178,20 +178,12 @@ private: }; } // End anonymous namespace. -typedef llvm::ImmutableSet<SymbolRef> SymbolSet; /// Maps from the symbol for a class instance to the set of /// symbols remaining that must be released in -dealloc. +REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef) REGISTER_MAP_WITH_PROGRAMSTATE(UnreleasedIvarMap, SymbolRef, SymbolSet) -namespace clang { -namespace ento { -template<> struct ProgramStateTrait<SymbolSet> -: public ProgramStatePartialTrait<SymbolSet> { - static void *GDMIndex() { static int index = 0; return &index; } -}; -} -} /// An AST check that diagnose when the class requires a -dealloc method and /// is missing one. diff --git a/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp index b3638d0b9cf..716a89972a9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/InnerPointerChecker.cpp @@ -25,23 +25,10 @@ using namespace clang; using namespace ento; -using PtrSet = llvm::ImmutableSet<SymbolRef>; - // Associate container objects with a set of raw pointer symbols. +REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(PtrSet, SymbolRef); REGISTER_MAP_WITH_PROGRAMSTATE(RawPtrMap, const MemRegion *, PtrSet) -// This is a trick to gain access to PtrSet's Factory. -namespace clang { -namespace ento { -template <> -struct ProgramStateTrait<PtrSet> : public ProgramStatePartialTrait<PtrSet> { - static void *GDMIndex() { - static int Index = 0; - return &Index; - } -}; -} // end namespace ento -} // end namespace clang namespace { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 202deb0d4fc..66cbebad1c2 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -406,9 +406,8 @@ namespace { }; } // end anonymous namespace -REGISTER_TRAIT_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap, - CLANG_ENTO_PROGRAMSTATE_MAP(const MemRegion *, - unsigned)) +REGISTER_MAP_WITH_PROGRAMSTATE(DynamicDispatchBifurcationMap, + const MemRegion *, unsigned) bool ExprEngine::inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, |