CheckerManager.h revision 8dae128d16bf98759b7a678ce3eebb613bd17109
137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===// 237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// 337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// The LLVM Compiler Infrastructure 437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// 537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// This file is distributed under the University of Illinois Open Source 637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// License. See LICENSE.TXT for details. 737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// 837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===----------------------------------------------------------------------===// 937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// 1037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// Defines the Static Analyzer Checker Manager. 1137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// 1237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===----------------------------------------------------------------------===// 1337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 1437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 1537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H 1637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 1737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "clang/Analysis/ProgramPoint.h" 1837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "clang/Basic/LangOptions.h" 1937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 2037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" 2137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "llvm/ADT/DenseMap.h" 2237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "llvm/ADT/FoldingSet.h" 2337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include "llvm/ADT/SmallVector.h" 2437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang#include <vector> 2537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 2637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangnamespace clang { 2737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class Decl; 2837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class Stmt; 2937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class CallExpr; 3037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 3137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangnamespace ento { 3237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class CheckerBase; 3337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class ExprEngine; 3437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class AnalysisManager; 3537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class BugReporter; 3637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class CheckerContext; 3737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class SimpleCall; 387d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris class ObjCMethodCall; 397d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris class SVal; 407d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris class ExplodedNode; 411fdb08e5fc427b54b54214e3b3fbdda73d369f4dDavid Mosberger-Tang class ExplodedNodeSet; 4237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class ExplodedGraph; 4337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang class ProgramState; 445f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura class NodeBuilder; 455f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura struct NodeBuilderContext; 465f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura class MemRegion; 475f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura class SymbolReaper; 485f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura 495f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuuratemplate <typename T> class CheckerFn; 505f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura 515f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuuratemplate <typename RET, typename P1, typename P2, typename P3, typename P4, 525f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura typename P5> 535f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuuraclass CheckerFn<RET(P1, P2, P3, P4, P5)> { 545f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura typedef RET (*Func)(void *, P1, P2, P3, P4, P5); 555f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura Func Fn; 565f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuurapublic: 575f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura CheckerBase *Checker; 585f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 595f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const { 605f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura return Fn(Checker, p1, p2, p3, p4, p5); 615f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura } 625f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura}; 635f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura 645f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuuratemplate <typename RET, typename P1, typename P2, typename P3, typename P4> 6537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangclass CheckerFn<RET(P1, P2, P3, P4)> { 6637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang typedef RET (*Func)(void *, P1, P2, P3, P4); 6737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang Func Fn; 6837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangpublic: 6937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerBase *Checker; 7037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 7137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const { 7237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang return Fn(Checker, p1, p2, p3, p4); 7337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang } 7437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang}; 7537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 7600db7f752ac26c5aab6b4ca03531a2c3e212b135Arun Sharmatemplate <typename RET, typename P1, typename P2, typename P3> 773842dac7333e42aa44531eda34ba55200b99ccf8Daniel Jacobowitzclass CheckerFn<RET(P1, P2, P3)> { 787d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris typedef RET (*Func)(void *, P1, P2, P3); 797d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferris Func Fn; 807d46a21e0a2cb561e4cad57b101a7137e01023dcChristopher Ferrispublic: 8137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerBase *Checker; 8237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 8337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } 8437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang}; 8537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 8637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangtemplate <typename RET, typename P1, typename P2> 879e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuuraclass CheckerFn<RET(P1, P2)> { 889e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura typedef RET (*Func)(void *, P1, P2); 8937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang Func Fn; 9037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangpublic: 9137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerBase *Checker; 9237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 9337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } 94c64723835c0c855fde5bec3d7528db64fe539015Konstantin Belousov}; 95752ce15c4fbe0e08c2d19df18caa86887732b3c8Konstantin Belousov 96752ce15c4fbe0e08c2d19df18caa86887732b3c8Konstantin Belousovtemplate <typename RET, typename P1> 9737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangclass CheckerFn<RET(P1)> { 9837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang typedef RET (*Func)(void *, P1); 9937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang Func Fn; 100649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharmapublic: 101649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma CheckerBase *Checker; 10237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 10337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang RET operator()(P1 p1) const { return Fn(Checker, p1); } 104649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma}; 105649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma 106649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharmatemplate <typename RET> 107649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharmaclass CheckerFn<RET()> { 108649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma typedef RET (*Func)(void *); 109649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharma Func Fn; 110649f1fb3449a65dd0626a709432d8b02a7c56bbcArun Sharmapublic: 11137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerBase *Checker; 11237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } 11337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang RET operator()() const { return Fn(Checker); } 11437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang}; 11537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 11637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang/// \brief Describes the different reasons a pointer escapes 11737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang/// during analysis. 11837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangenum PointerEscapeKind { 119ae5c1f2adf4da04235d87d024d4d942c01b2b447Lassi Tuura /// A pointer escapes due to binding its value to a location 12037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// that the analyzer cannot track. 12137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang PSK_EscapeOnBind, 122ae5c1f2adf4da04235d87d024d4d942c01b2b447Lassi Tuura 12337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// The pointer has been passed to a function call directly. 1248cdd8bfed8f21bb632faf69cca023c9762d78ab1Arun Sharma PSK_DirectEscapeOnCall, 12537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 12637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// The pointer has been passed to a function indirectly. 12737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// For example, the pointer is accessible through an 12837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// argument to a function. 12937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang PSK_IndirectEscapeOnCall, 13037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 13137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// The reason for pointer escape is unknown. For example, 13237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// a region containing this pointer is invalidated. 13337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang PSK_EscapeOther 13437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang}; 13537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 13637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tangclass CheckerManager { 13737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const LangOptions LangOpts; 1388cdd8bfed8f21bb632faf69cca023c9762d78ab1Arun Sharma AnalyzerOptionsRef AOptions; 1398cdd8bfed8f21bb632faf69cca023c9762d78ab1Arun Sharmapublic: 14037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerManager(const LangOptions &langOpts, 14137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang AnalyzerOptionsRef AOptions) 14237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang : LangOpts(langOpts), 14337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang AOptions(AOptions) {} 14437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 14537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ~CheckerManager(); 14637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 14737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang bool hasPathSensitiveCheckers() const; 14837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 14937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang void finishedCheckerRegistration(); 15037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 15137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const LangOptions &getLangOpts() const { return LangOpts; } 15237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang AnalyzerOptions &getAnalyzerOptions() { return *AOptions; } 15337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 15437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang typedef CheckerBase *CheckerRef; 15537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang typedef const void *CheckerTag; 15637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang typedef CheckerFn<void ()> CheckerDtor; 15737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 15837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===----------------------------------------------------------------------===// 15937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// registerChecker 16037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===----------------------------------------------------------------------===// 16137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 16237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \brief Used to register checkers. 16337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// 16437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \returns a pointer to the checker object. 16537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang template <typename CHECKER> 16637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CHECKER *registerChecker() { 16737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerTag tag = getTag<CHECKER>(); 16837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerRef &ref = CheckerTags[tag]; 16937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang if (ref) 17037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang return static_cast<CHECKER *>(ref); // already registered. 17137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 17237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CHECKER *checker = new CHECKER(); 17337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 17437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CHECKER::_register(checker, *this); 17537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ref = checker; 17637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang return checker; 17737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang } 17837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 17937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang template <typename CHECKER> 18037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CHECKER *registerChecker(AnalyzerOptions &AOpts) { 18137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerTag tag = getTag<CHECKER>(); 18237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang CheckerRef &ref = CheckerTags[tag]; 18337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang if (ref) 18437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang return static_cast<CHECKER *>(ref); // already registered. 18537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 186e2962af9d31266761700b431da894421c0d757ecArun Sharma CHECKER *checker = new CHECKER(AOpts); 1875d0f376b08126b51a001d7cdfba1ec4e0d644f54Tommi Rantala CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); 18828f33c8ce0b654cf31d6beda9a612870662f3c56Lassi Tuura CHECKER::_register(checker, *this); 18937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ref = checker; 19037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang return checker; 19137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang } 19237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 193d93d96ad833390519ea68a2df22dd55dd26a3214Martin Milata//===----------------------------------------------------------------------===// 19437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang// Functions for running checkers for AST traversing.. 19537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang//===----------------------------------------------------------------------===// 19637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 197dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /// \brief Run checkers handling Decls. 198dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 199dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura BugReporter &BR); 200dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 201dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /// \brief Run checkers handling Decls containing a Stmt body. 202dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 203dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura BugReporter &BR); 204dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 205dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura//===----------------------------------------------------------------------===// 2069e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura// Functions for running checkers for path-sensitive checking. 2075f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura//===----------------------------------------------------------------------===// 208ae5c1f2adf4da04235d87d024d4d942c01b2b447Lassi Tuura 20937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \brief Run checkers for pre-visiting Stmts. 21037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// 21137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// The notification is performed for every explored CFGElement, which does 21237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// not include the control flow statements such as IfStmt. 21337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// 21437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \sa runCheckersForBranchCondition, runCheckersForPostStmt 21537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang void runCheckersForPreStmt(ExplodedNodeSet &Dst, 21637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const ExplodedNodeSet &Src, 21737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const Stmt *S, 21837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ExprEngine &Eng) { 21937be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); 22037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang } 22137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 22237be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \brief Run checkers for post-visiting Stmts. 22337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// 22437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// The notification is performed for every explored CFGElement, which does 22537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// not include the control flow statements such as IfStmt. 22637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// 22737be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang /// \sa runCheckersForBranchCondition, runCheckersForPreStmt 22837be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang void runCheckersForPostStmt(ExplodedNodeSet &Dst, 2295d0f376b08126b51a001d7cdfba1ec4e0d644f54Tommi Rantala const ExplodedNodeSet &Src, 23037be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const Stmt *S, 23137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ExprEngine &Eng, 23228f33c8ce0b654cf31d6beda9a612870662f3c56Lassi Tuura bool wasInlined = false) { 23337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); 23437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang } 23537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang 236ae5c1f2adf4da04235d87d024d4d942c01b2b447Lassi Tuura /// \brief Run checkers for visiting Stmts. 23716b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris void runCheckersForStmt(bool isPreVisit, 238f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 239f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris const Stmt *S, ExprEngine &Eng, 240f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris bool wasInlined = false); 241f4a8df5f4f338f1a12c25213227e98b34b42447fChristopher Ferris 24216b95a68caaa7e021209e2cd6a877ae1e558f740Christopher Ferris /// \brief Run checkers for pre-visiting obj-c messages. 24337be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, 24437be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const ExplodedNodeSet &Src, 24537be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang const ObjCMethodCall &msg, 24637be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang ExprEngine &Eng) { 247dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng); 248dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura } 249dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura 250dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura /// \brief Run checkers for post-visiting obj-c messages. 251dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, 252dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura const ExplodedNodeSet &Src, 253dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura const ObjCMethodCall &msg, 2549e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura ExprEngine &Eng, 2559e98f15e9aee12e67cd5956d06ccb559f6a06213Lassi Tuura bool wasInlined = false) { 256dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng, 257dac2d001afb1fa7040ca7d8ae57032f684d7023eLassi Tuura wasInlined); 258e2962af9d31266761700b431da894421c0d757ecArun Sharma } 2595f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura 2605f38f35d5d6c78aafa6da20845d9ceff74af00f8Lassi Tuura /// \brief Run checkers for visiting obj-c messages. 26137be21c01ebe23402d4b5f1391e7a83da34e8c32David Mosberger-Tang void runCheckersForObjCMessage(bool isPreVisit, 262 ExplodedNodeSet &Dst, 263 const ExplodedNodeSet &Src, 264 const ObjCMethodCall &msg, ExprEngine &Eng, 265 bool wasInlined = false); 266 267 /// \brief Run checkers for pre-visiting obj-c messages. 268 void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 269 const CallEvent &Call, ExprEngine &Eng) { 270 runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); 271 } 272 273 /// \brief Run checkers for post-visiting obj-c messages. 274 void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, 275 const CallEvent &Call, ExprEngine &Eng, 276 bool wasInlined = false) { 277 runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng, 278 wasInlined); 279 } 280 281 /// \brief Run checkers for visiting obj-c messages. 282 void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, 283 const ExplodedNodeSet &Src, 284 const CallEvent &Call, ExprEngine &Eng, 285 bool wasInlined = false); 286 287 /// \brief Run checkers for load/store of a location. 288 void runCheckersForLocation(ExplodedNodeSet &Dst, 289 const ExplodedNodeSet &Src, 290 SVal location, 291 bool isLoad, 292 const Stmt *NodeEx, 293 const Stmt *BoundEx, 294 ExprEngine &Eng); 295 296 /// \brief Run checkers for binding of a value to a location. 297 void runCheckersForBind(ExplodedNodeSet &Dst, 298 const ExplodedNodeSet &Src, 299 SVal location, SVal val, 300 const Stmt *S, ExprEngine &Eng, 301 const ProgramPoint &PP); 302 303 /// \brief Run checkers for end of analysis. 304 void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, 305 ExprEngine &Eng); 306 307 /// \brief Run checkers on end of function. 308 void runCheckersForEndFunction(NodeBuilderContext &BC, 309 ExplodedNodeSet &Dst, 310 ExplodedNode *Pred, 311 ExprEngine &Eng); 312 313 /// \brief Run checkers for branch condition. 314 void runCheckersForBranchCondition(const Stmt *condition, 315 ExplodedNodeSet &Dst, ExplodedNode *Pred, 316 ExprEngine &Eng); 317 318 /// \brief Run checkers for live symbols. 319 /// 320 /// Allows modifying SymbolReaper object. For example, checkers can explicitly 321 /// register symbols of interest as live. These symbols will not be marked 322 /// dead and removed. 323 void runCheckersForLiveSymbols(ProgramStateRef state, 324 SymbolReaper &SymReaper); 325 326 /// \brief Run checkers for dead symbols. 327 /// 328 /// Notifies checkers when symbols become dead. For example, this allows 329 /// checkers to aggressively clean up/reduce the checker state and produce 330 /// precise diagnostics. 331 void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 332 const ExplodedNodeSet &Src, 333 SymbolReaper &SymReaper, const Stmt *S, 334 ExprEngine &Eng, 335 ProgramPoint::Kind K); 336 337 /// \brief True if at least one checker wants to check region changes. 338 bool wantsRegionChangeUpdate(ProgramStateRef state); 339 340 /// \brief Run checkers for region changes. 341 /// 342 /// This corresponds to the check::RegionChanges callback. 343 /// \param state The current program state. 344 /// \param invalidated A set of all symbols potentially touched by the change. 345 /// \param ExplicitRegions The regions explicitly requested for invalidation. 346 /// For example, in the case of a function call, these would be arguments. 347 /// \param Regions The transitive closure of accessible regions, 348 /// i.e. all regions that may have been touched by this change. 349 /// \param Call The call expression wrapper if the regions are invalidated 350 /// by a call. 351 ProgramStateRef 352 runCheckersForRegionChanges(ProgramStateRef state, 353 const InvalidatedSymbols *invalidated, 354 ArrayRef<const MemRegion *> ExplicitRegions, 355 ArrayRef<const MemRegion *> Regions, 356 const CallEvent *Call); 357 358 /// \brief Run checkers when pointers escape. 359 /// 360 /// This notifies the checkers about pointer escape, which occurs whenever 361 /// the analyzer cannot track the symbol any more. For example, as a 362 /// result of assigning a pointer into a global or when it's passed to a 363 /// function call the analyzer cannot model. 364 /// 365 /// \param State The state at the point of escape. 366 /// \param Escaped The list of escaped symbols. 367 /// \param Call The corresponding CallEvent, if the symbols escape as 368 /// parameters to the given call. 369 /// \param IsConst Specifies if the pointer is const. 370 /// \returns Checkers can modify the state by returning a new one. 371 ProgramStateRef 372 runCheckersForPointerEscape(ProgramStateRef State, 373 const InvalidatedSymbols &Escaped, 374 const CallEvent *Call, 375 PointerEscapeKind Kind, 376 bool IsConst = false); 377 378 /// \brief Run checkers for handling assumptions on symbolic values. 379 ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, 380 SVal Cond, bool Assumption); 381 382 /// \brief Run checkers for evaluating a call. 383 /// 384 /// Warning: Currently, the CallEvent MUST come from a CallExpr! 385 void runCheckersForEvalCall(ExplodedNodeSet &Dst, 386 const ExplodedNodeSet &Src, 387 const CallEvent &CE, ExprEngine &Eng); 388 389 /// \brief Run checkers for the entire Translation Unit. 390 void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, 391 AnalysisManager &mgr, 392 BugReporter &BR); 393 394 /// \brief Run checkers for debug-printing a ProgramState. 395 /// 396 /// Unlike most other callbacks, any checker can simply implement the virtual 397 /// method CheckerBase::printState if it has custom data to print. 398 /// \param Out The output stream 399 /// \param State The state being printed 400 /// \param NL The preferred representation of a newline. 401 /// \param Sep The preferred separator between different kinds of data. 402 void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State, 403 const char *NL, const char *Sep); 404 405//===----------------------------------------------------------------------===// 406// Internal registration functions for AST traversing. 407//===----------------------------------------------------------------------===// 408 409 // Functions used by the registration mechanism, checkers should not touch 410 // these directly. 411 412 typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> 413 CheckDeclFunc; 414 415 typedef bool (*HandlesDeclFunc)(const Decl *D); 416 void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); 417 418 void _registerForBody(CheckDeclFunc checkfn); 419 420//===----------------------------------------------------------------------===// 421// Internal registration functions for path-sensitive checking. 422//===----------------------------------------------------------------------===// 423 424 typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; 425 426 typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)> 427 CheckObjCMessageFunc; 428 429 typedef CheckerFn<void (const CallEvent &, CheckerContext &)> 430 CheckCallFunc; 431 432 typedef CheckerFn<void (const SVal &location, bool isLoad, 433 const Stmt *S, 434 CheckerContext &)> 435 CheckLocationFunc; 436 437 typedef CheckerFn<void (const SVal &location, const SVal &val, 438 const Stmt *S, CheckerContext &)> 439 CheckBindFunc; 440 441 typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> 442 CheckEndAnalysisFunc; 443 444 typedef CheckerFn<void (CheckerContext &)> 445 CheckEndFunctionFunc; 446 447 typedef CheckerFn<void (const Stmt *, CheckerContext &)> 448 CheckBranchConditionFunc; 449 450 typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> 451 CheckDeadSymbolsFunc; 452 453 typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; 454 455 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 456 const InvalidatedSymbols *symbols, 457 ArrayRef<const MemRegion *> ExplicitRegions, 458 ArrayRef<const MemRegion *> Regions, 459 const CallEvent *Call)> 460 CheckRegionChangesFunc; 461 462 typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc; 463 464 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 465 const InvalidatedSymbols &Escaped, 466 const CallEvent *Call, 467 PointerEscapeKind Kind, 468 bool IsConst)> 469 CheckPointerEscapeFunc; 470 471 typedef CheckerFn<ProgramStateRef (ProgramStateRef, 472 const SVal &cond, bool assumption)> 473 EvalAssumeFunc; 474 475 typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> 476 EvalCallFunc; 477 478 typedef CheckerFn<void (const TranslationUnitDecl *, 479 AnalysisManager&, BugReporter &)> 480 CheckEndOfTranslationUnit; 481 482 typedef bool (*HandlesStmtFunc)(const Stmt *D); 483 void _registerForPreStmt(CheckStmtFunc checkfn, 484 HandlesStmtFunc isForStmtFn); 485 void _registerForPostStmt(CheckStmtFunc checkfn, 486 HandlesStmtFunc isForStmtFn); 487 488 void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn); 489 void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn); 490 491 void _registerForPreCall(CheckCallFunc checkfn); 492 void _registerForPostCall(CheckCallFunc checkfn); 493 494 void _registerForLocation(CheckLocationFunc checkfn); 495 496 void _registerForBind(CheckBindFunc checkfn); 497 498 void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); 499 500 void _registerForEndFunction(CheckEndFunctionFunc checkfn); 501 502 void _registerForBranchCondition(CheckBranchConditionFunc checkfn); 503 504 void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); 505 506 void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); 507 508 void _registerForRegionChanges(CheckRegionChangesFunc checkfn, 509 WantsRegionChangeUpdateFunc wantUpdateFn); 510 511 void _registerForPointerEscape(CheckPointerEscapeFunc checkfn); 512 513 void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn); 514 515 void _registerForEvalAssume(EvalAssumeFunc checkfn); 516 517 void _registerForEvalCall(EvalCallFunc checkfn); 518 519 void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn); 520 521//===----------------------------------------------------------------------===// 522// Internal registration functions for events. 523//===----------------------------------------------------------------------===// 524 525 typedef void *EventTag; 526 typedef CheckerFn<void (const void *event)> CheckEventFunc; 527 528 template <typename EVENT> 529 void _registerListenerForEvent(CheckEventFunc checkfn) { 530 EventInfo &info = Events[getTag<EVENT>()]; 531 info.Checkers.push_back(checkfn); 532 } 533 534 template <typename EVENT> 535 void _registerDispatcherForEvent() { 536 EventInfo &info = Events[getTag<EVENT>()]; 537 info.HasDispatcher = true; 538 } 539 540 template <typename EVENT> 541 void _dispatchEvent(const EVENT &event) const { 542 EventsTy::const_iterator I = Events.find(getTag<EVENT>()); 543 if (I == Events.end()) 544 return; 545 const EventInfo &info = I->second; 546 for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) 547 info.Checkers[i](&event); 548 } 549 550//===----------------------------------------------------------------------===// 551// Implementation details. 552//===----------------------------------------------------------------------===// 553 554private: 555 template <typename CHECKER> 556 static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } 557 558 template <typename T> 559 static void *getTag() { static int tag; return &tag; } 560 561 llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; 562 563 std::vector<CheckerDtor> CheckerDtors; 564 565 struct DeclCheckerInfo { 566 CheckDeclFunc CheckFn; 567 HandlesDeclFunc IsForDeclFn; 568 }; 569 std::vector<DeclCheckerInfo> DeclCheckers; 570 571 std::vector<CheckDeclFunc> BodyCheckers; 572 573 typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; 574 typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; 575 CachedDeclCheckersMapTy CachedDeclCheckersMap; 576 577 struct StmtCheckerInfo { 578 CheckStmtFunc CheckFn; 579 HandlesStmtFunc IsForStmtFn; 580 bool IsPreVisit; 581 }; 582 std::vector<StmtCheckerInfo> StmtCheckers; 583 584 struct CachedStmtCheckersKey { 585 unsigned StmtKind; 586 bool IsPreVisit; 587 588 CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } 589 CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) 590 : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } 591 592 static CachedStmtCheckersKey getSentinel() { 593 return CachedStmtCheckersKey(~0U, 0); 594 } 595 unsigned getHashValue() const { 596 llvm::FoldingSetNodeID ID; 597 ID.AddInteger(StmtKind); 598 ID.AddBoolean(IsPreVisit); 599 return ID.ComputeHash(); 600 } 601 bool operator==(const CachedStmtCheckersKey &RHS) const { 602 return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; 603 } 604 }; 605 friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; 606 607 typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; 608 typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> 609 CachedStmtCheckersMapTy; 610 CachedStmtCheckersMapTy CachedStmtCheckersMap; 611 612 CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); 613 614 std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; 615 std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; 616 617 std::vector<CheckCallFunc> PreCallCheckers; 618 std::vector<CheckCallFunc> PostCallCheckers; 619 620 std::vector<CheckLocationFunc> LocationCheckers; 621 622 std::vector<CheckBindFunc> BindCheckers; 623 624 std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; 625 626 std::vector<CheckEndFunctionFunc> EndFunctionCheckers; 627 628 std::vector<CheckBranchConditionFunc> BranchConditionCheckers; 629 630 std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; 631 632 std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; 633 634 struct RegionChangesCheckerInfo { 635 CheckRegionChangesFunc CheckFn; 636 WantsRegionChangeUpdateFunc WantUpdateFn; 637 }; 638 std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; 639 640 std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers; 641 642 std::vector<EvalAssumeFunc> EvalAssumeCheckers; 643 644 std::vector<EvalCallFunc> EvalCallCheckers; 645 646 std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers; 647 648 struct EventInfo { 649 SmallVector<CheckEventFunc, 4> Checkers; 650 bool HasDispatcher; 651 EventInfo() : HasDispatcher(false) { } 652 }; 653 654 typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; 655 EventsTy Events; 656}; 657 658} // end ento namespace 659 660} // end clang namespace 661 662namespace llvm { 663 /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key 664 /// in DenseMap and DenseSets. 665 template <> 666 struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { 667 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 668 getEmptyKey() { 669 return clang::ento::CheckerManager::CachedStmtCheckersKey(); 670 } 671 static inline clang::ento::CheckerManager::CachedStmtCheckersKey 672 getTombstoneKey() { 673 return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); 674 } 675 676 static unsigned 677 getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { 678 return S.getHashValue(); 679 } 680 681 static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, 682 clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { 683 return LHS == RHS; 684 } 685 }; 686} // end namespace llvm 687 688#endif 689