From d448fcd9b2238377dd8832ce9e35a37b59ef5aeb Mon Sep 17 00:00:00 2001 From: Balazs Benics Date: Fri, 19 Nov 2021 18:32:13 +0100 Subject: [PATCH] [analyzer][NFC] Introduce CallDescriptionSets Sometimes we only want to decide if some function is called, and we don't care which of the set. This `CallDescriptionSet` will have the same behavior, except instead of `lookup()` returning a pointer to the mapped value, the `contains()` returns `bool`. Internally, it uses the `CallDescriptionMap` for implementing the behavior. It is preferred, to reuse the generic `CallDescriptionMap::lookup()` logic, instead of duplicating it. The generic version might be improved by implementing a hash lookup or something along those lines. Reviewed By: martong, Szelethus Differential Revision: https://reviews.llvm.org/D113589 --- .../StaticAnalyzer/Core/PathSensitive/CallDescription.h | 17 +++++++++++++++++ clang/lib/StaticAnalyzer/Core/CallDescription.cpp | 11 +++++++++++ 2 files changed, 28 insertions(+) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h index bbf58d7..b34e1c8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h @@ -88,6 +88,8 @@ public: /// 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 @@ public: } }; +/// 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 diff --git a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp index 0589a2c..097cbf6 100644 --- a/clang/lib/StaticAnalyzer/Core/CallDescription.cpp +++ b/clang/lib/StaticAnalyzer/Core/CallDescription.cpp @@ -46,3 +46,14 @@ ento::CallDescription::CallDescription( 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)); +} -- 2.7.4