Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -88,6 +88,8 @@ /// An immutable map from CallDescriptions to arbitrary data. Provides a unified /// way for checkers to react on function calls. template class CallDescriptionMap { + friend class CallDescriptionSet; + // Some call descriptions aren't easily hashable (eg., the ones with qualified // names in which some sections are omitted), so let's put them // in a simple vector and use linear lookup. @@ -118,6 +120,21 @@ } }; +/// An immutable set of CallDescriptions. +/// Checkers can efficiently decide if a given CallEvent matches any +/// CallDescription in the set. +class CallDescriptionSet { + CallDescriptionMap Impl = {}; + +public: + CallDescriptionSet(std::initializer_list &&List); + + CallDescriptionSet(const CallDescriptionSet &) = delete; + CallDescriptionSet &operator=(const CallDescription &) = delete; + + LLVM_NODISCARD bool contains(const CallEvent &Call) const; +}; + } // namespace ento } // namespace clang Index: clang/lib/StaticAnalyzer/Core/CallDescription.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/CallDescription.cpp +++ clang/lib/StaticAnalyzer/Core/CallDescription.cpp @@ -46,3 +46,14 @@ Optional RequiredArgs /*= None*/, Optional RequiredParams /*= None*/) : CallDescription(0, QualifiedName, RequiredArgs, RequiredParams) {} + +ento::CallDescriptionSet::CallDescriptionSet( + std::initializer_list &&List) { + Impl.LinearMap.reserve(List.size()); + for (const CallDescription &CD : List) + Impl.LinearMap.push_back({CD, /*unused*/ true}); +} + +bool ento::CallDescriptionSet::contains(const CallEvent &Call) const { + return static_cast(Impl.lookup(Call)); +}