summaryrefslogtreecommitdiffstats
path: root/include/clang/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang/StaticAnalyzer')
-rw-r--r--include/clang/StaticAnalyzer/Checkers/CheckerBase.td39
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ClangCheckers.h22
-rw-r--r--include/clang/StaticAnalyzer/Checkers/LocalCheckers.h28
-rw-r--r--include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h234
-rw-r--r--include/clang/StaticAnalyzer/Core/Analyses.def57
-rw-r--r--include/clang/StaticAnalyzer/Core/AnalyzerOptions.h567
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h561
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h366
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/BugType.h81
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h25
-rw-r--r--include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h848
-rw-r--r--include/clang/StaticAnalyzer/Core/Checker.h554
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerManager.h632
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerOptInfo.h44
-rw-r--r--include/clang/StaticAnalyzer/Core/CheckerRegistry.h140
-rw-r--r--include/clang/StaticAnalyzer/Core/IssueHash.h51
-rw-r--r--include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h40
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h109
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h135
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h200
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h60
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h1091
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h349
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h49
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h188
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h547
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h52
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h57
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h127
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h497
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h646
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h140
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h36
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h1370
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h854
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h245
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h43
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h333
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h574
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/Store.h288
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h51
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h162
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h61
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h681
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h46
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h27
-rw-r--r--include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h100
-rw-r--r--include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h49
-rw-r--r--include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h33
-rw-r--r--include/clang/StaticAnalyzer/Frontend/FrontendActions.h60
-rw-r--r--include/clang/StaticAnalyzer/Frontend/ModelConsumer.h44
51 files changed, 0 insertions, 13593 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
deleted file mode 100644
index 11f1e5d..0000000
--- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td
+++ /dev/null
@@ -1,39 +0,0 @@
-//===--- CheckerBase.td - Checker TableGen classes ------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the TableGen core definitions for checkers
-//
-//===----------------------------------------------------------------------===//
-
-class CheckerGroup<string name> {
- string GroupName = name;
-}
-class InGroup<CheckerGroup G> { CheckerGroup Group = G; }
-
-class Package<string name> {
- string PackageName = name;
- bit Hidden = 0;
- Package ParentPackage;
- CheckerGroup Group;
-}
-class InPackage<Package P> { Package ParentPackage = P; }
-
-// All checkers are an indirect subclass of this.
-class Checker<string name = ""> {
- string CheckerName = name;
- string DescFile;
- string HelpText;
- bit Hidden = 0;
- Package ParentPackage;
- CheckerGroup Group;
-}
-
-class DescFile<string filename> { string DescFile = filename; }
-class HelpText<string text> { string HelpText = text; }
-class Hidden { bit Hidden = 1; }
diff --git a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h b/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
deleted file mode 100644
index cf0a30a..0000000
--- a/include/clang/StaticAnalyzer/Checkers/ClangCheckers.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//===--- ClangCheckers.h - Provides builtin checkers ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
-#define LLVM_CLANG_STATICANALYZER_CHECKERS_CLANGCHECKERS_H
-
-namespace clang {
-namespace ento {
-class CheckerRegistry;
-
-void registerBuiltinCheckers(CheckerRegistry &registry);
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
deleted file mode 100644
index 463f04a..0000000
--- a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//==- LocalCheckers.h - Intra-Procedural+Flow-Sensitive Checkers -*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interface to call a set of intra-procedural (local)
-// checkers that use flow/path-sensitive analyses to find bugs.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_LOCALCHECKERS_H
-#define LLVM_CLANG_STATICANALYZER_CHECKERS_LOCALCHECKERS_H
-
-namespace clang {
-namespace ento {
-
-class ExprEngine;
-
-void RegisterCallInliner(ExprEngine &Eng);
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
deleted file mode 100644
index 5850656..0000000
--- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h
+++ /dev/null
@@ -1,234 +0,0 @@
-//==-- ObjCRetainCount.h - Retain count summaries for Cocoa -------*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the core data structures for retain count "summaries"
-// for Objective-C and Core Foundation APIs. These summaries are used
-// by the static analyzer to summarize the retain/release effects of
-// function and method calls. This drives a path-sensitive typestate
-// analysis in the static analyzer, but can also potentially be used by
-// other clients.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
-#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-
-namespace clang {
-class FunctionDecl;
-class ObjCMethodDecl;
-
-namespace ento { namespace objc_retain {
-
-/// An ArgEffect summarizes the retain count behavior on an argument or receiver
-/// to a function or method.
-enum ArgEffect {
- /// There is no effect.
- DoNothing,
-
- /// The argument is treated as if an -autorelease message had been sent to
- /// the referenced object.
- Autorelease,
-
- /// The argument is treated as if an -dealloc message had been sent to
- /// the referenced object.
- Dealloc,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if CFRelease has been called on the argument.
- DecRef,
-
- /// The argument has its reference count decreased by 1. This is as
- /// if a -release message has been sent to the argument. This differs
- /// in behavior from DecRef when GC is enabled.
- DecRefMsg,
-
- /// The argument has its reference count decreased by 1 to model
- /// a transferred bridge cast under ARC.
- DecRefBridgedTransferred,
-
- /// The argument has its reference count increased by 1. This is as
- /// if a -retain message has been sent to the argument. This differs
- /// in behavior from IncRef when GC is enabled.
- IncRefMsg,
-
- /// The argument has its reference count increased by 1. This is as
- /// if CFRetain has been called on the argument.
- IncRef,
-
- /// The argument acts as if has been passed to CFMakeCollectable, which
- /// transfers the object to the Garbage Collector under GC.
- MakeCollectable,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +0 value or NULL.
- UnretainedOutParameter,
-
- /// The argument is a pointer to a retain-counted object; on exit, the new
- /// value of the pointer is a +1 value or NULL.
- RetainedOutParameter,
-
- /// The argument is treated as potentially escaping, meaning that
- /// even when its reference count hits 0 it should be treated as still
- /// possibly being alive as someone else *may* be holding onto the object.
- MayEscape,
-
- /// All typestate tracking of the object ceases. This is usually employed
- /// when the effect of the call is completely unknown.
- StopTracking,
-
- /// All typestate tracking of the object ceases. Unlike StopTracking,
- /// this is also enforced when the method body is inlined.
- ///
- /// In some cases, we obtain a better summary for this checker
- /// by looking at the call site than by inlining the function.
- /// Signifies that we should stop tracking the symbol even if
- /// the function is inlined.
- StopTrackingHard,
-
- /// Performs the combined functionality of DecRef and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefAndStopTrackingHard,
-
- /// Performs the combined functionality of DecRefMsg and StopTrackingHard.
- ///
- /// The models the effect that the called function decrements the reference
- /// count of the argument and all typestate tracking on that argument
- /// should cease.
- DecRefMsgAndStopTrackingHard
-};
-
-/// RetEffect summarizes a call's retain/release behavior with respect
-/// to its return value.
-class RetEffect {
-public:
- enum Kind {
- /// Indicates that no retain count information is tracked for
- /// the return value.
- NoRet,
- /// Indicates that the returned value is an owned (+1) symbol.
- OwnedSymbol,
- /// Indicates that the returned value is an owned (+1) symbol and
- /// that it should be treated as freshly allocated.
- OwnedAllocatedSymbol,
- /// Indicates that the returned value is an object with retain count
- /// semantics but that it is not owned (+0). This is the default
- /// for getters, etc.
- NotOwnedSymbol,
- /// Indicates that the object is not owned and controlled by the
- /// Garbage collector.
- GCNotOwnedSymbol,
- /// Indicates that the return value is an owned object when the
- /// receiver is also a tracked object.
- OwnedWhenTrackedReceiver,
- // Treat this function as returning a non-tracked symbol even if
- // the function has been inlined. This is used where the call
- // site summary is more presise than the summary indirectly produced
- // by inlining the function
- NoRetHard
- };
-
- /// Determines the object kind of a tracked object.
- enum ObjKind {
- /// Indicates that the tracked object is a CF object. This is
- /// important between GC and non-GC code.
- CF,
- /// Indicates that the tracked object is an Objective-C object.
- ObjC,
- /// Indicates that the tracked object could be a CF or Objective-C object.
- AnyObj
- };
-
-private:
- Kind K;
- ObjKind O;
-
- RetEffect(Kind k, ObjKind o = AnyObj) : K(k), O(o) {}
-
-public:
- Kind getKind() const { return K; }
-
- ObjKind getObjKind() const { return O; }
-
- bool isOwned() const {
- return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
- K == OwnedWhenTrackedReceiver;
- }
-
- bool notOwned() const {
- return K == NotOwnedSymbol;
- }
-
- bool operator==(const RetEffect &Other) const {
- return K == Other.K && O == Other.O;
- }
-
- static RetEffect MakeOwnedWhenTrackedReceiver() {
- return RetEffect(OwnedWhenTrackedReceiver, ObjC);
- }
-
- static RetEffect MakeOwned(ObjKind o, bool isAllocated = false) {
- return RetEffect(isAllocated ? OwnedAllocatedSymbol : OwnedSymbol, o);
- }
- static RetEffect MakeNotOwned(ObjKind o) {
- return RetEffect(NotOwnedSymbol, o);
- }
- static RetEffect MakeGCNotOwned() {
- return RetEffect(GCNotOwnedSymbol, ObjC);
- }
- static RetEffect MakeNoRet() {
- return RetEffect(NoRet);
- }
- static RetEffect MakeNoRetHard() {
- return RetEffect(NoRetHard);
- }
-};
-
-/// Encapsulates the retain count semantics on the arguments, return value,
-/// and receiver (if any) of a function/method call.
-///
-/// Note that construction of these objects is not highly efficient. That
-/// is okay for clients where creating these objects isn't really a bottleneck.
-/// The purpose of the API is to provide something simple. The actual
-/// static analyzer checker that implements retain/release typestate
-/// tracking uses something more efficient.
-class CallEffects {
- llvm::SmallVector<ArgEffect, 10> Args;
- RetEffect Ret;
- ArgEffect Receiver;
-
- CallEffects(const RetEffect &R) : Ret(R) {}
-
-public:
- /// Returns the argument effects for a call.
- ArrayRef<ArgEffect> getArgs() const { return Args; }
-
- /// Returns the effects on the receiver.
- ArgEffect getReceiver() const { return Receiver; }
-
- /// Returns the effect on the return value.
- RetEffect getReturnValue() const { return Ret; }
-
- /// Return the CallEfect for a given Objective-C method.
- static CallEffects getEffect(const ObjCMethodDecl *MD);
-
- /// Return the CallEfect for a given C/C++ function.
- static CallEffects getEffect(const FunctionDecl *FD);
-};
-
-}}}
-
-#endif
-
diff --git a/include/clang/StaticAnalyzer/Core/Analyses.def b/include/clang/StaticAnalyzer/Core/Analyses.def
deleted file mode 100644
index 3355f4b..0000000
--- a/include/clang/StaticAnalyzer/Core/Analyses.def
+++ /dev/null
@@ -1,57 +0,0 @@
-//===-- Analyses.def - Metadata about Static Analyses -----------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the set of static analyses used by AnalysisConsumer.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ANALYSIS_STORE
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN)
-#endif
-
-ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateRegionStoreManager)
-
-#ifndef ANALYSIS_CONSTRAINTS
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN)
-#endif
-
-ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager)
-
-#ifndef ANALYSIS_DIAGNOSTICS
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)
-#endif
-
-ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer)
-ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer)
-
-#ifndef ANALYSIS_PURGE
-#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC)
-#endif
-
-ANALYSIS_PURGE(PurgeStmt, "statement", "Purge symbols, bindings, and constraints before every statement")
-ANALYSIS_PURGE(PurgeBlock, "block", "Purge symbols, bindings, and constraints before every basic block")
-ANALYSIS_PURGE(PurgeNone, "none", "Do not purge symbols, bindings, or constraints")
-
-#ifndef ANALYSIS_INLINING_MODE
-#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC)
-#endif
-
-ANALYSIS_INLINING_MODE(All, "all", "Analyze all functions as top level")
-ANALYSIS_INLINING_MODE(NoRedundancy, "noredundancy", "Do not analyze a function which has been previously inlined")
-
-#undef ANALYSIS_STORE
-#undef ANALYSIS_CONSTRAINTS
-#undef ANALYSIS_DIAGNOSTICS
-#undef ANALYSIS_PURGE
-#undef ANALYSIS_INLINING_MODE
-#undef ANALYSIS_IPA
-
diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
deleted file mode 100644
index 3959de2..0000000
--- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ /dev/null
@@ -1,567 +0,0 @@
-//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header defines various options for the static analyzer that are set
-// by the frontend and are consulted throughout the analyzer.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
-#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringMap.h"
-#include <string>
-#include <vector>
-
-namespace clang {
-class ASTConsumer;
-class DiagnosticsEngine;
-class Preprocessor;
-class LangOptions;
-
-namespace ento {
-class CheckerBase;
-}
-
-/// Analysis - Set of available source code analyses.
-enum Analyses {
-#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) NAME,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-NumAnalyses
-};
-
-/// AnalysisStores - Set of available analysis store models.
-enum AnalysisStores {
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-NumStores
-};
-
-/// AnalysisConstraints - Set of available constraint models.
-enum AnalysisConstraints {
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) NAME##Model,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-NumConstraints
-};
-
-/// AnalysisDiagClients - Set of available diagnostic clients for rendering
-/// analysis results.
-enum AnalysisDiagClients {
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-PD_NONE,
-NUM_ANALYSIS_DIAG_CLIENTS
-};
-
-/// AnalysisPurgeModes - Set of available strategies for dead symbol removal.
-enum AnalysisPurgeMode {
-#define ANALYSIS_PURGE(NAME, CMDFLAG, DESC) NAME,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-NumPurgeModes
-};
-
-/// AnalysisInlineFunctionSelection - Set of inlining function selection heuristics.
-enum AnalysisInliningMode {
-#define ANALYSIS_INLINING_MODE(NAME, CMDFLAG, DESC) NAME,
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-NumInliningModes
-};
-
-/// \brief Describes the different kinds of C++ member functions which can be
-/// considered for inlining by the analyzer.
-///
-/// These options are cumulative; enabling one kind of member function will
-/// enable all kinds with lower enum values.
-enum CXXInlineableMemberKind {
- // Uninitialized = 0,
-
- /// A dummy mode in which no C++ inlining is enabled.
- CIMK_None = 1,
-
- /// Refers to regular member function and operator calls.
- CIMK_MemberFunctions,
-
- /// Refers to constructors (implicit or explicit).
- ///
- /// Note that a constructor will not be inlined if the corresponding
- /// destructor is non-trivial.
- CIMK_Constructors,
-
- /// Refers to destructors (implicit or explicit).
- CIMK_Destructors
-};
-
-/// \brief Describes the different modes of inter-procedural analysis.
-enum IPAKind {
- IPAK_NotSet = 0,
-
- /// Perform only intra-procedural analysis.
- IPAK_None = 1,
-
- /// Inline C functions and blocks when their definitions are available.
- IPAK_BasicInlining = 2,
-
- /// Inline callees(C, C++, ObjC) when their definitions are available.
- IPAK_Inlining = 3,
-
- /// Enable inlining of dynamically dispatched methods.
- IPAK_DynamicDispatch = 4,
-
- /// Enable inlining of dynamically dispatched methods, bifurcate paths when
- /// exact type info is unavailable.
- IPAK_DynamicDispatchBifurcate = 5
-};
-
-class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> {
-public:
- typedef llvm::StringMap<std::string> ConfigTable;
-
- /// \brief Pair of checker name and enable/disable.
- std::vector<std::pair<std::string, bool> > CheckersControlList;
-
- /// \brief A key-value table of use-specified configuration values.
- ConfigTable Config;
- AnalysisStores AnalysisStoreOpt;
- AnalysisConstraints AnalysisConstraintsOpt;
- AnalysisDiagClients AnalysisDiagOpt;
- AnalysisPurgeMode AnalysisPurgeOpt;
-
- std::string AnalyzeSpecificFunction;
-
- /// \brief The maximum number of times the analyzer visits a block.
- unsigned maxBlockVisitOnPath;
-
-
- /// \brief Disable all analyzer checks.
- ///
- /// This flag allows one to disable analyzer checks on the code processed by
- /// the given analysis consumer. Note, the code will get parsed and the
- /// command-line options will get checked.
- unsigned DisableAllChecks : 1;
-
- unsigned ShowCheckerHelp : 1;
- unsigned AnalyzeAll : 1;
- unsigned AnalyzerDisplayProgress : 1;
- unsigned AnalyzeNestedBlocks : 1;
-
- /// \brief The flag regulates if we should eagerly assume evaluations of
- /// conditionals, thus, bifurcating the path.
- ///
- /// This flag indicates how the engine should handle expressions such as: 'x =
- /// (y != 0)'. When this flag is true then the subexpression 'y != 0' will be
- /// eagerly assumed to be true or false, thus evaluating it to the integers 0
- /// or 1 respectively. The upside is that this can increase analysis
- /// precision until we have a better way to lazily evaluate such logic. The
- /// downside is that it eagerly bifurcates paths.
- unsigned eagerlyAssumeBinOpBifurcation : 1;
-
- unsigned TrimGraph : 1;
- unsigned visualizeExplodedGraphWithGraphViz : 1;
- unsigned visualizeExplodedGraphWithUbiGraph : 1;
- unsigned UnoptimizedCFG : 1;
- unsigned PrintStats : 1;
-
- /// \brief Do not re-analyze paths leading to exhausted nodes with a different
- /// strategy. We get better code coverage when retry is enabled.
- unsigned NoRetryExhausted : 1;
-
- /// \brief The inlining stack depth limit.
- unsigned InlineMaxStackDepth;
-
- /// \brief The mode of function selection used during inlining.
- AnalysisInliningMode InliningMode;
-
-private:
- /// \brief Describes the kinds for high-level analyzer mode.
- enum UserModeKind {
- UMK_NotSet = 0,
- /// Perform shallow but fast analyzes.
- UMK_Shallow = 1,
- /// Perform deep analyzes.
- UMK_Deep = 2
- };
-
- /// Controls the high-level analyzer mode, which influences the default
- /// settings for some of the lower-level config options (such as IPAMode).
- /// \sa getUserMode
- UserModeKind UserMode;
-
- /// Controls the mode of inter-procedural analysis.
- IPAKind IPAMode;
-
- /// Controls which C++ member functions will be considered for inlining.
- CXXInlineableMemberKind CXXMemberInliningMode;
-
- /// \sa includeTemporaryDtorsInCFG
- Optional<bool> IncludeTemporaryDtorsInCFG;
-
- /// \sa mayInlineCXXStandardLibrary
- Optional<bool> InlineCXXStandardLibrary;
-
- /// \sa mayInlineTemplateFunctions
- Optional<bool> InlineTemplateFunctions;
-
- /// \sa mayInlineCXXAllocator
- Optional<bool> InlineCXXAllocator;
-
- /// \sa mayInlineCXXContainerMethods
- Optional<bool> InlineCXXContainerMethods;
-
- /// \sa mayInlineCXXSharedPtrDtor
- Optional<bool> InlineCXXSharedPtrDtor;
-
- /// \sa mayInlineObjCMethod
- Optional<bool> ObjCInliningMode;
-
- // Cache of the "ipa-always-inline-size" setting.
- // \sa getAlwaysInlineSize
- Optional<unsigned> AlwaysInlineSize;
-
- /// \sa shouldSuppressNullReturnPaths
- Optional<bool> SuppressNullReturnPaths;
-
- // \sa getMaxInlinableSize
- Optional<unsigned> MaxInlinableSize;
-
- /// \sa shouldAvoidSuppressingNullArgumentPaths
- Optional<bool> AvoidSuppressingNullArgumentPaths;
-
- /// \sa shouldSuppressInlinedDefensiveChecks
- Optional<bool> SuppressInlinedDefensiveChecks;
-
- /// \sa shouldSuppressFromCXXStandardLibrary
- Optional<bool> SuppressFromCXXStandardLibrary;
-
- /// \sa reportIssuesInMainSourceFile
- Optional<bool> ReportIssuesInMainSourceFile;
-
- /// \sa StableReportFilename
- Optional<bool> StableReportFilename;
-
- /// \sa getGraphTrimInterval
- Optional<unsigned> GraphTrimInterval;
-
- /// \sa getMaxTimesInlineLarge
- Optional<unsigned> MaxTimesInlineLarge;
-
- /// \sa getMinCFGSizeTreatFunctionsAsLarge
- Optional<unsigned> MinCFGSizeTreatFunctionsAsLarge;
-
- /// \sa getMaxNodesPerTopLevelFunction
- Optional<unsigned> MaxNodesPerTopLevelFunction;
-
- /// \sa shouldInlineLambdas
- Optional<bool> InlineLambdas;
-
- /// \sa shouldWidenLoops
- Optional<bool> WidenLoops;
-
- /// A helper function that retrieves option for a given full-qualified
- /// checker name.
- /// Options for checkers can be specified via 'analyzer-config' command-line
- /// option.
- /// Example:
- /// @code-analyzer-config unix.Malloc:OptionName=CheckerOptionValue @endcode
- /// or @code-analyzer-config unix:OptionName=GroupOptionValue @endcode
- /// for groups of checkers.
- /// @param [in] CheckerName Full-qualified checker name, like
- /// alpha.unix.StreamChecker.
- /// @param [in] OptionName Name of the option to get.
- /// @param [in] Default Default value if no option is specified.
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- /// @retval CheckerOptionValue An option for a checker if it was specified.
- /// @retval GroupOptionValue An option for group if it was specified and no
- /// checker-specific options were found. The closer group to checker,
- /// the more priority it has. For example, @c coregroup.subgroup has more
- /// priority than @c coregroup for @c coregroup.subgroup.CheckerName checker.
- /// @retval Default If nor checker option, nor group option was found.
- StringRef getCheckerOption(StringRef CheckerName, StringRef OptionName,
- StringRef Default,
- bool SearchInParents = false);
-
-public:
- /// Interprets an option's string value as a boolean. The "true" string is
- /// interpreted as true and the "false" string is interpreted as false.
- ///
- /// If an option value is not provided, returns the given \p DefaultVal.
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- bool getBooleanOption(StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- /// Variant that accepts a Optional value to cache the result.
- ///
- /// @param [in,out] V Return value storage, returned if parameter contains
- /// an existing valid option, else it is used to store a return value
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- bool getBooleanOption(Optional<bool> &V, StringRef Name, bool DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- /// Interprets an option's string value as an integer value.
- ///
- /// If an option value is not provided, returns the given \p DefaultVal.
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- int getOptionAsInteger(StringRef Name, int DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- /// Query an option's string value.
- ///
- /// If an option value is not provided, returns the given \p DefaultVal.
- /// @param [in] Name Name for option to retrieve.
- /// @param [in] DefaultVal Default value returned if no such option was
- /// specified.
- /// @param [in] C The optional checker parameter that can be used to restrict
- /// the search to the options of this particular checker (and its parents
- /// dependening on search mode).
- /// @param [in] SearchInParents If set to true and the searched option was not
- /// specified for the given checker the options for the parent packages will
- /// be searched as well. The inner packages take precedence over the outer
- /// ones.
- StringRef getOptionAsString(StringRef Name, StringRef DefaultVal,
- const ento::CheckerBase *C = nullptr,
- bool SearchInParents = false);
-
- /// \brief Retrieves and sets the UserMode. This is a high-level option,
- /// which is used to set other low-level options. It is not accessible
- /// outside of AnalyzerOptions.
- UserModeKind getUserMode();
-
- /// \brief Returns the inter-procedural analysis mode.
- IPAKind getIPAMode();
-
- /// Returns the option controlling which C++ member functions will be
- /// considered for inlining.
- ///
- /// This is controlled by the 'c++-inlining' config option.
- ///
- /// \sa CXXMemberInliningMode
- bool mayInlineCXXMemberFunction(CXXInlineableMemberKind K);
-
- /// Returns true if ObjectiveC inlining is enabled, false otherwise.
- bool mayInlineObjCMethod();
-
- /// Returns whether or not the destructors for C++ temporary objects should
- /// be included in the CFG.
- ///
- /// This is controlled by the 'cfg-temporary-dtors' config option, which
- /// accepts the values "true" and "false".
- bool includeTemporaryDtorsInCFG();
-
- /// Returns whether or not C++ standard library functions may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-stdlib-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXStandardLibrary();
-
- /// Returns whether or not templated functions may be considered for inlining.
- ///
- /// This is controlled by the 'c++-template-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineTemplateFunctions();
-
- /// Returns whether or not allocator call may be considered for inlining.
- ///
- /// This is controlled by the 'c++-allocator-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXAllocator();
-
- /// Returns whether or not methods of C++ container objects may be considered
- /// for inlining.
- ///
- /// This is controlled by the 'c++-container-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXContainerMethods();
-
- /// Returns whether or not the destructor of C++ 'shared_ptr' may be
- /// considered for inlining.
- ///
- /// This covers std::shared_ptr, std::tr1::shared_ptr, and boost::shared_ptr,
- /// and indeed any destructor named "~shared_ptr".
- ///
- /// This is controlled by the 'c++-shared_ptr-inlining' config option, which
- /// accepts the values "true" and "false".
- bool mayInlineCXXSharedPtrDtor();
-
- /// Returns whether or not paths that go through null returns should be
- /// suppressed.
- ///
- /// This is a heuristic for avoiding bug reports with paths that go through
- /// inlined functions that are more defensive than their callers.
- ///
- /// This is controlled by the 'suppress-null-return-paths' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressNullReturnPaths();
-
- /// Returns whether a bug report should \em not be suppressed if its path
- /// includes a call with a null argument, even if that call has a null return.
- ///
- /// This option has no effect when #shouldSuppressNullReturnPaths() is false.
- ///
- /// This is a counter-heuristic to avoid false negatives.
- ///
- /// This is controlled by the 'avoid-suppressing-null-argument-paths' config
- /// option, which accepts the values "true" and "false".
- bool shouldAvoidSuppressingNullArgumentPaths();
-
- /// Returns whether or not diagnostics containing inlined defensive NULL
- /// checks should be suppressed.
- ///
- /// This is controlled by the 'suppress-inlined-defensive-checks' config
- /// option, which accepts the values "true" and "false".
- bool shouldSuppressInlinedDefensiveChecks();
-
- /// Returns whether or not diagnostics reported within the C++ standard
- /// library should be suppressed.
- ///
- /// This is controlled by the 'suppress-c++-stdlib' config option,
- /// which accepts the values "true" and "false".
- bool shouldSuppressFromCXXStandardLibrary();
-
- /// Returns whether or not the diagnostic report should be always reported
- /// in the main source file and not the headers.
- ///
- /// This is controlled by the 'report-in-main-source-file' config option,
- /// which accepts the values "true" and "false".
- bool shouldReportIssuesInMainSourceFile();
-
- /// Returns whether or not the report filename should be random or not.
- ///
- /// This is controlled by the 'stable-report-filename' config option,
- /// which accepts the values "true" and "false". Default = false
- bool shouldWriteStableReportFilename();
-
- /// Returns whether irrelevant parts of a bug report path should be pruned
- /// out of the final output.
- ///
- /// This is controlled by the 'prune-paths' config option, which accepts the
- /// values "true" and "false".
- bool shouldPrunePaths();
-
- /// Returns true if 'static' initializers should be in conditional logic
- /// in the CFG.
- bool shouldConditionalizeStaticInitializers();
-
- // Returns the size of the functions (in basic blocks), which should be
- // considered to be small enough to always inline.
- //
- // This is controlled by "ipa-always-inline-size" analyzer-config option.
- unsigned getAlwaysInlineSize();
-
- // Returns the bound on the number of basic blocks in an inlined function
- // (50 by default).
- //
- // This is controlled by "-analyzer-config max-inlinable-size" option.
- unsigned getMaxInlinableSize();
-
- /// Returns true if the analyzer engine should synthesize fake bodies
- /// for well-known functions.
- bool shouldSynthesizeBodies();
-
- /// Returns how often nodes in the ExplodedGraph should be recycled to save
- /// memory.
- ///
- /// This is controlled by the 'graph-trim-interval' config option. To disable
- /// node reclamation, set the option to "0".
- unsigned getGraphTrimInterval();
-
- /// Returns the maximum times a large function could be inlined.
- ///
- /// This is controlled by the 'max-times-inline-large' config option.
- unsigned getMaxTimesInlineLarge();
-
- /// Returns the number of basic blocks a function needs to have to be
- /// considered large for the 'max-times-inline-large' config option.
- ///
- /// This is controlled by the 'min-cfg-size-treat-functions-as-large' config
- /// option.
- unsigned getMinCFGSizeTreatFunctionsAsLarge();
-
- /// Returns the maximum number of nodes the analyzer can generate while
- /// exploring a top level function (for each exploded graph).
- /// 150000 is default; 0 means no limit.
- ///
- /// This is controlled by the 'max-nodes' config option.
- unsigned getMaxNodesPerTopLevelFunction();
-
- /// Returns true if lambdas should be inlined. Otherwise a sink node will be
- /// generated each time a LambdaExpr is visited.
- bool shouldInlineLambdas();
-
- /// Returns true if the analysis should try to widen loops.
- /// This is controlled by the 'widen-loops' config option.
- bool shouldWidenLoops();
-
-public:
- AnalyzerOptions() :
- AnalysisStoreOpt(RegionStoreModel),
- AnalysisConstraintsOpt(RangeConstraintsModel),
- AnalysisDiagOpt(PD_HTML),
- AnalysisPurgeOpt(PurgeStmt),
- DisableAllChecks(0),
- ShowCheckerHelp(0),
- AnalyzeAll(0),
- AnalyzerDisplayProgress(0),
- AnalyzeNestedBlocks(0),
- eagerlyAssumeBinOpBifurcation(0),
- TrimGraph(0),
- visualizeExplodedGraphWithGraphViz(0),
- visualizeExplodedGraphWithUbiGraph(0),
- UnoptimizedCFG(0),
- PrintStats(0),
- NoRetryExhausted(0),
- // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
- InlineMaxStackDepth(5),
- InliningMode(NoRedundancy),
- UserMode(UMK_NotSet),
- IPAMode(IPAK_NotSet),
- CXXMemberInliningMode() {}
-
-};
-
-typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef;
-
-}
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
deleted file mode 100644
index 57c73fd..0000000
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h
+++ /dev/null
@@ -1,561 +0,0 @@
-//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines BugReporter, a utility class for generating
-// PathDiagnostics for analyses based on ProgramState.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H
-
-#include "clang/Basic/SourceLocation.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/ImmutableSet.h"
-#include "llvm/ADT/SmallSet.h"
-#include "llvm/ADT/ilist.h"
-#include "llvm/ADT/ilist_node.h"
-
-namespace clang {
-
-class ASTContext;
-class DiagnosticsEngine;
-class Stmt;
-class ParentMap;
-
-namespace ento {
-
-class PathDiagnostic;
-class ExplodedNode;
-class ExplodedGraph;
-class BugReport;
-class BugReporter;
-class BugReporterContext;
-class ExprEngine;
-class BugType;
-
-//===----------------------------------------------------------------------===//
-// Interface for individual bug reports.
-//===----------------------------------------------------------------------===//
-
-/// This class provides an interface through which checkers can create
-/// individual bug reports.
-class BugReport : public llvm::ilist_node<BugReport> {
-public:
- class NodeResolver {
- virtual void anchor();
- public:
- virtual ~NodeResolver() {}
- virtual const ExplodedNode*
- getOriginalNode(const ExplodedNode *N) = 0;
- };
-
- typedef const SourceRange *ranges_iterator;
- typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList;
- typedef VisitorList::iterator visitor_iterator;
- typedef SmallVector<StringRef, 2> ExtraTextList;
-
-protected:
- friend class BugReporter;
- friend class BugReportEquivClass;
-
- BugType& BT;
- const Decl *DeclWithIssue;
- std::string ShortDescription;
- std::string Description;
- PathDiagnosticLocation Location;
- PathDiagnosticLocation UniqueingLocation;
- const Decl *UniqueingDecl;
-
- const ExplodedNode *ErrorNode;
- SmallVector<SourceRange, 4> Ranges;
- ExtraTextList ExtraText;
-
- typedef llvm::DenseSet<SymbolRef> Symbols;
- typedef llvm::DenseSet<const MemRegion *> Regions;
-
- /// A (stack of) a set of symbols that are registered with this
- /// report as being "interesting", and thus used to help decide which
- /// diagnostics to include when constructing the final path diagnostic.
- /// The stack is largely used by BugReporter when generating PathDiagnostics
- /// for multiple PathDiagnosticConsumers.
- SmallVector<Symbols *, 2> interestingSymbols;
-
- /// A (stack of) set of regions that are registered with this report as being
- /// "interesting", and thus used to help decide which diagnostics
- /// to include when constructing the final path diagnostic.
- /// The stack is largely used by BugReporter when generating PathDiagnostics
- /// for multiple PathDiagnosticConsumers.
- SmallVector<Regions *, 2> interestingRegions;
-
- /// A set of location contexts that correspoind to call sites which should be
- /// considered "interesting".
- llvm::SmallSet<const LocationContext *, 2> InterestingLocationContexts;
-
- /// A set of custom visitors which generate "event" diagnostics at
- /// interesting points in the path.
- VisitorList Callbacks;
-
- /// Used for ensuring the visitors are only added once.
- llvm::FoldingSet<BugReporterVisitor> CallbacksSet;
-
- /// Used for clients to tell if the report's configuration has changed
- /// since the last time they checked.
- unsigned ConfigurationChangeToken;
-
- /// When set, this flag disables all callstack pruning from a diagnostic
- /// path. This is useful for some reports that want maximum fidelty
- /// when reporting an issue.
- bool DoNotPrunePath;
-
- /// Used to track unique reasons why a bug report might be invalid.
- ///
- /// \sa markInvalid
- /// \sa removeInvalidation
- typedef std::pair<const void *, const void *> InvalidationRecord;
-
- /// If non-empty, this bug report is likely a false positive and should not be
- /// shown to the user.
- ///
- /// \sa markInvalid
- /// \sa removeInvalidation
- llvm::SmallSet<InvalidationRecord, 4> Invalidations;
-
-private:
- // Used internally by BugReporter.
- Symbols &getInterestingSymbols();
- Regions &getInterestingRegions();
-
- void lazyInitializeInterestingSets();
- void pushInterestingSymbolsAndRegions();
- void popInterestingSymbolsAndRegions();
-
-public:
- BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode),
- ConfigurationChangeToken(0), DoNotPrunePath(false) {}
-
- BugReport(BugType& bt, StringRef shortDesc, StringRef desc,
- const ExplodedNode *errornode)
- : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc),
- Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
-
- BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l)
- : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l),
- ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {}
-
- /// \brief Create a BugReport with a custom uniqueing location.
- ///
- /// The reports that have the same report location, description, bug type, and
- /// ranges are uniqued - only one of the equivalent reports will be presented
- /// to the user. This method allows to rest the location which should be used
- /// for uniquing reports. For example, memory leaks checker, could set this to
- /// the allocation site, rather then the location where the bug is reported.
- BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode,
- PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique)
- : BT(bt), DeclWithIssue(nullptr), Description(desc),
- UniqueingLocation(LocationToUnique),
- UniqueingDecl(DeclToUnique),
- ErrorNode(errornode), ConfigurationChangeToken(0),
- DoNotPrunePath(false) {}
-
- virtual ~BugReport();
-
- const BugType& getBugType() const { return BT; }
- BugType& getBugType() { return BT; }
-
- const ExplodedNode *getErrorNode() const { return ErrorNode; }
-
- StringRef getDescription() const { return Description; }
-
- StringRef getShortDescription(bool UseFallback = true) const {
- if (ShortDescription.empty() && UseFallback)
- return Description;
- return ShortDescription;
- }
-
- /// Indicates whether or not any path pruning should take place
- /// when generating a PathDiagnostic from this BugReport.
- bool shouldPrunePath() const { return !DoNotPrunePath; }
-
- /// Disable all path pruning when generating a PathDiagnostic.
- void disablePathPruning() { DoNotPrunePath = true; }
-
- void markInteresting(SymbolRef sym);
- void markInteresting(const MemRegion *R);
- void markInteresting(SVal V);
- void markInteresting(const LocationContext *LC);
-
- bool isInteresting(SymbolRef sym);
- bool isInteresting(const MemRegion *R);
- bool isInteresting(SVal V);
- bool isInteresting(const LocationContext *LC);
-
- unsigned getConfigurationChangeToken() const {
- return ConfigurationChangeToken;
- }
-
- /// Returns whether or not this report should be considered valid.
- ///
- /// Invalid reports are those that have been classified as likely false
- /// positives after the fact.
- bool isValid() const {
- return Invalidations.empty();
- }
-
- /// Marks the current report as invalid, meaning that it is probably a false
- /// positive and should not be reported to the user.
- ///
- /// The \p Tag and \p Data arguments are intended to be opaque identifiers for
- /// this particular invalidation, where \p Tag represents the visitor
- /// responsible for invalidation, and \p Data represents the reason this
- /// visitor decided to invalidate the bug report.
- ///
- /// \sa removeInvalidation
- void markInvalid(const void *Tag, const void *Data) {
- Invalidations.insert(std::make_pair(Tag, Data));
- }
-
- /// Reverses the effects of a previous invalidation.
- ///
- /// \sa markInvalid
- void removeInvalidation(const void *Tag, const void *Data) {
- Invalidations.erase(std::make_pair(Tag, Data));
- }
-
- /// Return the canonical declaration, be it a method or class, where
- /// this issue semantically occurred.
- const Decl *getDeclWithIssue() const;
-
- /// Specifically set the Decl where an issue occurred. This isn't necessary
- /// for BugReports that cover a path as it will be automatically inferred.
- void setDeclWithIssue(const Decl *declWithIssue) {
- DeclWithIssue = declWithIssue;
- }
-
- /// \brief This allows for addition of meta data to the diagnostic.
- ///
- /// Currently, only the HTMLDiagnosticClient knows how to display it.
- void addExtraText(StringRef S) {
- ExtraText.push_back(S);
- }
-
- virtual const ExtraTextList &getExtraText() {
- return ExtraText;
- }
-
- /// \brief Return the "definitive" location of the reported bug.
- ///
- /// While a bug can span an entire path, usually there is a specific
- /// location that can be used to identify where the key issue occurred.
- /// This location is used by clients rendering diagnostics.
- virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const;
-
- /// \brief Get the location on which the report should be uniqued.
- PathDiagnosticLocation getUniqueingLocation() const {
- return UniqueingLocation;
- }
-
- /// \brief Get the declaration containing the uniqueing location.
- const Decl *getUniqueingDecl() const {
- return UniqueingDecl;
- }
-
- const Stmt *getStmt() const;
-
- /// \brief Add a range to a bug report.
- ///
- /// Ranges are used to highlight regions of interest in the source code.
- /// They should be at the same source code line as the BugReport location.
- /// By default, the source range of the statement corresponding to the error
- /// node will be used; add a single invalid range to specify absence of
- /// ranges.
- void addRange(SourceRange R) {
- assert((R.isValid() || Ranges.empty()) && "Invalid range can only be used "
- "to specify that the report does not have a range.");
- Ranges.push_back(R);
- }
-
- /// \brief Get the SourceRanges associated with the report.
- virtual llvm::iterator_range<ranges_iterator> getRanges();
-
- /// \brief Add custom or predefined bug report visitors to this report.
- ///
- /// The visitors should be used when the default trace is not sufficient.
- /// For example, they allow constructing a more elaborate trace.
- /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(),
- /// registerFindLastStore(), registerNilReceiverVisitor(), and
- /// registerVarDeclsLastStore().
- void addVisitor(std::unique_ptr<BugReporterVisitor> visitor);
-
- /// Iterators through the custom diagnostic visitors.
- visitor_iterator visitor_begin() { return Callbacks.begin(); }
- visitor_iterator visitor_end() { return Callbacks.end(); }
-
- /// Profile to identify equivalent bug reports for error report coalescing.
- /// Reports are uniqued to ensure that we do not emit multiple diagnostics
- /// for each bug.
- virtual void Profile(llvm::FoldingSetNodeID& hash) const;
-};
-
-} // end ento namespace
-} // end clang namespace
-
-namespace llvm {
- template<> struct ilist_traits<clang::ento::BugReport>
- : public ilist_default_traits<clang::ento::BugReport> {
- clang::ento::BugReport *createSentinel() const {
- return static_cast<clang::ento::BugReport *>(&Sentinel);
- }
- void destroySentinel(clang::ento::BugReport *) const {}
-
- clang::ento::BugReport *provideInitialHead() const {
- return createSentinel();
- }
- clang::ento::BugReport *ensureHead(clang::ento::BugReport *) const {
- return createSentinel();
- }
- private:
- mutable ilist_half_node<clang::ento::BugReport> Sentinel;
- };
-}
-
-namespace clang {
-namespace ento {
-
-//===----------------------------------------------------------------------===//
-// BugTypes (collections of related reports).
-//===----------------------------------------------------------------------===//
-
-class BugReportEquivClass : public llvm::FoldingSetNode {
- /// List of *owned* BugReport objects.
- llvm::ilist<BugReport> Reports;
-
- friend class BugReporter;
- void AddReport(std::unique_ptr<BugReport> R) {
- Reports.push_back(R.release());
- }
-
-public:
- BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); }
- ~BugReportEquivClass();
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- assert(!Reports.empty());
- Reports.front().Profile(ID);
- }
-
- typedef llvm::ilist<BugReport>::iterator iterator;
- typedef llvm::ilist<BugReport>::const_iterator const_iterator;
-
- iterator begin() { return Reports.begin(); }
- iterator end() { return Reports.end(); }
-
- const_iterator begin() const { return Reports.begin(); }
- const_iterator end() const { return Reports.end(); }
-};
-
-//===----------------------------------------------------------------------===//
-// BugReporter and friends.
-//===----------------------------------------------------------------------===//
-
-class BugReporterData {
-public:
- virtual ~BugReporterData();
- virtual DiagnosticsEngine& getDiagnostic() = 0;
- virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0;
- virtual ASTContext &getASTContext() = 0;
- virtual SourceManager& getSourceManager() = 0;
- virtual AnalyzerOptions& getAnalyzerOptions() = 0;
-};
-
-/// BugReporter is a utility class for generating PathDiagnostics for analysis.
-/// It collects the BugReports and BugTypes and knows how to generate
-/// and flush the corresponding diagnostics.
-class BugReporter {
-public:
- enum Kind { BaseBRKind, GRBugReporterKind };
-
-private:
- typedef llvm::ImmutableSet<BugType*> BugTypesTy;
- BugTypesTy::Factory F;
- BugTypesTy BugTypes;
-
- const Kind kind;
- BugReporterData& D;
-
- /// Generate and flush the diagnostics for the given bug report.
- void FlushReport(BugReportEquivClass& EQ);
-
- /// Generate and flush the diagnostics for the given bug report
- /// and PathDiagnosticConsumer.
- void FlushReport(BugReport *exampleReport,
- PathDiagnosticConsumer &PD,
- ArrayRef<BugReport*> BugReports);
-
- /// The set of bug reports tracked by the BugReporter.
- llvm::FoldingSet<BugReportEquivClass> EQClasses;
- /// A vector of BugReports for tracking the allocated pointers and cleanup.
- std::vector<BugReportEquivClass *> EQClassesVector;
-
-protected:
- BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k),
- D(d) {}
-
-public:
- BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind),
- D(d) {}
- virtual ~BugReporter();
-
- /// \brief Generate and flush diagnostics for all bug reports.
- void FlushReports();
-
- Kind getKind() const { return kind; }
-
- DiagnosticsEngine& getDiagnostic() {
- return D.getDiagnostic();
- }
-
- ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() {
- return D.getPathDiagnosticConsumers();
- }
-
- /// \brief Iterator over the set of BugTypes tracked by the BugReporter.
- typedef BugTypesTy::iterator iterator;
- iterator begin() { return BugTypes.begin(); }
- iterator end() { return BugTypes.end(); }
-
- /// \brief Iterator over the set of BugReports tracked by the BugReporter.
- typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator;
- EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); }
- EQClasses_iterator EQClasses_end() { return EQClasses.end(); }
-
- ASTContext &getContext() { return D.getASTContext(); }
-
- SourceManager& getSourceManager() { return D.getSourceManager(); }
-
- AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); }
-
- virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic,
- PathDiagnosticConsumer &PC,
- ArrayRef<BugReport *> &bugReports) {
- return true;
- }
-
- bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R);
-
- void Register(BugType *BT);
-
- /// \brief Add the given report to the set of reports tracked by BugReporter.
- ///
- /// The reports are usually generated by the checkers. Further, they are
- /// folded based on the profile value, which is done to coalesce similar
- /// reports.
- void emitReport(std::unique_ptr<BugReport> R);
-
- void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker,
- StringRef BugName, StringRef BugCategory,
- StringRef BugStr, PathDiagnosticLocation Loc,
- ArrayRef<SourceRange> Ranges = None);
-
- void EmitBasicReport(const Decl *DeclWithIssue, CheckName CheckName,
- StringRef BugName, StringRef BugCategory,
- StringRef BugStr, PathDiagnosticLocation Loc,
- ArrayRef<SourceRange> Ranges = None);
-
-private:
- llvm::StringMap<BugType *> StrBugTypes;
-
- /// \brief Returns a BugType that is associated with the given name and
- /// category.
- BugType *getBugTypeForName(CheckName CheckName, StringRef name,
- StringRef category);
-};
-
-// FIXME: Get rid of GRBugReporter. It's the wrong abstraction.
-class GRBugReporter : public BugReporter {
- ExprEngine& Eng;
-public:
- GRBugReporter(BugReporterData& d, ExprEngine& eng)
- : BugReporter(d, GRBugReporterKind), Eng(eng) {}
-
- ~GRBugReporter() override;
-
- /// getEngine - Return the analysis engine used to analyze a given
- /// function or method.
- ExprEngine &getEngine() { return Eng; }
-
- /// getGraph - Get the exploded graph created by the analysis engine
- /// for the analyzed method or function.
- ExplodedGraph &getGraph();
-
- /// getStateManager - Return the state manager used by the analysis
- /// engine.
- ProgramStateManager &getStateManager();
-
- /// Generates a path corresponding to one of the given bug reports.
- ///
- /// Which report is used for path generation is not specified. The
- /// bug reporter will try to pick the shortest path, but this is not
- /// guaranteed.
- ///
- /// \return True if the report was valid and a path was generated,
- /// false if the reports should be considered invalid.
- bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC,
- ArrayRef<BugReport*> &bugReports) override;
-
- /// classof - Used by isa<>, cast<>, and dyn_cast<>.
- static bool classof(const BugReporter* R) {
- return R->getKind() == GRBugReporterKind;
- }
-};
-
-class BugReporterContext {
- virtual void anchor();
- GRBugReporter &BR;
-public:
- BugReporterContext(GRBugReporter& br) : BR(br) {}
-
- virtual ~BugReporterContext() {}
-
- GRBugReporter& getBugReporter() { return BR; }
-
- ExplodedGraph &getGraph() { return BR.getGraph(); }
-
- ProgramStateManager& getStateManager() {
- return BR.getStateManager();
- }
-
- SValBuilder& getSValBuilder() {
- return getStateManager().getSValBuilder();
- }
-
- ASTContext &getASTContext() {
- return BR.getContext();
- }
-
- SourceManager& getSourceManager() {
- return BR.getSourceManager();
- }
-
- virtual BugReport::NodeResolver& getNodeResolver() = 0;
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
deleted file mode 100644
index 197d27a..0000000
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h
+++ /dev/null
@@ -1,366 +0,0 @@
-//===--- BugReporterVisitor.h - Generate PathDiagnostics -------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares BugReporterVisitors, which are used to generate enhanced
-// diagnostic traces.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/ADT/FoldingSet.h"
-
-namespace clang {
-
-namespace ento {
-
-class BugReport;
-class BugReporterContext;
-class ExplodedNode;
-class MemRegion;
-class PathDiagnosticPiece;
-
-/// \brief BugReporterVisitors are used to add custom diagnostics along a path.
-///
-/// Custom visitors should subclass the BugReporterVisitorImpl class for a
-/// default implementation of the clone() method.
-/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
-/// default implementation of clone() will NOT do the right thing, and you
-/// will have to provide your own implementation.)
-class BugReporterVisitor : public llvm::FoldingSetNode {
-public:
- BugReporterVisitor() = default;
- BugReporterVisitor(const BugReporterVisitor &) = default;
- BugReporterVisitor(BugReporterVisitor &&) {}
- virtual ~BugReporterVisitor();
-
- /// \brief Returns a copy of this BugReporter.
- ///
- /// Custom BugReporterVisitors should not override this method directly.
- /// Instead, they should inherit from BugReporterVisitorImpl and provide
- /// a protected or public copy constructor.
- ///
- /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
- /// default implementation of clone() will NOT do the right thing, and you
- /// will have to provide your own implementation.)
- virtual std::unique_ptr<BugReporterVisitor> clone() const = 0;
-
- /// \brief Return a diagnostic piece which should be associated with the
- /// given node.
- ///
- /// The last parameter can be used to register a new visitor with the given
- /// BugReport while processing a node.
- virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
- BugReporterContext &BRC,
- BugReport &BR) = 0;
-
- /// \brief Provide custom definition for the final diagnostic piece on the
- /// path - the piece, which is displayed before the path is expanded.
- ///
- /// If returns NULL the default implementation will be used.
- /// Also note that at most one visitor of a BugReport should generate a
- /// non-NULL end of path diagnostic piece.
- virtual std::unique_ptr<PathDiagnosticPiece>
- getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR);
-
- virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0;
-
- /// \brief Generates the default final diagnostic piece.
- static std::unique_ptr<PathDiagnosticPiece>
- getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N,
- BugReport &BR);
-};
-
-/// This class provides a convenience implementation for clone() using the
-/// Curiously-Recurring Template Pattern. If you are implementing a custom
-/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public
-/// or protected copy constructor.
-///
-/// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the
-/// default implementation of clone() will NOT do the right thing, and you
-/// will have to provide your own implementation.)
-template <class DERIVED>
-class BugReporterVisitorImpl : public BugReporterVisitor {
- std::unique_ptr<BugReporterVisitor> clone() const override {
- return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this));
- }
-};
-
-class FindLastStoreBRVisitor final
- : public BugReporterVisitorImpl<FindLastStoreBRVisitor> {
- const MemRegion *R;
- SVal V;
- bool Satisfied;
-
- /// If the visitor is tracking the value directly responsible for the
- /// bug, we are going to employ false positive suppression.
- bool EnableNullFPSuppression;
-
-public:
- /// Creates a visitor for every VarDecl inside a Stmt and registers it with
- /// the BugReport.
- static void registerStatementVarDecls(BugReport &BR, const Stmt *S,
- bool EnableNullFPSuppression);
-
- FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R,
- bool InEnableNullFPSuppression)
- : R(R),
- V(V),
- Satisfied(false),
- EnableNullFPSuppression(InEnableNullFPSuppression) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-};
-
-class TrackConstraintBRVisitor final
- : public BugReporterVisitorImpl<TrackConstraintBRVisitor> {
- DefinedSVal Constraint;
- bool Assumption;
- bool IsSatisfied;
- bool IsZeroCheck;
-
- /// We should start tracking from the last node along the path in which the
- /// value is constrained.
- bool IsTrackingTurnedOn;
-
-public:
- TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption)
- : Constraint(constraint), Assumption(assumption), IsSatisfied(false),
- IsZeroCheck(!Assumption && Constraint.getAs<Loc>()),
- IsTrackingTurnedOn(false) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- /// Return the tag associated with this visitor. This tag will be used
- /// to make all PathDiagnosticPieces created by this visitor.
- static const char *getTag();
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-
-private:
- /// Checks if the constraint is valid in the current state.
- bool isUnderconstrained(const ExplodedNode *N) const;
-
-};
-
-/// \class NilReceiverBRVisitor
-/// \brief Prints path notes when a message is sent to a nil receiver.
-class NilReceiverBRVisitor final
- : public BugReporterVisitorImpl<NilReceiverBRVisitor> {
-public:
-
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int x = 0;
- ID.AddPointer(&x);
- }
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-
- /// If the statement is a message send expression with nil receiver, returns
- /// the receiver expression. Returns NULL otherwise.
- static const Expr *getNilReceiver(const Stmt *S, const ExplodedNode *N);
-};
-
-/// Visitor that tries to report interesting diagnostics from conditions.
-class ConditionBRVisitor final
- : public BugReporterVisitorImpl<ConditionBRVisitor> {
-public:
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int x = 0;
- ID.AddPointer(&x);
- }
-
- /// Return the tag associated with this visitor. This tag will be used
- /// to make all PathDiagnosticPieces created by this visitor.
- static const char *getTag();
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR) override;
-
- PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR);
-
- PathDiagnosticPiece *VisitTerminator(const Stmt *Term,
- const ExplodedNode *N,
- const CFGBlock *srcBlk,
- const CFGBlock *dstBlk,
- BugReport &R,
- BugReporterContext &BRC);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- bool tookTrue,
- BugReporterContext &BRC,
- BugReport &R,
- const ExplodedNode *N);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- const DeclRefExpr *DR,
- const bool tookTrue,
- BugReporterContext &BRC,
- BugReport &R,
- const ExplodedNode *N);
-
- PathDiagnosticPiece *VisitTrueTest(const Expr *Cond,
- const BinaryOperator *BExpr,
- const bool tookTrue,
- BugReporterContext &BRC,
- BugReport &R,
- const ExplodedNode *N);
-
- PathDiagnosticPiece *VisitConditionVariable(StringRef LhsString,
- const Expr *CondVarExpr,
- const bool tookTrue,
- BugReporterContext &BRC,
- BugReport &R,
- const ExplodedNode *N);
-
- bool patternMatch(const Expr *Ex,
- raw_ostream &Out,
- BugReporterContext &BRC,
- BugReport &R,
- const ExplodedNode *N,
- Optional<bool> &prunable);
-};
-
-/// \brief Suppress reports that might lead to known false positives.
-///
-/// Currently this suppresses reports based on locations of bugs.
-class LikelyFalsePositiveSuppressionBRVisitor final
- : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> {
-public:
- static void *getTag() {
- static int Tag = 0;
- return static_cast<void *>(&Tag);
- }
-
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- ID.AddPointer(getTag());
- }
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *Prev,
- BugReporterContext &BRC,
- BugReport &BR) override {
- return nullptr;
- }
-
- std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC,
- const ExplodedNode *N,
- BugReport &BR) override;
-};
-
-/// \brief When a region containing undefined value or '0' value is passed
-/// as an argument in a call, marks the call as interesting.
-///
-/// As a result, BugReporter will not prune the path through the function even
-/// if the region's contents are not modified/accessed by the call.
-class UndefOrNullArgVisitor final
- : public BugReporterVisitorImpl<UndefOrNullArgVisitor> {
-
- /// The interesting memory region this visitor is tracking.
- const MemRegion *R;
-
-public:
- UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {}
-
- void Profile(llvm::FoldingSetNodeID &ID) const override {
- static int Tag = 0;
- ID.AddPointer(&Tag);
- ID.AddPointer(R);
- }
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
- const ExplodedNode *PrevN,
- BugReporterContext &BRC,
- BugReport &BR) override;
-};
-
-class SuppressInlineDefensiveChecksVisitor final
- : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> {
- /// The symbolic value for which we are tracking constraints.
- /// This value is constrained to null in the end of path.
- DefinedSVal V;
-
- /// Track if we found the node where the constraint was first added.
- bool IsSatisfied;
-
- /// Since the visitors can be registered on nodes previous to the last
- /// node in the BugReport, but the path traversal always starts with the last
- /// node, the visitor invariant (that we start with a node in which V is null)
- /// might not hold when node visitation starts. We are going to start tracking
- /// from the last node in which the value is null.
- bool IsTrackingTurnedOn;
-
-public:
- SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N);
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- /// Return the tag associated with this visitor. This tag will be used
- /// to make all PathDiagnosticPieces created by this visitor.
- static const char *getTag();
-
- PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ,
- const ExplodedNode *Pred,
- BugReporterContext &BRC,
- BugReport &BR) override;
-};
-
-namespace bugreporter {
-
-/// Attempts to add visitors to trace a null or undefined value back to its
-/// point of origin, whether it is a symbol constrained to null or an explicit
-/// assignment.
-///
-/// \param N A node "downstream" from the evaluation of the statement.
-/// \param S The statement whose value is null or undefined.
-/// \param R The bug report to which visitors should be attached.
-/// \param IsArg Whether the statement is an argument to an inlined function.
-/// If this is the case, \p N \em must be the CallEnter node for
-/// the function.
-/// \param EnableNullFPSuppression Whether we should employ false positive
-/// suppression (inlined defensive checks, returned null).
-///
-/// \return Whether or not the function was able to add visitors for this
-/// statement. Note that returning \c true does not actually imply
-/// that any visitors were added.
-bool trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R,
- bool IsArg = false,
- bool EnableNullFPSuppression = true);
-
-const Expr *getDerefExpr(const Stmt *S);
-const Stmt *GetDenomExpr(const ExplodedNode *N);
-const Stmt *GetRetValExpr(const ExplodedNode *N);
-bool isDeclRefExprToReference(const Expr *E);
-
-
-} // end namespace clang
-} // end namespace ento
-} // end namespace bugreporter
-
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
deleted file mode 100644
index 16226e9..0000000
--- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines BugType, a class representing a bug type.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H
-
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "llvm/ADT/FoldingSet.h"
-#include <string>
-
-namespace clang {
-
-namespace ento {
-
-class BugReporter;
-class ExplodedNode;
-class ExprEngine;
-
-class BugType {
-private:
- const CheckName Check;
- const std::string Name;
- const std::string Category;
- bool SuppressonSink;
-
- virtual void anchor();
-public:
- BugType(class CheckName check, StringRef name, StringRef cat)
- : Check(check), Name(name), Category(cat), SuppressonSink(false) {}
- BugType(const CheckerBase *checker, StringRef name, StringRef cat)
- : Check(checker->getCheckName()), Name(name), Category(cat),
- SuppressonSink(false) {}
- virtual ~BugType() {}
-
- // FIXME: Should these be made strings as well?
- StringRef getName() const { return Name; }
- StringRef getCategory() const { return Category; }
- StringRef getCheckName() const { return Check.getName(); }
-
- /// isSuppressOnSink - Returns true if bug reports associated with this bug
- /// type should be suppressed if the end node of the report is post-dominated
- /// by a sink node.
- bool isSuppressOnSink() const { return SuppressonSink; }
- void setSuppressOnSink(bool x) { SuppressonSink = x; }
-
- virtual void FlushReports(BugReporter& BR);
-};
-
-class BuiltinBug : public BugType {
- const std::string desc;
- void anchor() override;
-public:
- BuiltinBug(class CheckName check, const char *name, const char *description)
- : BugType(check, name, categories::LogicError), desc(description) {}
-
- BuiltinBug(const CheckerBase *checker, const char *name,
- const char *description)
- : BugType(checker, name, categories::LogicError), desc(description) {}
-
- BuiltinBug(const CheckerBase *checker, const char *name)
- : BugType(checker, name, categories::LogicError), desc(name) {}
-
- StringRef getDescription() const { return desc; }
-};
-
-} // end GR namespace
-
-} // end clang namespace
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
deleted file mode 100644
index 8df2bc3..0000000
--- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//=--- CommonBugCategories.h - Provides common issue categories -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H
-
-// Common strings used for the "category" of many static analyzer issues.
-namespace clang {
- namespace ento {
- namespace categories {
- extern const char * const CoreFoundationObjectiveC;
- extern const char * const LogicError;
- extern const char * const MemoryCoreFoundationObjectiveC;
- extern const char * const UnixAPI;
- }
- }
-}
-#endif
-
diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
deleted file mode 100644
index 35421f9..0000000
--- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ /dev/null
@@ -1,848 +0,0 @@
-//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the PathDiagnostic-related interfaces.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
-#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H
-
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/PointerUnion.h"
-#include <deque>
-#include <iterator>
-#include <list>
-#include <string>
-#include <vector>
-
-namespace clang {
-class ConditionalOperator;
-class AnalysisDeclContext;
-class BinaryOperator;
-class CompoundStmt;
-class Decl;
-class LocationContext;
-class MemberExpr;
-class ParentMap;
-class ProgramPoint;
-class SourceManager;
-class Stmt;
-class CallExpr;
-
-namespace ento {
-
-class ExplodedNode;
-class SymExpr;
-typedef const SymExpr* SymbolRef;
-
-//===----------------------------------------------------------------------===//
-// High-level interface for handlers of path-sensitive diagnostics.
-//===----------------------------------------------------------------------===//
-
-class PathDiagnostic;
-
-class PathDiagnosticConsumer {
-public:
- class PDFileEntry : public llvm::FoldingSetNode {
- public:
- PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {}
-
- typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles;
-
- /// \brief A vector of <consumer,file> pairs.
- ConsumerFiles files;
-
- /// \brief A precomputed hash tag used for uniquing PDFileEntry objects.
- const llvm::FoldingSetNodeID NodeID;
-
- /// \brief Used for profiling in the FoldingSet.
- void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; }
- };
-
- class FilesMade {
- llvm::BumpPtrAllocator Alloc;
- llvm::FoldingSet<PDFileEntry> Set;
-
- public:
- ~FilesMade();
-
- bool empty() const { return Set.empty(); }
-
- void addDiagnostic(const PathDiagnostic &PD,
- StringRef ConsumerName,
- StringRef fileName);
-
- PDFileEntry::ConsumerFiles *getFiles(const PathDiagnostic &PD);
- };
-
-private:
- virtual void anchor();
-public:
- PathDiagnosticConsumer() : flushed(false) {}
- virtual ~PathDiagnosticConsumer();
-
- void FlushDiagnostics(FilesMade *FilesMade);
-
- virtual void FlushDiagnosticsImpl(std::vector<const PathDiagnostic *> &Diags,
- FilesMade *filesMade) = 0;
-
- virtual StringRef getName() const = 0;
-
- void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D);
-
- enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive };
- virtual PathGenerationScheme getGenerationScheme() const { return Minimal; }
- virtual bool supportsLogicalOpControlFlow() const { return false; }
-
- /// Return true if the PathDiagnosticConsumer supports individual
- /// PathDiagnostics that span multiple files.
- virtual bool supportsCrossFileDiagnostics() const { return false; }
-
-protected:
- bool flushed;
- llvm::FoldingSet<PathDiagnostic> Diags;
-};
-
-//===----------------------------------------------------------------------===//
-// Path-sensitive diagnostics.
-//===----------------------------------------------------------------------===//
-
-class PathDiagnosticRange : public SourceRange {
-public:
- bool isPoint;
-
- PathDiagnosticRange(SourceRange R, bool isP = false)
- : SourceRange(R), isPoint(isP) {}
-
- PathDiagnosticRange() : isPoint(false) {}
-};
-
-typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*>
- LocationOrAnalysisDeclContext;
-
-class PathDiagnosticLocation {
-private:
- enum Kind { RangeK, SingleLocK, StmtK, DeclK } K;
- const Stmt *S;
- const Decl *D;
- const SourceManager *SM;
- FullSourceLoc Loc;
- PathDiagnosticRange Range;
-
- PathDiagnosticLocation(SourceLocation L, const SourceManager &sm,
- Kind kind)
- : K(kind), S(nullptr), D(nullptr), SM(&sm),
- Loc(genLocation(L)), Range(genRange()) {
- }
-
- FullSourceLoc genLocation(
- SourceLocation L = SourceLocation(),
- LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
-
- PathDiagnosticRange genRange(
- LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const;
-
-public:
- /// Create an invalid location.
- PathDiagnosticLocation()
- : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {}
-
- /// Create a location corresponding to the given statement.
- PathDiagnosticLocation(const Stmt *s,
- const SourceManager &sm,
- LocationOrAnalysisDeclContext lac)
- : K(s->getLocStart().isValid() ? StmtK : SingleLocK),
- S(K == StmtK ? s : nullptr),
- D(nullptr), SM(&sm),
- Loc(genLocation(SourceLocation(), lac)),
- Range(genRange(lac)) {
- assert(K == SingleLocK || S);
- assert(K == SingleLocK || Loc.isValid());
- assert(K == SingleLocK || Range.isValid());
- }
-
- /// Create a location corresponding to the given declaration.
- PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
- : K(DeclK), S(nullptr), D(d), SM(&sm),
- Loc(genLocation()), Range(genRange()) {
- assert(D);
- assert(Loc.isValid());
- assert(Range.isValid());
- }
-
- /// Create a location at an explicit offset in the source.
- ///
- /// This should only be used if there are no more appropriate constructors.
- PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm)
- : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm),
- Range(genRange()) {
- assert(Loc.isValid());
- assert(Range.isValid());
- }
-
- /// Create a location corresponding to the given declaration.
- static PathDiagnosticLocation create(const Decl *D,
- const SourceManager &SM) {
- return PathDiagnosticLocation(D, SM);
- }
-
- /// Create a location for the beginning of the declaration.
- static PathDiagnosticLocation createBegin(const Decl *D,
- const SourceManager &SM);
-
- /// Create a location for the beginning of the statement.
- static PathDiagnosticLocation createBegin(const Stmt *S,
- const SourceManager &SM,
- const LocationOrAnalysisDeclContext LAC);
-
- /// Create a location for the end of the statement.
- ///
- /// If the statement is a CompoundStatement, the location will point to the
- /// closing brace instead of following it.
- static PathDiagnosticLocation createEnd(const Stmt *S,
- const SourceManager &SM,
- const LocationOrAnalysisDeclContext LAC);
-
- /// Create the location for the operator of the binary expression.
- /// Assumes the statement has a valid location.
- static PathDiagnosticLocation createOperatorLoc(const BinaryOperator *BO,
- const SourceManager &SM);
- static PathDiagnosticLocation createConditionalColonLoc(
- const ConditionalOperator *CO,
- const SourceManager &SM);
-
- /// For member expressions, return the location of the '.' or '->'.
- /// Assumes the statement has a valid location.
- static PathDiagnosticLocation createMemberLoc(const MemberExpr *ME,
- const SourceManager &SM);
-
- /// Create a location for the beginning of the compound statement.
- /// Assumes the statement has a valid location.
- static PathDiagnosticLocation createBeginBrace(const CompoundStmt *CS,
- const SourceManager &SM);
-
- /// Create a location for the end of the compound statement.
- /// Assumes the statement has a valid location.
- static PathDiagnosticLocation createEndBrace(const CompoundStmt *CS,
- const SourceManager &SM);
-
- /// Create a location for the beginning of the enclosing declaration body.
- /// Defaults to the beginning of the first statement in the declaration body.
- static PathDiagnosticLocation createDeclBegin(const LocationContext *LC,
- const SourceManager &SM);
-
- /// Constructs a location for the end of the enclosing declaration body.
- /// Defaults to the end of brace.
- static PathDiagnosticLocation createDeclEnd(const LocationContext *LC,
- const SourceManager &SM);
-
- /// Create a location corresponding to the given valid ExplodedNode.
- static PathDiagnosticLocation create(const ProgramPoint& P,
- const SourceManager &SMng);
-
- /// Create a location corresponding to the next valid ExplodedNode as end
- /// of path location.
- static PathDiagnosticLocation createEndOfPath(const ExplodedNode* N,
- const SourceManager &SM);
-
- /// Convert the given location into a single kind location.
- static PathDiagnosticLocation createSingleLocation(
- const PathDiagnosticLocation &PDL);
-
- bool operator==(const PathDiagnosticLocation &X) const {
- return K == X.K && Loc == X.Loc && Range == X.Range;
- }
-
- bool operator!=(const PathDiagnosticLocation &X) const {
- return !(*this == X);
- }
-
- bool isValid() const {
- return SM != nullptr;
- }
-
- FullSourceLoc asLocation() const {
- return Loc;
- }
-
- PathDiagnosticRange asRange() const {
- return Range;
- }
-
- const Stmt *asStmt() const { assert(isValid()); return S; }
- const Decl *asDecl() const { assert(isValid()); return D; }
-
- bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; }
-
- void invalidate() {
- *this = PathDiagnosticLocation();
- }
-
- void flatten();
-
- const SourceManager& getManager() const { assert(isValid()); return *SM; }
-
- void Profile(llvm::FoldingSetNodeID &ID) const;
-
- void dump() const;
-
- /// \brief Given an exploded node, retrieve the statement that should be used
- /// for the diagnostic location.
- static const Stmt *getStmt(const ExplodedNode *N);
-
- /// \brief Retrieve the statement corresponding to the successor node.
- static const Stmt *getNextStmt(const ExplodedNode *N);
-};
-
-class PathDiagnosticLocationPair {
-private:
- PathDiagnosticLocation Start, End;
-public:
- PathDiagnosticLocationPair(const PathDiagnosticLocation &start,
- const PathDiagnosticLocation &end)
- : Start(start), End(end) {}
-
- const PathDiagnosticLocation &getStart() const { return Start; }
- const PathDiagnosticLocation &getEnd() const { return End; }
-
- void setStart(const PathDiagnosticLocation &L) { Start = L; }
- void setEnd(const PathDiagnosticLocation &L) { End = L; }
-
- void flatten() {
- Start.flatten();
- End.flatten();
- }
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Start.Profile(ID);
- End.Profile(ID);
- }
-};
-
-//===----------------------------------------------------------------------===//
-// Path "pieces" for path-sensitive diagnostics.
-//===----------------------------------------------------------------------===//
-
-class PathDiagnosticPiece : public RefCountedBaseVPTR {
-public:
- enum Kind { ControlFlow, Event, Macro, Call };
- enum DisplayHint { Above, Below };
-
-private:
- const std::string str;
- const Kind kind;
- const DisplayHint Hint;
-
- /// \brief In the containing bug report, this piece is the last piece from
- /// the main source file.
- bool LastInMainSourceFile;
-
- /// A constant string that can be used to tag the PathDiagnosticPiece,
- /// typically with the identification of the creator. The actual pointer
- /// value is meant to be an identifier; the string itself is useful for
- /// debugging.
- StringRef Tag;
-
- std::vector<SourceRange> ranges;
-
- PathDiagnosticPiece() = delete;
- PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete;
- void operator=(const PathDiagnosticPiece &P) = delete;
-
-protected:
- PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below);
-
- PathDiagnosticPiece(Kind k, DisplayHint hint = Below);
-
-public:
- ~PathDiagnosticPiece() override;
-
- StringRef getString() const { return str; }
-
- /// Tag this PathDiagnosticPiece with the given C-string.
- void setTag(const char *tag) { Tag = tag; }
-
- /// Return the opaque tag (if any) on the PathDiagnosticPiece.
- const void *getTag() const { return Tag.data(); }
-
- /// Return the string representation of the tag. This is useful
- /// for debugging.
- StringRef getTagStr() const { return Tag; }
-
- /// getDisplayHint - Return a hint indicating where the diagnostic should
- /// be displayed by the PathDiagnosticConsumer.
- DisplayHint getDisplayHint() const { return Hint; }
-
- virtual PathDiagnosticLocation getLocation() const = 0;
- virtual void flattenLocations() = 0;
-
- Kind getKind() const { return kind; }
-
- void addRange(SourceRange R) {
- if (!R.isValid())
- return;
- ranges.push_back(R);
- }
-
- void addRange(SourceLocation B, SourceLocation E) {
- if (!B.isValid() || !E.isValid())
- return;
- ranges.push_back(SourceRange(B,E));
- }
-
- /// Return the SourceRanges associated with this PathDiagnosticPiece.
- ArrayRef<SourceRange> getRanges() const { return ranges; }
-
- virtual void Profile(llvm::FoldingSetNodeID &ID) const;
-
- void setAsLastInMainSourceFile() {
- LastInMainSourceFile = true;
- }
-
- bool isLastInMainSourceFile() const {
- return LastInMainSourceFile;
- }
-
- virtual void dump() const = 0;
-};
-
-
-class PathPieces : public std::list<IntrusiveRefCntPtr<PathDiagnosticPiece> > {
- void flattenTo(PathPieces &Primary, PathPieces &Current,
- bool ShouldFlattenMacros) const;
-public:
-
- PathPieces flatten(bool ShouldFlattenMacros) const {
- PathPieces Result;
- flattenTo(Result, Result, ShouldFlattenMacros);
- return Result;
- }
-
- void dump() const;
-};
-
-class PathDiagnosticSpotPiece : public PathDiagnosticPiece {
-private:
- PathDiagnosticLocation Pos;
-public:
- PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos,
- StringRef s,
- PathDiagnosticPiece::Kind k,
- bool addPosRange = true)
- : PathDiagnosticPiece(s, k), Pos(pos) {
- assert(Pos.isValid() && Pos.asLocation().isValid() &&
- "PathDiagnosticSpotPiece's must have a valid location.");
- if (addPosRange && Pos.hasRange()) addRange(Pos.asRange());
- }
-
- PathDiagnosticLocation getLocation() const override { return Pos; }
- void flattenLocations() override { Pos.flatten(); }
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == Event || P->getKind() == Macro;
- }
-};
-
-/// \brief Interface for classes constructing Stack hints.
-///
-/// If a PathDiagnosticEvent occurs in a different frame than the final
-/// diagnostic the hints can be used to summarize the effect of the call.
-class StackHintGenerator {
-public:
- virtual ~StackHintGenerator() = 0;
-
- /// \brief Construct the Diagnostic message for the given ExplodedNode.
- virtual std::string getMessage(const ExplodedNode *N) = 0;
-};
-
-/// \brief Constructs a Stack hint for the given symbol.
-///
-/// The class knows how to construct the stack hint message based on
-/// traversing the CallExpr associated with the call and checking if the given
-/// symbol is returned or is one of the arguments.
-/// The hint can be customized by redefining 'getMessageForX()' methods.
-class StackHintGeneratorForSymbol : public StackHintGenerator {
-private:
- SymbolRef Sym;
- std::string Msg;
-
-public:
- StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {}
- ~StackHintGeneratorForSymbol() override {}
-
- /// \brief Search the call expression for the symbol Sym and dispatch the
- /// 'getMessageForX()' methods to construct a specific message.
- std::string getMessage(const ExplodedNode *N) override;
-
- /// Produces the message of the following form:
- /// 'Msg via Nth parameter'
- virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex);
- virtual std::string getMessageForReturn(const CallExpr *CallExpr) {
- return Msg;
- }
- virtual std::string getMessageForSymbolNotFound() {
- return Msg;
- }
-};
-
-class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece {
- Optional<bool> IsPrunable;
-
- /// If the event occurs in a different frame than the final diagnostic,
- /// supply a message that will be used to construct an extra hint on the
- /// returns from all the calls on the stack from this event to the final
- /// diagnostic.
- std::unique_ptr<StackHintGenerator> CallStackHint;
-
-public:
- PathDiagnosticEventPiece(const PathDiagnosticLocation &pos,
- StringRef s, bool addPosRange = true,
- StackHintGenerator *stackHint = nullptr)
- : PathDiagnosticSpotPiece(pos, s, Event, addPosRange),
- CallStackHint(stackHint) {}
-
- ~PathDiagnosticEventPiece() override;
-
- /// Mark the diagnostic piece as being potentially prunable. This
- /// flag may have been previously set, at which point it will not
- /// be reset unless one specifies to do so.
- void setPrunable(bool isPrunable, bool override = false) {
- if (IsPrunable.hasValue() && !override)
- return;
- IsPrunable = isPrunable;
- }
-
- /// Return true if the diagnostic piece is prunable.
- bool isPrunable() const {
- return IsPrunable.hasValue() ? IsPrunable.getValue() : false;
- }
-
- bool hasCallStackHint() { return (bool)CallStackHint; }
-
- /// Produce the hint for the given node. The node contains
- /// information about the call for which the diagnostic can be generated.
- std::string getCallStackMessage(const ExplodedNode *N) {
- if (CallStackHint)
- return CallStackHint->getMessage(N);
- return "";
- }
-
- void dump() const override;
-
- static inline bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == Event;
- }
-};
-
-class PathDiagnosticCallPiece : public PathDiagnosticPiece {
- PathDiagnosticCallPiece(const Decl *callerD,
- const PathDiagnosticLocation &callReturnPos)
- : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
- NoExit(false), callReturn(callReturnPos) {}
-
- PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
- : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
- NoExit(true), path(oldPath) {}
-
- const Decl *Caller;
- const Decl *Callee;
-
- // Flag signifying that this diagnostic has only call enter and no matching
- // call exit.
- bool NoExit;
-
- // The custom string, which should appear after the call Return Diagnostic.
- // TODO: Should we allow multiple diagnostics?
- std::string CallStackMessage;
-
-public:
- PathDiagnosticLocation callEnter;
- PathDiagnosticLocation callEnterWithin;
- PathDiagnosticLocation callReturn;
- PathPieces path;
-
- ~PathDiagnosticCallPiece() override;
-
- const Decl *getCaller() const { return Caller; }
-
- const Decl *getCallee() const { return Callee; }
- void setCallee(const CallEnter &CE, const SourceManager &SM);
-
- bool hasCallStackMessage() { return !CallStackMessage.empty(); }
- void setCallStackMessage(StringRef st) {
- CallStackMessage = st;
- }
-
- PathDiagnosticLocation getLocation() const override {
- return callEnter;
- }
-
- IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallEnterEvent() const;
- IntrusiveRefCntPtr<PathDiagnosticEventPiece>
- getCallEnterWithinCallerEvent() const;
- IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const;
-
- void flattenLocations() override {
- callEnter.flatten();
- callReturn.flatten();
- for (PathPieces::iterator I = path.begin(),
- E = path.end(); I != E; ++I) (*I)->flattenLocations();
- }
-
- static PathDiagnosticCallPiece *construct(const ExplodedNode *N,
- const CallExitEnd &CE,
- const SourceManager &SM);
-
- static PathDiagnosticCallPiece *construct(PathPieces &pieces,
- const Decl *caller);
-
- void dump() const override;
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static inline bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == Call;
- }
-};
-
-class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece {
- std::vector<PathDiagnosticLocationPair> LPairs;
-public:
- PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
- const PathDiagnosticLocation &endPos,
- StringRef s)
- : PathDiagnosticPiece(s, ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
-
- PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos,
- const PathDiagnosticLocation &endPos)
- : PathDiagnosticPiece(ControlFlow) {
- LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos));
- }
-
- ~PathDiagnosticControlFlowPiece() override;
-
- PathDiagnosticLocation getStartLocation() const {
- assert(!LPairs.empty() &&
- "PathDiagnosticControlFlowPiece needs at least one location.");
- return LPairs[0].getStart();
- }
-
- PathDiagnosticLocation getEndLocation() const {
- assert(!LPairs.empty() &&
- "PathDiagnosticControlFlowPiece needs at least one location.");
- return LPairs[0].getEnd();
- }
-
- void setStartLocation(const PathDiagnosticLocation &L) {
- LPairs[0].setStart(L);
- }
-
- void setEndLocation(const PathDiagnosticLocation &L) {
- LPairs[0].setEnd(L);
- }
-
- void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); }
-
- PathDiagnosticLocation getLocation() const override {
- return getStartLocation();
- }
-
- typedef std::vector<PathDiagnosticLocationPair>::iterator iterator;
- iterator begin() { return LPairs.begin(); }
- iterator end() { return LPairs.end(); }
-
- void flattenLocations() override {
- for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten();
- }
-
- typedef std::vector<PathDiagnosticLocationPair>::const_iterator
- const_iterator;
- const_iterator begin() const { return LPairs.begin(); }
- const_iterator end() const { return LPairs.end(); }
-
- static inline bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == ControlFlow;
- }
-
- void dump() const override;
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-};
-
-class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece {
-public:
- PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos)
- : PathDiagnosticSpotPiece(pos, "", Macro) {}
-
- ~PathDiagnosticMacroPiece() override;
-
- PathPieces subPieces;
-
- bool containsEvent() const;
-
- void flattenLocations() override {
- PathDiagnosticSpotPiece::flattenLocations();
- for (PathPieces::iterator I = subPieces.begin(),
- E = subPieces.end(); I != E; ++I) (*I)->flattenLocations();
- }
-
- static inline bool classof(const PathDiagnosticPiece *P) {
- return P->getKind() == Macro;
- }
-
- void dump() const override;
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-};
-
-/// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive
-/// diagnostic. It represents an ordered-collection of PathDiagnosticPieces,
-/// each which represent the pieces of the path.
-class PathDiagnostic : public llvm::FoldingSetNode {
- std::string CheckName;
- const Decl *DeclWithIssue;
- std::string BugType;
- std::string VerboseDesc;
- std::string ShortDesc;
- std::string Category;
- std::deque<std::string> OtherDesc;
-
- /// \brief Loc The location of the path diagnostic report.
- PathDiagnosticLocation Loc;
-
- PathPieces pathImpl;
- SmallVector<PathPieces *, 3> pathStack;
-
- /// \brief Important bug uniqueing location.
- /// The location info is useful to differentiate between bugs.
- PathDiagnosticLocation UniqueingLoc;
- const Decl *UniqueingDecl;
-
- PathDiagnostic() = delete;
-public:
- PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue,
- StringRef bugtype, StringRef verboseDesc, StringRef shortDesc,
- StringRef category, PathDiagnosticLocation LocationToUnique,
- const Decl *DeclToUnique);
-
- ~PathDiagnostic();
-
- const PathPieces &path;
-
- /// Return the path currently used by builders for constructing the
- /// PathDiagnostic.
- PathPieces &getActivePath() {
- if (pathStack.empty())
- return pathImpl;
- return *pathStack.back();
- }
-
- /// Return a mutable version of 'path'.
- PathPieces &getMutablePieces() {
- return pathImpl;
- }
-
- /// Return the unrolled size of the path.
- unsigned full_size();
-
- void pushActivePath(PathPieces *p) { pathStack.push_back(p); }
- void popActivePath() { if (!pathStack.empty()) pathStack.pop_back(); }
-
- bool isWithinCall() const { return !pathStack.empty(); }
-
- void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) {
- assert(!Loc.isValid() && "End location already set!");
- Loc = EndPiece->getLocation();
- assert(Loc.isValid() && "Invalid location for end-of-path piece");
- getActivePath().push_back(EndPiece.release());
- }
-
- void appendToDesc(StringRef S) {
- if (!ShortDesc.empty())
- ShortDesc.append(S);
- VerboseDesc.append(S);
- }
-
- void resetPath() {
- pathStack.clear();
- pathImpl.clear();
- Loc = PathDiagnosticLocation();
- }
-
- /// \brief If the last piece of the report point to the header file, resets
- /// the location of the report to be the last location in the main source
- /// file.
- void resetDiagnosticLocationToMainFile();
-
- StringRef getVerboseDescription() const { return VerboseDesc; }
- StringRef getShortDescription() const {
- return ShortDesc.empty() ? VerboseDesc : ShortDesc;
- }
- StringRef getCheckName() const { return CheckName; }
- StringRef getBugType() const { return BugType; }
- StringRef getCategory() const { return Category; }
-
- /// Return the semantic context where an issue occurred. If the
- /// issue occurs along a path, this represents the "central" area
- /// where the bug manifests.
- const Decl *getDeclWithIssue() const { return DeclWithIssue; }
-
- typedef std::deque<std::string>::const_iterator meta_iterator;
- meta_iterator meta_begin() const { return OtherDesc.begin(); }
- meta_iterator meta_end() const { return OtherDesc.end(); }
- void addMeta(StringRef s) { OtherDesc.push_back(s); }
-
- PathDiagnosticLocation getLocation() const {
- assert(Loc.isValid() && "No report location set yet!");
- return Loc;
- }
-
- /// \brief Get the location on which the report should be uniqued.
- PathDiagnosticLocation getUniqueingLoc() const {
- return UniqueingLoc;
- }
-
- /// \brief Get the declaration containing the uniqueing location.
- const Decl *getUniqueingDecl() const {
- return UniqueingDecl;
- }
-
- void flattenLocations() {
- Loc.flatten();
- for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end();
- I != E; ++I) (*I)->flattenLocations();
- }
-
- /// Profiles the diagnostic, independent of the path it references.
- ///
- /// This can be used to merge diagnostics that refer to the same issue
- /// along different paths.
- void Profile(llvm::FoldingSetNodeID &ID) const;
-
- /// Profiles the diagnostic, including its path.
- ///
- /// Two diagnostics with the same issue along different paths will generate
- /// different profiles.
- void FullProfile(llvm::FoldingSetNodeID &ID) const;
-};
-
-} // end GR namespace
-
-} //end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h
deleted file mode 100644
index 1410af1..0000000
--- a/include/clang/StaticAnalyzer/Core/Checker.h
+++ /dev/null
@@ -1,554 +0,0 @@
-//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines Checker, used to create and register checkers.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
-
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/Support/Casting.h"
-
-namespace clang {
-namespace ento {
- class BugReporter;
-
-namespace check {
-
-template <typename DECL>
-class ASTDecl {
- template <typename CHECKER>
- static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
- BugReporter &BR) {
- ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
- }
-
- static bool _handlesDecl(const Decl *D) {
- return isa<DECL>(D);
- }
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
- _checkDecl<CHECKER>),
- _handlesDecl);
- }
-};
-
-class ASTCodeBody {
- template <typename CHECKER>
- static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
- BugReporter &BR) {
- ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
- _checkBody<CHECKER>));
- }
-};
-
-class EndOfTranslationUnit {
- template <typename CHECKER>
- static void _checkEndOfTranslationUnit(void *checker,
- const TranslationUnitDecl *TU,
- AnalysisManager& mgr,
- BugReporter &BR) {
- ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr){
- mgr._registerForEndOfTranslationUnit(
- CheckerManager::CheckEndOfTranslationUnit(checker,
- _checkEndOfTranslationUnit<CHECKER>));
- }
-};
-
-template <typename STMT>
-class PreStmt {
- template <typename CHECKER>
- static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
- ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
- }
-
- static bool _handlesStmt(const Stmt *S) {
- return isa<STMT>(S);
- }
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
- _checkStmt<CHECKER>),
- _handlesStmt);
- }
-};
-
-template <typename STMT>
-class PostStmt {
- template <typename CHECKER>
- static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
- ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
- }
-
- static bool _handlesStmt(const Stmt *S) {
- return isa<STMT>(S);
- }
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
- _checkStmt<CHECKER>),
- _handlesStmt);
- }
-};
-
-class PreObjCMessage {
- template <typename CHECKER>
- static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPreObjCMessage(
- CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
- }
-};
-
-class ObjCMessageNil {
- template <typename CHECKER>
- static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForObjCMessageNil(
- CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
- }
-};
-
-class PostObjCMessage {
- template <typename CHECKER>
- static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPostObjCMessage(
- CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
- }
-};
-
-class PreCall {
- template <typename CHECKER>
- static void _checkCall(void *checker, const CallEvent &msg,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkPreCall(msg, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPreCall(
- CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
- }
-};
-
-class PostCall {
- template <typename CHECKER>
- static void _checkCall(void *checker, const CallEvent &msg,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkPostCall(msg, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPostCall(
- CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
- }
-};
-
-class Location {
- template <typename CHECKER>
- static void _checkLocation(void *checker,
- const SVal &location, bool isLoad, const Stmt *S,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForLocation(
- CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
- }
-};
-
-class Bind {
- template <typename CHECKER>
- static void _checkBind(void *checker,
- const SVal &location, const SVal &val, const Stmt *S,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkBind(location, val, S, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForBind(
- CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
- }
-};
-
-class EndAnalysis {
- template <typename CHECKER>
- static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
- BugReporter &BR, ExprEngine &Eng) {
- ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForEndAnalysis(
- CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
- }
-};
-
-class EndFunction {
- template <typename CHECKER>
- static void _checkEndFunction(void *checker,
- CheckerContext &C) {
- ((const CHECKER *)checker)->checkEndFunction(C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForEndFunction(
- CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
- }
-};
-
-class BranchCondition {
- template <typename CHECKER>
- static void _checkBranchCondition(void *checker, const Stmt *Condition,
- CheckerContext & C) {
- ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForBranchCondition(
- CheckerManager::CheckBranchConditionFunc(checker,
- _checkBranchCondition<CHECKER>));
- }
-};
-
-class LiveSymbols {
- template <typename CHECKER>
- static void _checkLiveSymbols(void *checker, ProgramStateRef state,
- SymbolReaper &SR) {
- ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForLiveSymbols(
- CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
- }
-};
-
-class DeadSymbols {
- template <typename CHECKER>
- static void _checkDeadSymbols(void *checker,
- SymbolReaper &SR, CheckerContext &C) {
- ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForDeadSymbols(
- CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
- }
-};
-
-class RegionChanges {
- template <typename CHECKER>
- static ProgramStateRef
- _checkRegionChanges(void *checker,
- ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> Explicits,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call) {
- return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
- Explicits, Regions, Call);
- }
- template <typename CHECKER>
- static bool _wantsRegionChangeUpdate(void *checker,
- ProgramStateRef state) {
- return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForRegionChanges(
- CheckerManager::CheckRegionChangesFunc(checker,
- _checkRegionChanges<CHECKER>),
- CheckerManager::WantsRegionChangeUpdateFunc(checker,
- _wantsRegionChangeUpdate<CHECKER>));
- }
-};
-
-class PointerEscape {
- template <typename CHECKER>
- static ProgramStateRef
- _checkPointerEscape(void *Checker,
- ProgramStateRef State,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ETraits) {
-
- if (!ETraits)
- return ((const CHECKER *)Checker)->checkPointerEscape(State,
- Escaped,
- Call,
- Kind);
-
- InvalidatedSymbols RegularEscape;
- for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
- E = Escaped.end(); I != E; ++I)
- if (!ETraits->hasTrait(*I,
- RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
- !ETraits->hasTrait(*I,
- RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
- RegularEscape.insert(*I);
-
- if (RegularEscape.empty())
- return State;
-
- return ((const CHECKER *)Checker)->checkPointerEscape(State,
- RegularEscape,
- Call,
- Kind);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPointerEscape(
- CheckerManager::CheckPointerEscapeFunc(checker,
- _checkPointerEscape<CHECKER>));
- }
-};
-
-class ConstPointerEscape {
- template <typename CHECKER>
- static ProgramStateRef
- _checkConstPointerEscape(void *Checker,
- ProgramStateRef State,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ETraits) {
-
- if (!ETraits)
- return State;
-
- InvalidatedSymbols ConstEscape;
- for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
- E = Escaped.end(); I != E; ++I)
- if (ETraits->hasTrait(*I,
- RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
- !ETraits->hasTrait(*I,
- RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
- ConstEscape.insert(*I);
-
- if (ConstEscape.empty())
- return State;
-
- return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
- ConstEscape,
- Call,
- Kind);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForPointerEscape(
- CheckerManager::CheckPointerEscapeFunc(checker,
- _checkConstPointerEscape<CHECKER>));
- }
-};
-
-
-template <typename EVENT>
-class Event {
- template <typename CHECKER>
- static void _checkEvent(void *checker, const void *event) {
- ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
- }
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerListenerForEvent<EVENT>(
- CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
- }
-};
-
-} // end check namespace
-
-namespace eval {
-
-class Assume {
- template <typename CHECKER>
- static ProgramStateRef _evalAssume(void *checker,
- ProgramStateRef state,
- const SVal &cond,
- bool assumption) {
- return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForEvalAssume(
- CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
- }
-};
-
-class Call {
- template <typename CHECKER>
- static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
- return ((const CHECKER *)checker)->evalCall(CE, C);
- }
-
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerForEvalCall(
- CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
- }
-};
-
-} // end eval namespace
-
-class CheckerBase : public ProgramPointTag {
- CheckName Name;
- friend class ::clang::ento::CheckerManager;
-
-public:
- StringRef getTagDescription() const override;
- CheckName getCheckName() const;
-
- /// See CheckerManager::runCheckersForPrintState.
- virtual void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) const { }
-};
-
-/// Dump checker name to stream.
-raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
-
-/// Tag that can use a checker name as a message provider
-/// (see SimpleProgramPointTag).
-class CheckerProgramPointTag : public SimpleProgramPointTag {
-public:
- CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
- CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
-};
-
-template <typename CHECK1, typename... CHECKs>
-class Checker : public CHECK1, public CHECKs..., public CheckerBase {
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- CHECK1::_register(checker, mgr);
- Checker<CHECKs...>::_register(checker, mgr);
- }
-};
-
-template <typename CHECK1>
-class Checker<CHECK1> : public CHECK1, public CheckerBase {
-public:
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- CHECK1::_register(checker, mgr);
- }
-};
-
-template <typename EVENT>
-class EventDispatcher {
- CheckerManager *Mgr;
-public:
- EventDispatcher() : Mgr(nullptr) { }
-
- template <typename CHECKER>
- static void _register(CHECKER *checker, CheckerManager &mgr) {
- mgr._registerDispatcherForEvent<EVENT>();
- static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
- }
-
- void dispatchEvent(const EVENT &event) const {
- Mgr->_dispatchEvent(event);
- }
-};
-
-/// \brief We dereferenced a location that may be null.
-struct ImplicitNullDerefEvent {
- SVal Location;
- bool IsLoad;
- ExplodedNode *SinkNode;
- BugReporter *BR;
- // When true, the dereference is in the source code directly. When false, the
- // dereference might happen later (for example pointer passed to a parameter
- // that is marked with nonnull attribute.)
- bool IsDirectDereference;
-};
-
-/// \brief A helper class which wraps a boolean value set to false by default.
-///
-/// This class should behave exactly like 'bool' except that it doesn't need to
-/// be explicitly initialized.
-struct DefaultBool {
- bool val;
- DefaultBool() : val(false) {}
- /*implicit*/ operator bool&() { return val; }
- /*implicit*/ operator const bool&() const { return val; }
- DefaultBool &operator=(bool b) { val = b; return *this; }
-};
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h
deleted file mode 100644
index bc9af49..0000000
--- a/include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ /dev/null
@@ -1,632 +0,0 @@
-//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines the Static Analyzer Checker Manager.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H
-
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include <vector>
-
-namespace clang {
- class Decl;
- class Stmt;
- class CallExpr;
-
-namespace ento {
- class CheckerBase;
- class CheckerRegistry;
- class ExprEngine;
- class AnalysisManager;
- class BugReporter;
- class CheckerContext;
- class ObjCMethodCall;
- class SVal;
- class ExplodedNode;
- class ExplodedNodeSet;
- class ExplodedGraph;
- class ProgramState;
- class NodeBuilder;
- struct NodeBuilderContext;
- class MemRegion;
- class SymbolReaper;
-
-template <typename T> class CheckerFn;
-
-template <typename RET, typename... Ps>
-class CheckerFn<RET(Ps...)> {
- typedef RET (*Func)(void *, Ps...);
- Func Fn;
-public:
- CheckerBase *Checker;
- CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
- RET operator()(Ps... ps) const {
- return Fn(Checker, ps...);
- }
-};
-
-/// \brief Describes the different reasons a pointer escapes
-/// during analysis.
-enum PointerEscapeKind {
- /// A pointer escapes due to binding its value to a location
- /// that the analyzer cannot track.
- PSK_EscapeOnBind,
-
- /// The pointer has been passed to a function call directly.
- PSK_DirectEscapeOnCall,
-
- /// The pointer has been passed to a function indirectly.
- /// For example, the pointer is accessible through an
- /// argument to a function.
- PSK_IndirectEscapeOnCall,
-
- /// The reason for pointer escape is unknown. For example,
- /// a region containing this pointer is invalidated.
- PSK_EscapeOther
-};
-
-// This wrapper is used to ensure that only StringRefs originating from the
-// CheckerRegistry are used as check names. We want to make sure all check
-// name strings have a lifetime that keeps them alive at least until the path
-// diagnostics have been processed.
-class CheckName {
- StringRef Name;
- friend class ::clang::ento::CheckerRegistry;
- explicit CheckName(StringRef Name) : Name(Name) {}
-
-public:
- CheckName() = default;
- StringRef getName() const { return Name; }
-};
-
-enum class ObjCMessageVisitKind {
- Pre,
- Post,
- MessageNil
-};
-
-class CheckerManager {
- const LangOptions LangOpts;
- AnalyzerOptionsRef AOptions;
- CheckName CurrentCheckName;
-
-public:
- CheckerManager(const LangOptions &langOpts,
- AnalyzerOptionsRef AOptions)
- : LangOpts(langOpts),
- AOptions(AOptions) {}
-
- ~CheckerManager();
-
- void setCurrentCheckName(CheckName name) { CurrentCheckName = name; }
- CheckName getCurrentCheckName() const { return CurrentCheckName; }
-
- bool hasPathSensitiveCheckers() const;
-
- void finishedCheckerRegistration();
-
- const LangOptions &getLangOpts() const { return LangOpts; }
- AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
-
- typedef CheckerBase *CheckerRef;
- typedef const void *CheckerTag;
- typedef CheckerFn<void ()> CheckerDtor;
-
-//===----------------------------------------------------------------------===//
-// registerChecker
-//===----------------------------------------------------------------------===//
-
- /// \brief Used to register checkers.
- ///
- /// \returns a pointer to the checker object.
- template <typename CHECKER>
- CHECKER *registerChecker() {
- CheckerTag tag = getTag<CHECKER>();
- CheckerRef &ref = CheckerTags[tag];
- if (ref)
- return static_cast<CHECKER *>(ref); // already registered.
-
- CHECKER *checker = new CHECKER();
- checker->Name = CurrentCheckName;
- CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
- CHECKER::_register(checker, *this);
- ref = checker;
- return checker;
- }
-
- template <typename CHECKER>
- CHECKER *registerChecker(AnalyzerOptions &AOpts) {
- CheckerTag tag = getTag<CHECKER>();
- CheckerRef &ref = CheckerTags[tag];
- if (ref)
- return static_cast<CHECKER *>(ref); // already registered.
-
- CHECKER *checker = new CHECKER(AOpts);
- checker->Name = CurrentCheckName;
- CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
- CHECKER::_register(checker, *this);
- ref = checker;
- return checker;
- }
-
-//===----------------------------------------------------------------------===//
-// Functions for running checkers for AST traversing..
-//===----------------------------------------------------------------------===//
-
- /// \brief Run checkers handling Decls.
- void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
- BugReporter &BR);
-
- /// \brief Run checkers handling Decls containing a Stmt body.
- void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
- BugReporter &BR);
-
-//===----------------------------------------------------------------------===//
-// Functions for running checkers for path-sensitive checking.
-//===----------------------------------------------------------------------===//
-
- /// \brief Run checkers for pre-visiting Stmts.
- ///
- /// The notification is performed for every explored CFGElement, which does
- /// not include the control flow statements such as IfStmt.
- ///
- /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
- void runCheckersForPreStmt(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const Stmt *S,
- ExprEngine &Eng) {
- runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
- }
-
- /// \brief Run checkers for post-visiting Stmts.
- ///
- /// The notification is performed for every explored CFGElement, which does
- /// not include the control flow statements such as IfStmt.
- ///
- /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
- void runCheckersForPostStmt(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const Stmt *S,
- ExprEngine &Eng,
- bool wasInlined = false) {
- runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
- }
-
- /// \brief Run checkers for visiting Stmts.
- void runCheckersForStmt(bool isPreVisit,
- ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
- const Stmt *S, ExprEngine &Eng,
- bool wasInlined = false);
-
- /// \brief Run checkers for pre-visiting obj-c messages.
- void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const ObjCMethodCall &msg,
- ExprEngine &Eng) {
- runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng);
- }
-
- /// \brief Run checkers for post-visiting obj-c messages.
- void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const ObjCMethodCall &msg,
- ExprEngine &Eng,
- bool wasInlined = false) {
- runCheckersForObjCMessage(ObjCMessageVisitKind::Post, Dst, Src, msg, Eng,
- wasInlined);
- }
-
- /// \brief Run checkers for visiting an obj-c message to nil.
- void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const ObjCMethodCall &msg,
- ExprEngine &Eng) {
- runCheckersForObjCMessage(ObjCMessageVisitKind::MessageNil, Dst, Src, msg,
- Eng);
- }
-
-
- /// \brief Run checkers for visiting obj-c messages.
- void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind,
- ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const ObjCMethodCall &msg, ExprEngine &Eng,
- bool wasInlined = false);
-
- /// \brief Run checkers for pre-visiting obj-c messages.
- void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
- const CallEvent &Call, ExprEngine &Eng) {
- runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
- }
-
- /// \brief Run checkers for post-visiting obj-c messages.
- void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
- const CallEvent &Call, ExprEngine &Eng,
- bool wasInlined = false) {
- runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
- wasInlined);
- }
-
- /// \brief Run checkers for visiting obj-c messages.
- void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const CallEvent &Call, ExprEngine &Eng,
- bool wasInlined = false);
-
- /// \brief Run checkers for load/store of a location.
- void runCheckersForLocation(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- SVal location,
- bool isLoad,
- const Stmt *NodeEx,
- const Stmt *BoundEx,
- ExprEngine &Eng);
-
- /// \brief Run checkers for binding of a value to a location.
- void runCheckersForBind(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- SVal location, SVal val,
- const Stmt *S, ExprEngine &Eng,
- const ProgramPoint &PP);
-
- /// \brief Run checkers for end of analysis.
- void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
- ExprEngine &Eng);
-
- /// \brief Run checkers on end of function.
- void runCheckersForEndFunction(NodeBuilderContext &BC,
- ExplodedNodeSet &Dst,
- ExplodedNode *Pred,
- ExprEngine &Eng);
-
- /// \brief Run checkers for branch condition.
- void runCheckersForBranchCondition(const Stmt *condition,
- ExplodedNodeSet &Dst, ExplodedNode *Pred,
- ExprEngine &Eng);
-
- /// \brief Run checkers for live symbols.
- ///
- /// Allows modifying SymbolReaper object. For example, checkers can explicitly
- /// register symbols of interest as live. These symbols will not be marked
- /// dead and removed.
- void runCheckersForLiveSymbols(ProgramStateRef state,
- SymbolReaper &SymReaper);
-
- /// \brief Run checkers for dead symbols.
- ///
- /// Notifies checkers when symbols become dead. For example, this allows
- /// checkers to aggressively clean up/reduce the checker state and produce
- /// precise diagnostics.
- void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- SymbolReaper &SymReaper, const Stmt *S,
- ExprEngine &Eng,
- ProgramPoint::Kind K);
-
- /// \brief True if at least one checker wants to check region changes.
- bool wantsRegionChangeUpdate(ProgramStateRef state);
-
- /// \brief Run checkers for region changes.
- ///
- /// This corresponds to the check::RegionChanges callback.
- /// \param state The current program state.
- /// \param invalidated A set of all symbols potentially touched by the change.
- /// \param ExplicitRegions The regions explicitly requested for invalidation.
- /// For example, in the case of a function call, these would be arguments.
- /// \param Regions The transitive closure of accessible regions,
- /// i.e. all regions that may have been touched by this change.
- /// \param Call The call expression wrapper if the regions are invalidated
- /// by a call.
- ProgramStateRef
- runCheckersForRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call);
-
- /// \brief Run checkers when pointers escape.
- ///
- /// This notifies the checkers about pointer escape, which occurs whenever
- /// the analyzer cannot track the symbol any more. For example, as a
- /// result of assigning a pointer into a global or when it's passed to a
- /// function call the analyzer cannot model.
- ///
- /// \param State The state at the point of escape.
- /// \param Escaped The list of escaped symbols.
- /// \param Call The corresponding CallEvent, if the symbols escape as
- /// parameters to the given call.
- /// \param Kind The reason of pointer escape.
- /// \param ITraits Information about invalidation for a particular
- /// region/symbol.
- /// \returns Checkers can modify the state by returning a new one.
- ProgramStateRef
- runCheckersForPointerEscape(ProgramStateRef State,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ITraits);
-
- /// \brief Run checkers for handling assumptions on symbolic values.
- ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
- SVal Cond, bool Assumption);
-
- /// \brief Run checkers for evaluating a call.
- ///
- /// Warning: Currently, the CallEvent MUST come from a CallExpr!
- void runCheckersForEvalCall(ExplodedNodeSet &Dst,
- const ExplodedNodeSet &Src,
- const CallEvent &CE, ExprEngine &Eng);
-
- /// \brief Run checkers for the entire Translation Unit.
- void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
- AnalysisManager &mgr,
- BugReporter &BR);
-
- /// \brief Run checkers for debug-printing a ProgramState.
- ///
- /// Unlike most other callbacks, any checker can simply implement the virtual
- /// method CheckerBase::printState if it has custom data to print.
- /// \param Out The output stream
- /// \param State The state being printed
- /// \param NL The preferred representation of a newline.
- /// \param Sep The preferred separator between different kinds of data.
- void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep);
-
-//===----------------------------------------------------------------------===//
-// Internal registration functions for AST traversing.
-//===----------------------------------------------------------------------===//
-
- // Functions used by the registration mechanism, checkers should not touch
- // these directly.
-
- typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
- CheckDeclFunc;
-
- typedef bool (*HandlesDeclFunc)(const Decl *D);
- void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
-
- void _registerForBody(CheckDeclFunc checkfn);
-
-//===----------------------------------------------------------------------===//
-// Internal registration functions for path-sensitive checking.
-//===----------------------------------------------------------------------===//
-
- typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
-
- typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
- CheckObjCMessageFunc;
-
- typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
- CheckCallFunc;
-
- typedef CheckerFn<void (const SVal &location, bool isLoad,
- const Stmt *S,
- CheckerContext &)>
- CheckLocationFunc;
-
- typedef CheckerFn<void (const SVal &location, const SVal &val,
- const Stmt *S, CheckerContext &)>
- CheckBindFunc;
-
- typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
- CheckEndAnalysisFunc;
-
- typedef CheckerFn<void (CheckerContext &)>
- CheckEndFunctionFunc;
-
- typedef CheckerFn<void (const Stmt *, CheckerContext &)>
- CheckBranchConditionFunc;
-
- typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
- CheckDeadSymbolsFunc;
-
- typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols *symbols,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call)>
- CheckRegionChangesFunc;
-
- typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const InvalidatedSymbols &Escaped,
- const CallEvent *Call,
- PointerEscapeKind Kind,
- RegionAndSymbolInvalidationTraits *ITraits)>
- CheckPointerEscapeFunc;
-
- typedef CheckerFn<ProgramStateRef (ProgramStateRef,
- const SVal &cond, bool assumption)>
- EvalAssumeFunc;
-
- typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
- EvalCallFunc;
-
- typedef CheckerFn<void (const TranslationUnitDecl *,
- AnalysisManager&, BugReporter &)>
- CheckEndOfTranslationUnit;
-
- typedef bool (*HandlesStmtFunc)(const Stmt *D);
- void _registerForPreStmt(CheckStmtFunc checkfn,
- HandlesStmtFunc isForStmtFn);
- void _registerForPostStmt(CheckStmtFunc checkfn,
- HandlesStmtFunc isForStmtFn);
-
- void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
- void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
-
- void _registerForObjCMessageNil(CheckObjCMessageFunc checkfn);
-
- void _registerForPreCall(CheckCallFunc checkfn);
- void _registerForPostCall(CheckCallFunc checkfn);
-
- void _registerForLocation(CheckLocationFunc checkfn);
-
- void _registerForBind(CheckBindFunc checkfn);
-
- void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
-
- void _registerForEndFunction(CheckEndFunctionFunc checkfn);
-
- void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
-
- void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
-
- void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
-
- void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
- WantsRegionChangeUpdateFunc wantUpdateFn);
-
- void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
-
- void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
-
- void _registerForEvalAssume(EvalAssumeFunc checkfn);
-
- void _registerForEvalCall(EvalCallFunc checkfn);
-
- void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
-
-//===----------------------------------------------------------------------===//
-// Internal registration functions for events.
-//===----------------------------------------------------------------------===//
-
- typedef void *EventTag;
- typedef CheckerFn<void (const void *event)> CheckEventFunc;
-
- template <typename EVENT>
- void _registerListenerForEvent(CheckEventFunc checkfn) {
- EventInfo &info = Events[getTag<EVENT>()];
- info.Checkers.push_back(checkfn);
- }
-
- template <typename EVENT>
- void _registerDispatcherForEvent() {
- EventInfo &info = Events[getTag<EVENT>()];
- info.HasDispatcher = true;
- }
-
- template <typename EVENT>
- void _dispatchEvent(const EVENT &event) const {
- EventsTy::const_iterator I = Events.find(getTag<EVENT>());
- if (I == Events.end())
- return;
- const EventInfo &info = I->second;
- for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
- info.Checkers[i](&event);
- }
-
-//===----------------------------------------------------------------------===//
-// Implementation details.
-//===----------------------------------------------------------------------===//
-
-private:
- template <typename CHECKER>
- static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
-
- template <typename T>
- static void *getTag() { static int tag; return &tag; }
-
- llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
-
- std::vector<CheckerDtor> CheckerDtors;
-
- struct DeclCheckerInfo {
- CheckDeclFunc CheckFn;
- HandlesDeclFunc IsForDeclFn;
- };
- std::vector<DeclCheckerInfo> DeclCheckers;
-
- std::vector<CheckDeclFunc> BodyCheckers;
-
- typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
- typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
- CachedDeclCheckersMapTy CachedDeclCheckersMap;
-
- struct StmtCheckerInfo {
- CheckStmtFunc CheckFn;
- HandlesStmtFunc IsForStmtFn;
- bool IsPreVisit;
- };
- std::vector<StmtCheckerInfo> StmtCheckers;
-
- typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
- typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
- CachedStmtCheckersMapTy CachedStmtCheckersMap;
-
- const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
- bool isPreVisit);
-
- /// Returns the checkers that have registered for callbacks of the
- /// given \p Kind.
- const std::vector<CheckObjCMessageFunc> &
- getObjCMessageCheckers(ObjCMessageVisitKind Kind);
-
- std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
- std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
- std::vector<CheckObjCMessageFunc> ObjCMessageNilCheckers;
-
- std::vector<CheckCallFunc> PreCallCheckers;
- std::vector<CheckCallFunc> PostCallCheckers;
-
- std::vector<CheckLocationFunc> LocationCheckers;
-
- std::vector<CheckBindFunc> BindCheckers;
-
- std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
-
- std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
-
- std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
-
- std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
-
- std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
-
- struct RegionChangesCheckerInfo {
- CheckRegionChangesFunc CheckFn;
- WantsRegionChangeUpdateFunc WantUpdateFn;
- };
- std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
-
- std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
-
- std::vector<EvalAssumeFunc> EvalAssumeCheckers;
-
- std::vector<EvalCallFunc> EvalCallCheckers;
-
- std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
-
- struct EventInfo {
- SmallVector<CheckEventFunc, 4> Checkers;
- bool HasDispatcher;
- EventInfo() : HasDispatcher(false) { }
- };
-
- typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
- EventsTy Events;
-};
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h b/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
deleted file mode 100644
index e981871..0000000
--- a/include/clang/StaticAnalyzer/Core/CheckerOptInfo.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===--- CheckerOptInfo.h - Specifies which checkers to use -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKEROPTINFO_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang {
-namespace ento {
-
-/// Represents a request to include or exclude a checker or package from a
-/// specific analysis run.
-///
-/// \sa CheckerRegistry::initializeManager
-class CheckerOptInfo {
- StringRef Name;
- bool Enable;
- bool Claimed;
-
-public:
- CheckerOptInfo(StringRef name, bool enable)
- : Name(name), Enable(enable), Claimed(false) { }
-
- StringRef getName() const { return Name; }
- bool isEnabled() const { return Enable; }
- bool isDisabled() const { return !isEnabled(); }
-
- bool isClaimed() const { return Claimed; }
- bool isUnclaimed() const { return !isClaimed(); }
- void claim() { Claimed = true; }
-};
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
deleted file mode 100644
index c9724c0..0000000
--- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h
+++ /dev/null
@@ -1,140 +0,0 @@
-//===--- CheckerRegistry.h - Maintains all available checkers ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
-#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H
-
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include <vector>
-
-// FIXME: move this information to an HTML file in docs/.
-// At the very least, a checker plugin is a dynamic library that exports
-// clang_analyzerAPIVersionString. This should be defined as follows:
-//
-// extern "C"
-// const char clang_analyzerAPIVersionString[] =
-// CLANG_ANALYZER_API_VERSION_STRING;
-//
-// This is used to check whether the current version of the analyzer is known to
-// be incompatible with a plugin. Plugins with incompatible version strings,
-// or without a version string at all, will not be loaded.
-//
-// To add a custom checker to the analyzer, the plugin must also define the
-// function clang_registerCheckers. For example:
-//
-// extern "C"
-// void clang_registerCheckers (CheckerRegistry &registry) {
-// registry.addChecker<MainCallChecker>("example.MainCallChecker",
-// "Disallows calls to functions called main");
-// }
-//
-// The first method argument is the full name of the checker, including its
-// enclosing package. By convention, the registered name of a checker is the
-// name of the associated class (the template argument).
-// The second method argument is a short human-readable description of the
-// checker.
-//
-// The clang_registerCheckers function may add any number of checkers to the
-// registry. If any checkers require additional initialization, use the three-
-// argument form of CheckerRegistry::addChecker.
-//
-// To load a checker plugin, specify the full path to the dynamic library as
-// the argument to the -load option in the cc1 frontend. You can then enable
-// your custom checker using the -analyzer-checker:
-//
-// clang -cc1 -load </path/to/plugin.dylib> -analyze
-// -analyzer-checker=<example.MainCallChecker>
-//
-// For a complete working example, see examples/analyzer-plugin.
-
-#ifndef CLANG_ANALYZER_API_VERSION_STRING
-// FIXME: The Clang version string is not particularly granular;
-// the analyzer infrastructure can change a lot between releases.
-// Unfortunately, this string has to be statically embedded in each plugin,
-// so we can't just use the functions defined in Version.h.
-#include "clang/Basic/Version.h"
-#define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING
-#endif
-
-namespace clang {
-class DiagnosticsEngine;
-class AnalyzerOptions;
-
-namespace ento {
-
-class CheckerOptInfo;
-
-/// Manages a set of available checkers for running a static analysis.
-/// The checkers are organized into packages by full name, where including
-/// a package will recursively include all subpackages and checkers within it.
-/// For example, the checker "core.builtin.NoReturnFunctionChecker" will be
-/// included if initializeManager() is called with an option of "core",
-/// "core.builtin", or the full name "core.builtin.NoReturnFunctionChecker".
-class CheckerRegistry {
-public:
- /// Initialization functions perform any necessary setup for a checker.
- /// They should include a call to CheckerManager::registerChecker.
- typedef void (*InitializationFunction)(CheckerManager &);
- struct CheckerInfo {
- InitializationFunction Initialize;
- StringRef FullName;
- StringRef Desc;
-
- CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc)
- : Initialize(fn), FullName(name), Desc(desc) {}
- };
-
- typedef std::vector<CheckerInfo> CheckerInfoList;
-
-private:
- template <typename T>
- static void initializeManager(CheckerManager &mgr) {
- mgr.registerChecker<T>();
- }
-
-public:
- /// Adds a checker to the registry. Use this non-templated overload when your
- /// checker requires custom initialization.
- void addChecker(InitializationFunction fn, StringRef fullName,
- StringRef desc);
-
- /// Adds a checker to the registry. Use this templated overload when your
- /// checker does not require any custom initialization.
- template <class T>
- void addChecker(StringRef fullName, StringRef desc) {
- // Avoid MSVC's Compiler Error C2276:
- // http://msdn.microsoft.com/en-us/library/850cstw1(v=VS.80).aspx
- addChecker(&CheckerRegistry::initializeManager<T>, fullName, desc);
- }
-
- /// Initializes a CheckerManager by calling the initialization functions for
- /// all checkers specified by the given CheckerOptInfo list. The order of this
- /// list is significant; later options can be used to reverse earlier ones.
- /// This can be used to exclude certain checkers in an included package.
- void initializeManager(CheckerManager &mgr,
- SmallVectorImpl<CheckerOptInfo> &opts) const;
-
- /// Check if every option corresponds to a specific checker or package.
- void validateCheckerOptions(const AnalyzerOptions &opts,
- DiagnosticsEngine &diags) const;
-
- /// Prints the name and description of all checkers in this registry.
- /// This output is not intended to be machine-parseable.
- void printHelp(raw_ostream &out, size_t maxNameChars = 30) const ;
-
-private:
- mutable CheckerInfoList Checkers;
- mutable llvm::StringMap<size_t> Packages;
-};
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/IssueHash.h b/include/clang/StaticAnalyzer/Core/IssueHash.h
deleted file mode 100644
index b3c4f14..0000000
--- a/include/clang/StaticAnalyzer/Core/IssueHash.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===---------- IssueHash.h - Generate identification hashes ----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H
-#define LLVM_CLANG_STATICANALYZER_CORE_ISSUE_HASH_H
-
-#include "llvm/ADT/SmallString.h"
-
-namespace clang {
-class Decl;
-class SourceManager;
-class FullSourceLoc;
-class LangOptions;
-
-/// \brief Get an MD5 hash to help identify bugs.
-///
-/// This function returns a hash that helps identify bugs within a source file.
-/// This identification can be utilized to diff diagnostic results on different
-/// snapshots of a projects, or maintain a database of suppressed diagnotics.
-///
-/// The hash contains the normalized text of the location associated with the
-/// diagnostic. Normalization means removing the whitespaces. The associated
-/// location is the either the last location of a diagnostic path or a uniqueing
-/// location. The bugtype and the name of the checker is also part of the hash.
-/// The last component is the string representation of the enclosing declaration
-/// of the associated location.
-///
-/// In case a new hash is introduced, the old one should still be maintained for
-/// a while. One should not introduce a new hash for every change, it is
-/// possible to introduce experimental hashes that may change in the future.
-/// Such hashes should be marked as experimental using a comment in the plist
-/// files.
-llvm::SmallString<32> GetIssueHash(const SourceManager &SM,
- FullSourceLoc &IssueLoc,
- llvm::StringRef CheckerName,
- llvm::StringRef BugType, const Decl *D,
- const LangOptions &LangOpts);
-
-/// \brief Get the string representation of issue hash. See GetIssueHash() for
-/// more information.
-std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc,
- llvm::StringRef CheckerName, llvm::StringRef BugType,
- const Decl *D, const LangOptions &LangOpts);
-} // namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
deleted file mode 100644
index ce512fd..0000000
--- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h
+++ /dev/null
@@ -1,40 +0,0 @@
-//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interface to create different path diagostic clients.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H
-
-#include <string>
-#include <vector>
-
-namespace clang {
-
-class AnalyzerOptions;
-class Preprocessor;
-
-namespace ento {
-
-class PathDiagnosticConsumer;
-typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers;
-
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN)\
-void CREATEFN(AnalyzerOptions &AnalyzerOpts,\
- PathDiagnosticConsumers &C,\
- const std::string &Prefix,\
- const Preprocessor &PP);
-#include "clang/StaticAnalyzer/Core/Analyses.def"
-
-} // end 'ento' namespace
-} // end 'clang' namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
deleted file mode 100644
index cc8a9b8..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h
+++ /dev/null
@@ -1,109 +0,0 @@
-//== APSIntType.h - Simple record of the type of APSInts --------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H
-
-#include "llvm/ADT/APSInt.h"
-#include <tuple>
-
-namespace clang {
-namespace ento {
-
-/// \brief A record of the "type" of an APSInt, used for conversions.
-class APSIntType {
- uint32_t BitWidth;
- bool IsUnsigned;
-
-public:
- APSIntType(uint32_t Width, bool Unsigned)
- : BitWidth(Width), IsUnsigned(Unsigned) {}
-
- /* implicit */ APSIntType(const llvm::APSInt &Value)
- : BitWidth(Value.getBitWidth()), IsUnsigned(Value.isUnsigned()) {}
-
- uint32_t getBitWidth() const { return BitWidth; }
- bool isUnsigned() const { return IsUnsigned; }
-
- /// \brief Convert a given APSInt, in place, to match this type.
- ///
- /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives
- /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF).
- void apply(llvm::APSInt &Value) const {
- // Note the order here. We extend first to preserve the sign, if this value
- // is signed, /then/ match the signedness of the result type.
- Value = Value.extOrTrunc(BitWidth);
- Value.setIsUnsigned(IsUnsigned);
- }
-
- /// Convert and return a new APSInt with the given value, but this
- /// type's bit width and signedness.
- ///
- /// \see apply
- llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY {
- llvm::APSInt Result(Value, Value.isUnsigned());
- apply(Result);
- return Result;
- }
-
- /// Returns an all-zero value for this type.
- llvm::APSInt getZeroValue() const LLVM_READONLY {
- return llvm::APSInt(BitWidth, IsUnsigned);
- }
-
- /// Returns the minimum value for this type.
- llvm::APSInt getMinValue() const LLVM_READONLY {
- return llvm::APSInt::getMinValue(BitWidth, IsUnsigned);
- }
-
- /// Returns the maximum value for this type.
- llvm::APSInt getMaxValue() const LLVM_READONLY {
- return llvm::APSInt::getMaxValue(BitWidth, IsUnsigned);
- }
-
- llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY {
- return (llvm::APSInt(BitWidth, IsUnsigned) = RawValue);
- }
-
- /// Used to classify whether a value is representable using this type.
- ///
- /// \see testInRange
- enum RangeTestResultKind {
- RTR_Below = -1, ///< Value is less than the minimum representable value.
- RTR_Within = 0, ///< Value is representable using this type.
- RTR_Above = 1 ///< Value is greater than the maximum representable value.
- };
-
- /// Tests whether a given value is losslessly representable using this type.
- ///
- /// \param Val The value to test.
- /// \param AllowMixedSign Whether or not to allow signedness conversions.
- /// This determines whether -1s8 is considered in range
- /// for 'unsigned char' (u8).
- RangeTestResultKind testInRange(const llvm::APSInt &Val,
- bool AllowMixedSign) const LLVM_READONLY;
-
- bool operator==(const APSIntType &Other) const {
- return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned;
- }
-
- /// \brief Provide an ordering for finding a common conversion type.
- ///
- /// Unsigned integers are considered to be better conversion types than
- /// signed integers of the same width.
- bool operator<(const APSIntType &Other) const {
- return std::tie(BitWidth, IsUnsigned) <
- std::tie(Other.BitWidth, Other.IsUnsigned);
- }
-};
-
-} // end ento namespace
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
deleted file mode 100644
index 3e0913e..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h
+++ /dev/null
@@ -1,135 +0,0 @@
-//== AnalysisManager.h - Path sensitive analysis data manager ------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the AnalysisManager class that manages the data and policy
-// for path sensitive analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H
-
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h"
-
-namespace clang {
-
-class CodeInjector;
-
-namespace ento {
- class CheckerManager;
-
-class AnalysisManager : public BugReporterData {
- virtual void anchor();
- AnalysisDeclContextManager AnaCtxMgr;
-
- ASTContext &Ctx;
- DiagnosticsEngine &Diags;
- const LangOptions &LangOpts;
- PathDiagnosticConsumers PathConsumers;
-
- // Configurable components creators.
- StoreManagerCreator CreateStoreMgr;
- ConstraintManagerCreator CreateConstraintMgr;
-
- CheckerManager *CheckerMgr;
-
-public:
- AnalyzerOptions &options;
-
- AnalysisManager(ASTContext &ctx,DiagnosticsEngine &diags,
- const LangOptions &lang,
- const PathDiagnosticConsumers &Consumers,
- StoreManagerCreator storemgr,
- ConstraintManagerCreator constraintmgr,
- CheckerManager *checkerMgr,
- AnalyzerOptions &Options,
- CodeInjector* injector = nullptr);
-
- ~AnalysisManager() override;
-
- void ClearContexts() {
- AnaCtxMgr.clear();
- }
-
- AnalysisDeclContextManager& getAnalysisDeclContextManager() {
- return AnaCtxMgr;
- }
-
- StoreManagerCreator getStoreManagerCreator() {
- return CreateStoreMgr;
- }
-
- AnalyzerOptions& getAnalyzerOptions() override {
- return options;
- }
-
- ConstraintManagerCreator getConstraintManagerCreator() {
- return CreateConstraintMgr;
- }
-
- CheckerManager *getCheckerManager() const { return CheckerMgr; }
-
- ASTContext &getASTContext() override {
- return Ctx;
- }
-
- SourceManager &getSourceManager() override {
- return getASTContext().getSourceManager();
- }
-
- DiagnosticsEngine &getDiagnostic() override {
- return Diags;
- }
-
- const LangOptions &getLangOpts() const {
- return LangOpts;
- }
-
- ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override {
- return PathConsumers;
- }
-
- void FlushDiagnostics();
-
- bool shouldVisualize() const {
- return options.visualizeExplodedGraphWithGraphViz ||
- options.visualizeExplodedGraphWithUbiGraph;
- }
-
- bool shouldInlineCall() const {
- return options.getIPAMode() != IPAK_None;
- }
-
- CFG *getCFG(Decl const *D) {
- return AnaCtxMgr.getContext(D)->getCFG();
- }
-
- template <typename T>
- T *getAnalysis(Decl const *D) {
- return AnaCtxMgr.getContext(D)->getAnalysis<T>();
- }
-
- ParentMap &getParentMap(Decl const *D) {
- return AnaCtxMgr.getContext(D)->getParentMap();
- }
-
- AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) {
- return AnaCtxMgr.getContext(D);
- }
-};
-
-} // enAnaCtxMgrspace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
deleted file mode 100644
index 5b007f1..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
+++ /dev/null
@@ -1,200 +0,0 @@
-//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines BasicValueFactory, a class that manages the lifetime
-// of APSInt objects and symbolic constraints used by ExprEngine
-// and related classes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
-
-namespace clang {
-namespace ento {
-
-class CompoundValData : public llvm::FoldingSetNode {
- QualType T;
- llvm::ImmutableList<SVal> L;
-
-public:
- CompoundValData(QualType t, llvm::ImmutableList<SVal> l)
- : T(t), L(l) {}
-
- typedef llvm::ImmutableList<SVal>::iterator iterator;
- iterator begin() const { return L.begin(); }
- iterator end() const { return L.end(); }
-
- static void Profile(llvm::FoldingSetNodeID& ID, QualType T,
- llvm::ImmutableList<SVal> L);
-
- void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
-};
-
-class LazyCompoundValData : public llvm::FoldingSetNode {
- StoreRef store;
- const TypedValueRegion *region;
-public:
- LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r)
- : store(st), region(r) {}
-
- const void *getStore() const { return store.getStore(); }
- const TypedValueRegion *getRegion() const { return region; }
-
- static void Profile(llvm::FoldingSetNodeID& ID,
- const StoreRef &store,
- const TypedValueRegion *region);
-
- void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); }
-};
-
-class BasicValueFactory {
- typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
- APSIntSetTy;
-
- ASTContext &Ctx;
- llvm::BumpPtrAllocator& BPAlloc;
-
- APSIntSetTy APSIntSet;
- void * PersistentSVals;
- void * PersistentSValPairs;
-
- llvm::ImmutableList<SVal>::Factory SValListFactory;
- llvm::FoldingSet<CompoundValData> CompoundValDataSet;
- llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
-
- // This is private because external clients should use the factory
- // method that takes a QualType.
- const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
-
-public:
- BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc)
- : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr),
- PersistentSValPairs(nullptr), SValListFactory(Alloc) {}
-
- ~BasicValueFactory();
-
- ASTContext &getContext() const { return Ctx; }
-
- const llvm::APSInt& getValue(const llvm::APSInt& X);
- const llvm::APSInt& getValue(const llvm::APInt& X, bool isUnsigned);
- const llvm::APSInt& getValue(uint64_t X, QualType T);
-
- /// Returns the type of the APSInt used to store values of the given QualType.
- APSIntType getAPSIntType(QualType T) const {
- assert(T->isIntegralOrEnumerationType() || Loc::isLocType(T));
- return APSIntType(Ctx.getTypeSize(T),
- !T->isSignedIntegerOrEnumerationType());
- }
-
- /// Convert - Create a new persistent APSInt with the same value as 'From'
- /// but with the bitwidth and signedness of 'To'.
- const llvm::APSInt &Convert(const llvm::APSInt& To,
- const llvm::APSInt& From) {
- APSIntType TargetType(To);
- if (TargetType == APSIntType(From))
- return From;
-
- return getValue(TargetType.convert(From));
- }
-
- const llvm::APSInt &Convert(QualType T, const llvm::APSInt &From) {
- APSIntType TargetType = getAPSIntType(T);
- if (TargetType == APSIntType(From))
- return From;
-
- return getValue(TargetType.convert(From));
- }
-
- const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) {
- QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy;
- return getValue(X, T);
- }
-
- inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) {
- return getValue(APSIntType(v).getMaxValue());
- }
-
- inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) {
- return getValue(APSIntType(v).getMinValue());
- }
-
- inline const llvm::APSInt& getMaxValue(QualType T) {
- return getValue(getAPSIntType(T).getMaxValue());
- }
-
- inline const llvm::APSInt& getMinValue(QualType T) {
- return getValue(getAPSIntType(T).getMinValue());
- }
-
- inline const llvm::APSInt& Add1(const llvm::APSInt& V) {
- llvm::APSInt X = V;
- ++X;
- return getValue(X);
- }
-
- inline const llvm::APSInt& Sub1(const llvm::APSInt& V) {
- llvm::APSInt X = V;
- --X;
- return getValue(X);
- }
-
- inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) {
- return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
- }
-
- inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) {
- return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned);
- }
-
- inline const llvm::APSInt& getTruthValue(bool b, QualType T) {
- return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false);
- }
-
- inline const llvm::APSInt& getTruthValue(bool b) {
- return getTruthValue(b, Ctx.getLogicalOperationType());
- }
-
- const CompoundValData *getCompoundValData(QualType T,
- llvm::ImmutableList<SVal> Vals);
-
- const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store,
- const TypedValueRegion *region);
-
- llvm::ImmutableList<SVal> getEmptySValList() {
- return SValListFactory.getEmptyList();
- }
-
- llvm::ImmutableList<SVal> consVals(SVal X, llvm::ImmutableList<SVal> L) {
- return SValListFactory.add(X, L);
- }
-
- const llvm::APSInt* evalAPSInt(BinaryOperator::Opcode Op,
- const llvm::APSInt& V1,
- const llvm::APSInt& V2);
-
- const std::pair<SVal, uintptr_t>&
- getPersistentSValWithData(const SVal& V, uintptr_t Data);
-
- const std::pair<SVal, SVal>&
- getPersistentSValPair(const SVal& V1, const SVal& V2);
-
- const SVal* getPersistentSVal(SVal X);
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
deleted file mode 100644
index 1d779e6..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//==- BlockCounter.h - ADT for counting block visits ---------------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines BlockCounter, an abstract data type used to count
-// the number of times a given block has been visited along a path
-// analyzed by CoreEngine.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H
-
-#include "llvm/Support/Allocator.h"
-
-namespace clang {
-
-class StackFrameContext;
-
-namespace ento {
-
-/// \class BlockCounter
-/// \brief An abstract data type used to count the number of times a given
-/// block has been visited along a path analyzed by CoreEngine.
-class BlockCounter {
- void *Data;
-
- BlockCounter(void *D) : Data(D) {}
-
-public:
- BlockCounter() : Data(nullptr) {}
-
- unsigned getNumVisited(const StackFrameContext *CallSite,
- unsigned BlockID) const;
-
- class Factory {
- void *F;
- public:
- Factory(llvm::BumpPtrAllocator& Alloc);
- ~Factory();
-
- BlockCounter GetEmptyCounter();
- BlockCounter IncrementCount(BlockCounter BC,
- const StackFrameContext *CallSite,
- unsigned BlockID);
- };
-
- friend class Factory;
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
deleted file mode 100644
index b09dffa..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
+++ /dev/null
@@ -1,1091 +0,0 @@
-//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-/// \file This file defines CallEvent and its subclasses, which represent path-
-/// sensitive instances of different kinds of function and method calls
-/// (C, C++, and Objective-C).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H
-
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/ADT/PointerIntPair.h"
-
-namespace clang {
-class ProgramPoint;
-class ProgramPointTag;
-
-namespace ento {
-
-enum CallEventKind {
- CE_Function,
- CE_CXXMember,
- CE_CXXMemberOperator,
- CE_CXXDestructor,
- CE_BEG_CXX_INSTANCE_CALLS = CE_CXXMember,
- CE_END_CXX_INSTANCE_CALLS = CE_CXXDestructor,
- CE_CXXConstructor,
- CE_CXXAllocator,
- CE_BEG_FUNCTION_CALLS = CE_Function,
- CE_END_FUNCTION_CALLS = CE_CXXAllocator,
- CE_Block,
- CE_ObjCMessage
-};
-
-class CallEvent;
-class CallEventManager;
-
-template<typename T = CallEvent>
-class CallEventRef : public IntrusiveRefCntPtr<const T> {
-public:
- CallEventRef(const T *Call) : IntrusiveRefCntPtr<const T>(Call) {}
- CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {}
-
- CallEventRef<T> cloneWithState(ProgramStateRef State) const {
- return this->get()->template cloneWithState<T>(State);
- }
-
- // Allow implicit conversions to a superclass type, since CallEventRef
- // behaves like a pointer-to-const.
- template <typename SuperT>
- operator CallEventRef<SuperT> () const {
- return this->get();
- }
-};
-
-/// \class RuntimeDefinition
-/// \brief Defines the runtime definition of the called function.
-///
-/// Encapsulates the information we have about which Decl will be used
-/// when the call is executed on the given path. When dealing with dynamic
-/// dispatch, the information is based on DynamicTypeInfo and might not be
-/// precise.
-class RuntimeDefinition {
- /// The Declaration of the function which could be called at runtime.
- /// NULL if not available.
- const Decl *D;
-
- /// The region representing an object (ObjC/C++) on which the method is
- /// called. With dynamic dispatch, the method definition depends on the
- /// runtime type of this object. NULL when the DynamicTypeInfo is
- /// precise.
- const MemRegion *R;
-
-public:
- RuntimeDefinition(): D(nullptr), R(nullptr) {}
- RuntimeDefinition(const Decl *InD): D(InD), R(nullptr) {}
- RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {}
- const Decl *getDecl() { return D; }
-
- /// \brief Check if the definition we have is precise.
- /// If not, it is possible that the call dispatches to another definition at
- /// execution time.
- bool mayHaveOtherDefinitions() { return R != nullptr; }
-
- /// When other definitions are possible, returns the region whose runtime type
- /// determines the method definition.
- const MemRegion *getDispatchRegion() { return R; }
-};
-
-/// \brief Represents an abstract call to a function or method along a
-/// particular path.
-///
-/// CallEvents are created through the factory methods of CallEventManager.
-///
-/// CallEvents should always be cheap to create and destroy. In order for
-/// CallEventManager to be able to re-use CallEvent-sized memory blocks,
-/// subclasses of CallEvent may not add any data members to the base class.
-/// Use the "Data" and "Location" fields instead.
-class CallEvent {
-public:
- typedef CallEventKind Kind;
-
-private:
- ProgramStateRef State;
- const LocationContext *LCtx;
- llvm::PointerUnion<const Expr *, const Decl *> Origin;
-
- void operator=(const CallEvent &) = delete;
-
-protected:
- // This is user data for subclasses.
- const void *Data;
-
- // This is user data for subclasses.
- // This should come right before RefCount, so that the two fields can be
- // packed together on LP64 platforms.
- SourceLocation Location;
-
-private:
- mutable unsigned RefCount;
-
- template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo;
- void Retain() const { ++RefCount; }
- void Release() const;
-
-protected:
- friend class CallEventManager;
-
- CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx)
- : State(state), LCtx(lctx), Origin(E), RefCount(0) {}
-
- CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx)
- : State(state), LCtx(lctx), Origin(D), RefCount(0) {}
-
- // DO NOT MAKE PUBLIC
- CallEvent(const CallEvent &Original)
- : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin),
- Data(Original.Data), Location(Original.Location), RefCount(0) {}
-
- /// Copies this CallEvent, with vtable intact, into a new block of memory.
- virtual void cloneTo(void *Dest) const = 0;
-
- /// \brief Get the value of arbitrary expressions at this point in the path.
- SVal getSVal(const Stmt *S) const {
- return getState()->getSVal(S, getLocationContext());
- }
-
-
- typedef SmallVectorImpl<SVal> ValueList;
-
- /// \brief Used to specify non-argument regions that will be invalidated as a
- /// result of this call.
- virtual void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const {}
-
-public:
- virtual ~CallEvent() {}
-
- /// \brief Returns the kind of call this is.
- virtual Kind getKind() const = 0;
-
- /// \brief Returns the declaration of the function or method that will be
- /// called. May be null.
- virtual const Decl *getDecl() const {
- return Origin.dyn_cast<const Decl *>();
- }
-
- /// \brief The state in which the call is being evaluated.
- const ProgramStateRef &getState() const {
- return State;
- }
-
- /// \brief The context in which the call is being evaluated.
- const LocationContext *getLocationContext() const {
- return LCtx;
- }
-
- /// \brief Returns the definition of the function or method that will be
- /// called.
- virtual RuntimeDefinition getRuntimeDefinition() const = 0;
-
- /// \brief Returns the expression whose value will be the result of this call.
- /// May be null.
- const Expr *getOriginExpr() const {
- return Origin.dyn_cast<const Expr *>();
- }
-
- /// \brief Returns the number of arguments (explicit and implicit).
- ///
- /// Note that this may be greater than the number of parameters in the
- /// callee's declaration, and that it may include arguments not written in
- /// the source.
- virtual unsigned getNumArgs() const = 0;
-
- /// \brief Returns true if the callee is known to be from a system header.
- bool isInSystemHeader() const {
- const Decl *D = getDecl();
- if (!D)
- return false;
-
- SourceLocation Loc = D->getLocation();
- if (Loc.isValid()) {
- const SourceManager &SM =
- getState()->getStateManager().getContext().getSourceManager();
- return SM.isInSystemHeader(D->getLocation());
- }
-
- // Special case for implicitly-declared global operator new/delete.
- // These should be considered system functions.
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
- return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal();
-
- return false;
- }
-
- /// \brief Returns a source range for the entire call, suitable for
- /// outputting in diagnostics.
- virtual SourceRange getSourceRange() const {
- return getOriginExpr()->getSourceRange();
- }
-
- /// \brief Returns the value of a given argument at the time of the call.
- virtual SVal getArgSVal(unsigned Index) const;
-
- /// \brief Returns the expression associated with a given argument.
- /// May be null if this expression does not appear in the source.
- virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; }
-
- /// \brief Returns the source range for errors associated with this argument.
- ///
- /// May be invalid if the argument is not written in the source.
- virtual SourceRange getArgSourceRange(unsigned Index) const;
-
- /// \brief Returns the result type, adjusted for references.
- QualType getResultType() const;
-
- /// \brief Returns the return value of the call.
- ///
- /// This should only be called if the CallEvent was created using a state in
- /// which the return value has already been bound to the origin expression.
- SVal getReturnValue() const;
-
- /// \brief Returns true if the type of any of the non-null arguments satisfies
- /// the condition.
- bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const;
-
- /// \brief Returns true if any of the arguments appear to represent callbacks.
- bool hasNonZeroCallbackArg() const;
-
- /// \brief Returns true if any of the arguments is void*.
- bool hasVoidPointerToNonConstArg() const;
-
- /// \brief Returns true if any of the arguments are known to escape to long-
- /// term storage, even if this method will not modify them.
- // NOTE: The exact semantics of this are still being defined!
- // We don't really want a list of hardcoded exceptions in the long run,
- // but we don't want duplicated lists of known APIs in the short term either.
- virtual bool argumentsMayEscape() const {
- return hasNonZeroCallbackArg();
- }
-
- /// \brief Returns true if the callee is an externally-visible function in the
- /// top-level namespace, such as \c malloc.
- ///
- /// You can use this call to determine that a particular function really is
- /// a library function and not, say, a C++ member function with the same name.
- ///
- /// If a name is provided, the function must additionally match the given
- /// name.
- ///
- /// Note that this deliberately excludes C++ library functions in the \c std
- /// namespace, but will include C library functions accessed through the
- /// \c std namespace. This also does not check if the function is declared
- /// as 'extern "C"', or if it uses C++ name mangling.
- // FIXME: Add a helper for checking namespaces.
- // FIXME: Move this down to AnyFunctionCall once checkers have more
- // precise callbacks.
- bool isGlobalCFunction(StringRef SpecificName = StringRef()) const;
-
- /// \brief Returns the name of the callee, if its name is a simple identifier.
- ///
- /// Note that this will fail for Objective-C methods, blocks, and C++
- /// overloaded operators. The former is named by a Selector rather than a
- /// simple identifier, and the latter two do not have names.
- // FIXME: Move this down to AnyFunctionCall once checkers have more
- // precise callbacks.
- const IdentifierInfo *getCalleeIdentifier() const {
- const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl());
- if (!ND)
- return nullptr;
- return ND->getIdentifier();
- }
-
- /// \brief Returns an appropriate ProgramPoint for this call.
- ProgramPoint getProgramPoint(bool IsPreVisit = false,
- const ProgramPointTag *Tag = nullptr) const;
-
- /// \brief Returns a new state with all argument regions invalidated.
- ///
- /// This accepts an alternate state in case some processing has already
- /// occurred.
- ProgramStateRef invalidateRegions(unsigned BlockCount,
- ProgramStateRef Orig = nullptr) const;
-
- typedef std::pair<Loc, SVal> FrameBindingTy;
- typedef SmallVectorImpl<FrameBindingTy> BindingsTy;
-
- /// Populates the given SmallVector with the bindings in the callee's stack
- /// frame at the start of this call.
- virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const = 0;
-
- /// Returns a copy of this CallEvent, but using the given state.
- template <typename T>
- CallEventRef<T> cloneWithState(ProgramStateRef NewState) const;
-
- /// Returns a copy of this CallEvent, but using the given state.
- CallEventRef<> cloneWithState(ProgramStateRef NewState) const {
- return cloneWithState<CallEvent>(NewState);
- }
-
- /// \brief Returns true if this is a statement is a function or method call
- /// of some kind.
- static bool isCallStmt(const Stmt *S);
-
- /// \brief Returns the result type of a function or method declaration.
- ///
- /// This will return a null QualType if the result type cannot be determined.
- static QualType getDeclaredResultType(const Decl *D);
-
- /// \brief Returns true if the given decl is known to be variadic.
- ///
- /// \p D must not be null.
- static bool isVariadic(const Decl *D);
-
- // Iterator access to formal parameters and their types.
-private:
- typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun;
-
-public:
- /// Return call's formal parameters.
- ///
- /// Remember that the number of formal parameters may not match the number
- /// of arguments for all calls. However, the first parameter will always
- /// correspond with the argument value returned by \c getArgSVal(0).
- virtual ArrayRef<ParmVarDecl*> parameters() const = 0;
-
- typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, get_type_fun>
- param_type_iterator;
-
- /// Returns an iterator over the types of the call's formal parameters.
- ///
- /// This uses the callee decl found by default name lookup rather than the
- /// definition because it represents a public interface, and probably has
- /// more annotations.
- param_type_iterator param_type_begin() const {
- return llvm::map_iterator(parameters().begin(),
- get_type_fun(&ParmVarDecl::getType));
- }
- /// \sa param_type_begin()
- param_type_iterator param_type_end() const {
- return llvm::map_iterator(parameters().end(),
- get_type_fun(&ParmVarDecl::getType));
- }
-
- // For debugging purposes only
- void dump(raw_ostream &Out) const;
- void dump() const;
-};
-
-
-/// \brief Represents a call to any sort of function that might have a
-/// FunctionDecl.
-class AnyFunctionCall : public CallEvent {
-protected:
- AnyFunctionCall(const Expr *E, ProgramStateRef St,
- const LocationContext *LCtx)
- : CallEvent(E, St, LCtx) {}
- AnyFunctionCall(const Decl *D, ProgramStateRef St,
- const LocationContext *LCtx)
- : CallEvent(D, St, LCtx) {}
- AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {}
-
-public:
- // This function is overridden by subclasses, but they must return
- // a FunctionDecl.
- const FunctionDecl *getDecl() const override {
- return cast<FunctionDecl>(CallEvent::getDecl());
- }
-
- RuntimeDefinition getRuntimeDefinition() const override {
- const FunctionDecl *FD = getDecl();
- // Note that the AnalysisDeclContext will have the FunctionDecl with
- // the definition (if one exists).
- if (FD) {
- AnalysisDeclContext *AD =
- getLocationContext()->getAnalysisDeclContext()->
- getManager()->getContext(FD);
- if (AD->getBody())
- return RuntimeDefinition(AD->getDecl());
- }
-
- return RuntimeDefinition();
- }
-
- bool argumentsMayEscape() const override;
-
- void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const override;
-
- ArrayRef<ParmVarDecl *> parameters() const override;
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() >= CE_BEG_FUNCTION_CALLS &&
- CA->getKind() <= CE_END_FUNCTION_CALLS;
- }
-};
-
-/// \brief Represents a C function or static C++ member function call.
-///
-/// Example: \c fun()
-class SimpleFunctionCall : public AnyFunctionCall {
- friend class CallEventManager;
-
-protected:
- SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {}
- SimpleFunctionCall(const SimpleFunctionCall &Other)
- : AnyFunctionCall(Other) {}
- void cloneTo(void *Dest) const override {
- new (Dest) SimpleFunctionCall(*this);
- }
-
-public:
- virtual const CallExpr *getOriginExpr() const {
- return cast<CallExpr>(AnyFunctionCall::getOriginExpr());
- }
-
- const FunctionDecl *getDecl() const override;
-
- unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
-
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index);
- }
-
- Kind getKind() const override { return CE_Function; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_Function;
- }
-};
-
-/// \brief Represents a call to a block.
-///
-/// Example: <tt>^{ /* ... */ }()</tt>
-class BlockCall : public CallEvent {
- friend class CallEventManager;
-
-protected:
- BlockCall(const CallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : CallEvent(CE, St, LCtx) {}
-
- BlockCall(const BlockCall &Other) : CallEvent(Other) {}
- void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); }
-
- void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const override;
-
-public:
- virtual const CallExpr *getOriginExpr() const {
- return cast<CallExpr>(CallEvent::getOriginExpr());
- }
-
- unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
-
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index);
- }
-
- /// \brief Returns the region associated with this instance of the block.
- ///
- /// This may be NULL if the block's origin is unknown.
- const BlockDataRegion *getBlockRegion() const;
-
- const BlockDecl *getDecl() const override {
- const BlockDataRegion *BR = getBlockRegion();
- if (!BR)
- return nullptr;
- return BR->getDecl();
- }
-
- bool isConversionFromLambda() const {
- const BlockDecl *BD = getDecl();
- if (!BD)
- return false;
-
- return BD->isConversionFromLambda();
- }
-
- /// \brief For a block converted from a C++ lambda, returns the block
- /// VarRegion for the variable holding the captured C++ lambda record.
- const VarRegion *getRegionStoringCapturedLambda() const {
- assert(isConversionFromLambda());
- const BlockDataRegion *BR = getBlockRegion();
- assert(BR && "Block converted from lambda must have a block region");
-
- auto I = BR->referenced_vars_begin();
- assert(I != BR->referenced_vars_end());
-
- return I.getCapturedRegion();
- }
-
- RuntimeDefinition getRuntimeDefinition() const override {
- if (!isConversionFromLambda())
- return RuntimeDefinition(getDecl());
-
- // Clang converts lambdas to blocks with an implicit user-defined
- // conversion operator method on the lambda record that looks (roughly)
- // like:
- //
- // typedef R(^block_type)(P1, P2, ...);
- // operator block_type() const {
- // auto Lambda = *this;
- // return ^(P1 p1, P2 p2, ...){
- // /* return Lambda(p1, p2, ...); */
- // };
- // }
- //
- // Here R is the return type of the lambda and P1, P2, ... are
- // its parameter types. 'Lambda' is a fake VarDecl captured by the block
- // that is initialized to a copy of the lambda.
- //
- // Sema leaves the body of a lambda-converted block empty (it is
- // produced by CodeGen), so we can't analyze it directly. Instead, we skip
- // the block body and analyze the operator() method on the captured lambda.
- const VarDecl *LambdaVD = getRegionStoringCapturedLambda()->getDecl();
- const CXXRecordDecl *LambdaDecl = LambdaVD->getType()->getAsCXXRecordDecl();
- CXXMethodDecl* LambdaCallOperator = LambdaDecl->getLambdaCallOperator();
-
- return RuntimeDefinition(LambdaCallOperator);
- }
-
- bool argumentsMayEscape() const override {
- return true;
- }
-
- void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const override;
-
- ArrayRef<ParmVarDecl*> parameters() const override;
-
- Kind getKind() const override { return CE_Block; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_Block;
- }
-};
-
-/// \brief Represents a non-static C++ member function call, no matter how
-/// it is written.
-class CXXInstanceCall : public AnyFunctionCall {
-protected:
- void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const override;
-
- CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {}
- CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St,
- const LocationContext *LCtx)
- : AnyFunctionCall(D, St, LCtx) {}
-
-
- CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {}
-
-public:
- /// \brief Returns the expression representing the implicit 'this' object.
- virtual const Expr *getCXXThisExpr() const { return nullptr; }
-
- /// \brief Returns the value of the implicit 'this' object.
- virtual SVal getCXXThisVal() const;
-
- const FunctionDecl *getDecl() const override;
-
- RuntimeDefinition getRuntimeDefinition() const override;
-
- void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const override;
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS &&
- CA->getKind() <= CE_END_CXX_INSTANCE_CALLS;
- }
-};
-
-/// \brief Represents a non-static C++ member function call.
-///
-/// Example: \c obj.fun()
-class CXXMemberCall : public CXXInstanceCall {
- friend class CallEventManager;
-
-protected:
- CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : CXXInstanceCall(CE, St, LCtx) {}
-
- CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {}
- void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); }
-
-public:
- virtual const CXXMemberCallExpr *getOriginExpr() const {
- return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr());
- }
-
- unsigned getNumArgs() const override {
- if (const CallExpr *CE = getOriginExpr())
- return CE->getNumArgs();
- return 0;
- }
-
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index);
- }
-
- const Expr *getCXXThisExpr() const override;
-
- RuntimeDefinition getRuntimeDefinition() const override;
-
- Kind getKind() const override { return CE_CXXMember; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_CXXMember;
- }
-};
-
-/// \brief Represents a C++ overloaded operator call where the operator is
-/// implemented as a non-static member function.
-///
-/// Example: <tt>iter + 1</tt>
-class CXXMemberOperatorCall : public CXXInstanceCall {
- friend class CallEventManager;
-
-protected:
- CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St,
- const LocationContext *LCtx)
- : CXXInstanceCall(CE, St, LCtx) {}
-
- CXXMemberOperatorCall(const CXXMemberOperatorCall &Other)
- : CXXInstanceCall(Other) {}
- void cloneTo(void *Dest) const override {
- new (Dest) CXXMemberOperatorCall(*this);
- }
-
-public:
- virtual const CXXOperatorCallExpr *getOriginExpr() const {
- return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr());
- }
-
- unsigned getNumArgs() const override {
- return getOriginExpr()->getNumArgs() - 1;
- }
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index + 1);
- }
-
- const Expr *getCXXThisExpr() const override;
-
- Kind getKind() const override { return CE_CXXMemberOperator; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_CXXMemberOperator;
- }
-};
-
-/// \brief Represents an implicit call to a C++ destructor.
-///
-/// This can occur at the end of a scope (for automatic objects), at the end
-/// of a full-expression (for temporaries), or as part of a delete.
-class CXXDestructorCall : public CXXInstanceCall {
- friend class CallEventManager;
-
-protected:
- typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy;
-
- /// Creates an implicit destructor.
- ///
- /// \param DD The destructor that will be called.
- /// \param Trigger The statement whose completion causes this destructor call.
- /// \param Target The object region to be destructed.
- /// \param St The path-sensitive state at this point in the program.
- /// \param LCtx The location context at this point in the program.
- CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
- const MemRegion *Target, bool IsBaseDestructor,
- ProgramStateRef St, const LocationContext *LCtx)
- : CXXInstanceCall(DD, St, LCtx) {
- Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue();
- Location = Trigger->getLocEnd();
- }
-
- CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {}
- void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);}
-
-public:
- SourceRange getSourceRange() const override { return Location; }
- unsigned getNumArgs() const override { return 0; }
-
- RuntimeDefinition getRuntimeDefinition() const override;
-
- /// \brief Returns the value of the implicit 'this' object.
- SVal getCXXThisVal() const override;
-
- /// Returns true if this is a call to a base class destructor.
- bool isBaseDestructor() const {
- return DtorDataTy::getFromOpaqueValue(Data).getInt();
- }
-
- Kind getKind() const override { return CE_CXXDestructor; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_CXXDestructor;
- }
-};
-
-/// \brief Represents a call to a C++ constructor.
-///
-/// Example: \c T(1)
-class CXXConstructorCall : public AnyFunctionCall {
- friend class CallEventManager;
-
-protected:
- /// Creates a constructor call.
- ///
- /// \param CE The constructor expression as written in the source.
- /// \param Target The region where the object should be constructed. If NULL,
- /// a new symbolic region will be used.
- /// \param St The path-sensitive state at this point in the program.
- /// \param LCtx The location context at this point in the program.
- CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target,
- ProgramStateRef St, const LocationContext *LCtx)
- : AnyFunctionCall(CE, St, LCtx) {
- Data = Target;
- }
-
- CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
- void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); }
-
- void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const override;
-
-public:
- virtual const CXXConstructExpr *getOriginExpr() const {
- return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr());
- }
-
- const CXXConstructorDecl *getDecl() const override {
- return getOriginExpr()->getConstructor();
- }
-
- unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); }
-
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index);
- }
-
- /// \brief Returns the value of the implicit 'this' object.
- SVal getCXXThisVal() const;
-
- void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const override;
-
- Kind getKind() const override { return CE_CXXConstructor; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_CXXConstructor;
- }
-};
-
-/// \brief Represents the memory allocation call in a C++ new-expression.
-///
-/// This is a call to "operator new".
-class CXXAllocatorCall : public AnyFunctionCall {
- friend class CallEventManager;
-
-protected:
- CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St,
- const LocationContext *LCtx)
- : AnyFunctionCall(E, St, LCtx) {}
-
- CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {}
- void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); }
-
-public:
- virtual const CXXNewExpr *getOriginExpr() const {
- return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr());
- }
-
- const FunctionDecl *getDecl() const override {
- return getOriginExpr()->getOperatorNew();
- }
-
- unsigned getNumArgs() const override {
- return getOriginExpr()->getNumPlacementArgs() + 1;
- }
-
- const Expr *getArgExpr(unsigned Index) const override {
- // The first argument of an allocator call is the size of the allocation.
- if (Index == 0)
- return nullptr;
- return getOriginExpr()->getPlacementArg(Index - 1);
- }
-
- Kind getKind() const override { return CE_CXXAllocator; }
-
- static bool classof(const CallEvent *CE) {
- return CE->getKind() == CE_CXXAllocator;
- }
-};
-
-/// \brief Represents the ways an Objective-C message send can occur.
-//
-// Note to maintainers: OCM_Message should always be last, since it does not
-// need to fit in the Data field's low bits.
-enum ObjCMessageKind {
- OCM_PropertyAccess,
- OCM_Subscript,
- OCM_Message
-};
-
-/// \brief Represents any expression that calls an Objective-C method.
-///
-/// This includes all of the kinds listed in ObjCMessageKind.
-class ObjCMethodCall : public CallEvent {
- friend class CallEventManager;
-
- const PseudoObjectExpr *getContainingPseudoObjectExpr() const;
-
-protected:
- ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St,
- const LocationContext *LCtx)
- : CallEvent(Msg, St, LCtx) {
- Data = nullptr;
- }
-
- ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
- void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); }
-
- void getExtraInvalidatedValues(ValueList &Values,
- RegionAndSymbolInvalidationTraits *ETraits) const override;
-
- /// Check if the selector may have multiple definitions (may have overrides).
- virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,
- Selector Sel) const;
-
-public:
- virtual const ObjCMessageExpr *getOriginExpr() const {
- return cast<ObjCMessageExpr>(CallEvent::getOriginExpr());
- }
- const ObjCMethodDecl *getDecl() const override {
- return getOriginExpr()->getMethodDecl();
- }
- unsigned getNumArgs() const override {
- return getOriginExpr()->getNumArgs();
- }
- const Expr *getArgExpr(unsigned Index) const override {
- return getOriginExpr()->getArg(Index);
- }
-
- bool isInstanceMessage() const {
- return getOriginExpr()->isInstanceMessage();
- }
- ObjCMethodFamily getMethodFamily() const {
- return getOriginExpr()->getMethodFamily();
- }
- Selector getSelector() const {
- return getOriginExpr()->getSelector();
- }
-
- SourceRange getSourceRange() const override;
-
- /// \brief Returns the value of the receiver at the time of this call.
- SVal getReceiverSVal() const;
-
- /// \brief Return the value of 'self' if available.
- SVal getSelfSVal() const;
-
- /// \brief Get the interface for the receiver.
- ///
- /// This works whether this is an instance message or a class message.
- /// However, it currently just uses the static type of the receiver.
- const ObjCInterfaceDecl *getReceiverInterface() const {
- return getOriginExpr()->getReceiverInterface();
- }
-
- /// \brief Checks if the receiver refers to 'self' or 'super'.
- bool isReceiverSelfOrSuper() const;
-
- /// Returns how the message was written in the source (property access,
- /// subscript, or explicit message send).
- ObjCMessageKind getMessageKind() const;
-
- /// Returns true if this property access or subscript is a setter (has the
- /// form of an assignment).
- bool isSetter() const {
- switch (getMessageKind()) {
- case OCM_Message:
- llvm_unreachable("This is not a pseudo-object access!");
- case OCM_PropertyAccess:
- return getNumArgs() > 0;
- case OCM_Subscript:
- return getNumArgs() > 1;
- }
- llvm_unreachable("Unknown message kind");
- }
-
- RuntimeDefinition getRuntimeDefinition() const override;
-
- bool argumentsMayEscape() const override;
-
- void getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
- BindingsTy &Bindings) const override;
-
- ArrayRef<ParmVarDecl*> parameters() const override;
-
- Kind getKind() const override { return CE_ObjCMessage; }
-
- static bool classof(const CallEvent *CA) {
- return CA->getKind() == CE_ObjCMessage;
- }
-};
-
-
-/// \brief Manages the lifetime of CallEvent objects.
-///
-/// CallEventManager provides a way to create arbitrary CallEvents "on the
-/// stack" as if they were value objects by keeping a cache of CallEvent-sized
-/// memory blocks. The CallEvents created by CallEventManager are only valid
-/// for the lifetime of the OwnedCallEvent that holds them; right now these
-/// objects cannot be copied and ownership cannot be transferred.
-class CallEventManager {
- friend class CallEvent;
-
- llvm::BumpPtrAllocator &Alloc;
- SmallVector<void *, 8> Cache;
- typedef SimpleFunctionCall CallEventTemplateTy;
-
- void reclaim(const void *Memory) {
- Cache.push_back(const_cast<void *>(Memory));
- }
-
- /// Returns memory that can be initialized as a CallEvent.
- void *allocate() {
- if (Cache.empty())
- return Alloc.Allocate<CallEventTemplateTy>();
- else
- return Cache.pop_back_val();
- }
-
- template <typename T, typename Arg>
- T *create(Arg A, ProgramStateRef St, const LocationContext *LCtx) {
- static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
- "CallEvent subclasses are not all the same size");
- return new (allocate()) T(A, St, LCtx);
- }
-
- template <typename T, typename Arg1, typename Arg2>
- T *create(Arg1 A1, Arg2 A2, ProgramStateRef St, const LocationContext *LCtx) {
- static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
- "CallEvent subclasses are not all the same size");
- return new (allocate()) T(A1, A2, St, LCtx);
- }
-
- template <typename T, typename Arg1, typename Arg2, typename Arg3>
- T *create(Arg1 A1, Arg2 A2, Arg3 A3, ProgramStateRef St,
- const LocationContext *LCtx) {
- static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
- "CallEvent subclasses are not all the same size");
- return new (allocate()) T(A1, A2, A3, St, LCtx);
- }
-
- template <typename T, typename Arg1, typename Arg2, typename Arg3,
- typename Arg4>
- T *create(Arg1 A1, Arg2 A2, Arg3 A3, Arg4 A4, ProgramStateRef St,
- const LocationContext *LCtx) {
- static_assert(sizeof(T) == sizeof(CallEventTemplateTy),
- "CallEvent subclasses are not all the same size");
- return new (allocate()) T(A1, A2, A3, A4, St, LCtx);
- }
-
-public:
- CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {}
-
-
- CallEventRef<>
- getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State);
-
-
- CallEventRef<>
- getSimpleCall(const CallExpr *E, ProgramStateRef State,
- const LocationContext *LCtx);
-
- CallEventRef<ObjCMethodCall>
- getObjCMethodCall(const ObjCMessageExpr *E, ProgramStateRef State,
- const LocationContext *LCtx) {
- return create<ObjCMethodCall>(E, State, LCtx);
- }
-
- CallEventRef<CXXConstructorCall>
- getCXXConstructorCall(const CXXConstructExpr *E, const MemRegion *Target,
- ProgramStateRef State, const LocationContext *LCtx) {
- return create<CXXConstructorCall>(E, Target, State, LCtx);
- }
-
- CallEventRef<CXXDestructorCall>
- getCXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger,
- const MemRegion *Target, bool IsBase,
- ProgramStateRef State, const LocationContext *LCtx) {
- return create<CXXDestructorCall>(DD, Trigger, Target, IsBase, State, LCtx);
- }
-
- CallEventRef<CXXAllocatorCall>
- getCXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef State,
- const LocationContext *LCtx) {
- return create<CXXAllocatorCall>(E, State, LCtx);
- }
-};
-
-
-template <typename T>
-CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const {
- assert(isa<T>(*this) && "Cloning to unrelated type");
- static_assert(sizeof(T) == sizeof(CallEvent),
- "Subclasses may not add fields");
-
- if (NewState == State)
- return cast<T>(this);
-
- CallEventManager &Mgr = State->getStateManager().getCallEventManager();
- T *Copy = static_cast<T *>(Mgr.allocate());
- cloneTo(Copy);
- assert(Copy->getKind() == this->getKind() && "Bad copy");
-
- Copy->State = NewState;
- return Copy;
-}
-
-inline void CallEvent::Release() const {
- assert(RefCount > 0 && "Reference count is already zero.");
- --RefCount;
-
- if (RefCount > 0)
- return;
-
- CallEventManager &Mgr = State->getStateManager().getCallEventManager();
- Mgr.reclaim(this);
-
- this->~CallEvent();
-}
-
-} // end namespace ento
-} // end namespace clang
-
-namespace llvm {
- // Support isa<>, cast<>, and dyn_cast<> for CallEventRef.
- template<class T> struct simplify_type< clang::ento::CallEventRef<T> > {
- typedef const T *SimpleType;
-
- static SimpleType
- getSimplifiedValue(clang::ento::CallEventRef<T> Val) {
- return Val.get();
- }
- };
-}
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
deleted file mode 100644
index d4f014d..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ /dev/null
@@ -1,349 +0,0 @@
-//== CheckerContext.h - Context info for path-sensitive checkers--*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines CheckerContext that provides contextual info for
-// path-sensitive checkers.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-
-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.
- ExplodedNode *Pred;
- /// The flag is true if the (state of the execution) has been modified
- /// by the checker using this context. For example, a new transition has been
- /// added or a bug report issued.
- bool Changed;
- /// The tagged location, which is used to generate all new nodes.
- const ProgramPoint Location;
- NodeBuilder &NB;
-
-public:
- /// If we are post visiting a call, this flag will be set if the
- /// call was inlined. In all other cases it will be false.
- const bool wasInlined;
-
- CheckerContext(NodeBuilder &builder,
- ExprEngine &eng,
- ExplodedNode *pred,
- const ProgramPoint &loc,
- bool wasInlined = false)
- : Eng(eng),
- Pred(pred),
- Changed(false),
- Location(loc),
- NB(builder),
- wasInlined(wasInlined) {
- assert(Pred->getState() &&
- "We should not call the checkers on an empty state.");
- }
-
- AnalysisManager &getAnalysisManager() {
- return Eng.getAnalysisManager();
- }
-
- ConstraintManager &getConstraintManager() {
- return Eng.getConstraintManager();
- }
-
- StoreManager &getStoreManager() {
- return Eng.getStoreManager();
- }
-
- /// \brief Returns the previous node in the exploded graph, which includes
- /// the state of the program before the checker ran. Note, checkers should
- /// not retain the node in their state since the nodes might get invalidated.
- ExplodedNode *getPredecessor() { return Pred; }
- const ProgramStateRef &getState() const { return Pred->getState(); }
-
- /// \brief Check if the checker changed the state of the execution; ex: added
- /// a new transition or a bug report.
- bool isDifferent() { return Changed; }
-
- /// \brief Returns the number of times the current block has been visited
- /// along the analyzed path.
- unsigned blockCount() const {
- return NB.getContext().blockCount();
- }
-
- ASTContext &getASTContext() {
- return Eng.getContext();
- }
-
- const LangOptions &getLangOpts() const {
- return Eng.getContext().getLangOpts();
- }
-
- const LocationContext *getLocationContext() const {
- return Pred->getLocationContext();
- }
-
- const StackFrameContext *getStackFrame() const {
- return Pred->getStackFrame();
- }
-
- /// Return true if the current LocationContext has no caller context.
- bool inTopFrame() const { return getLocationContext()->inTopFrame(); }
-
- BugReporter &getBugReporter() {
- return Eng.getBugReporter();
- }
-
- SourceManager &getSourceManager() {
- return getBugReporter().getSourceManager();
- }
-
- SValBuilder &getSValBuilder() {
- return Eng.getSValBuilder();
- }
-
- SymbolManager &getSymbolManager() {
- return getSValBuilder().getSymbolManager();
- }
-
- bool isObjCGCEnabled() const {
- return Eng.isObjCGCEnabled();
- }
-
- ProgramStateManager &getStateManager() {
- return Eng.getStateManager();
- }
-
- AnalysisDeclContext *getCurrentAnalysisDeclContext() const {
- return Pred->getLocationContext()->getAnalysisDeclContext();
- }
-
- /// \brief Get the blockID.
- unsigned getBlockID() const {
- return NB.getContext().getBlock()->getBlockID();
- }
-
- /// \brief If the given node corresponds to a PostStore program point,
- /// retrieve the location region as it was uttered in the code.
- ///
- /// This utility can be useful for generating extensive diagnostics, for
- /// example, for finding variables that the given symbol was assigned to.
- static const MemRegion *getLocationRegionIfPostStore(const ExplodedNode *N) {
- ProgramPoint L = N->getLocation();
- if (Optional<PostStore> PSL = L.getAs<PostStore>())
- return reinterpret_cast<const MemRegion*>(PSL->getLocationValue());
- return nullptr;
- }
-
- /// \brief Get the value of arbitrary expressions at this point in the path.
- SVal getSVal(const Stmt *S) const {
- return getState()->getSVal(S, getLocationContext());
- }
-
- /// \brief Generates a new transition in the program state graph
- /// (ExplodedGraph). Uses the default CheckerContext predecessor node.
- ///
- /// @param State The state of the generated node. If not specified, the state
- /// will not be changed, but the new node will have the checker's tag.
- /// @param Tag The tag is used to uniquely identify the creation site. If no
- /// tag is specified, a default tag, unique to the given checker,
- /// will be used. Tags are used to prevent states generated at
- /// different sites from caching out.
- ExplodedNode *addTransition(ProgramStateRef State = nullptr,
- const ProgramPointTag *Tag = nullptr) {
- return addTransitionImpl(State ? State : getState(), false, nullptr, Tag);
- }
-
- /// \brief Generates a new transition with the given predecessor.
- /// Allows checkers to generate a chain of nodes.
- ///
- /// @param State The state of the generated node.
- /// @param Pred The transition will be generated from the specified Pred node
- /// to the newly generated node.
- /// @param Tag The tag to uniquely identify the creation site.
- ExplodedNode *addTransition(ProgramStateRef State,
- ExplodedNode *Pred,
- const ProgramPointTag *Tag = nullptr) {
- return addTransitionImpl(State, false, Pred, Tag);
- }
-
- /// \brief Generate a sink node. Generating a sink stops exploration of the
- /// given path. To create a sink node for the purpose of reporting an error,
- /// checkers should use generateErrorNode() instead.
- ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
- const ProgramPointTag *Tag = nullptr) {
- return addTransitionImpl(State ? State : getState(), true, Pred, Tag);
- }
-
- /// \brief Generate a transition to a node that will be used to report
- /// an error. This node will be a sink. That is, it will stop exploration of
- /// the given path.
- ///
- /// @param State The state of the generated node.
- /// @param Tag The tag to uniquely identify the creation site. If null,
- /// the default tag for the checker will be used.
- ExplodedNode *generateErrorNode(ProgramStateRef State = nullptr,
- const ProgramPointTag *Tag = nullptr) {
- return generateSink(State, Pred,
- (Tag ? Tag : Location.getTag()));
- }
-
- /// \brief Generate a transition to a node that will be used to report
- /// an error. This node will not be a sink. That is, exploration will
- /// continue along this path.
- ///
- /// @param State The state of the generated node.
- /// @param Tag The tag to uniquely identify the creation site. If null,
- /// the default tag for the checker will be used.
- ExplodedNode *
- generateNonFatalErrorNode(ProgramStateRef State = nullptr,
- const ProgramPointTag *Tag = nullptr) {
- return addTransition(State, (Tag ? Tag : Location.getTag()));
- }
-
- /// \brief Emit the diagnostics report.
- void emitReport(std::unique_ptr<BugReport> R) {
- Changed = true;
- Eng.getBugReporter().emitReport(std::move(R));
- }
-
- /// \brief Get the declaration of the called function (path-sensitive).
- const FunctionDecl *getCalleeDecl(const CallExpr *CE) const;
-
- /// \brief Get the name of the called function (path-sensitive).
- StringRef getCalleeName(const FunctionDecl *FunDecl) const;
-
- /// \brief Get the identifier of the called function (path-sensitive).
- const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const {
- const FunctionDecl *FunDecl = getCalleeDecl(CE);
- if (FunDecl)
- return FunDecl->getIdentifier();
- else
- return nullptr;
- }
-
- /// \brief Get the name of the called function (path-sensitive).
- StringRef getCalleeName(const CallExpr *CE) const {
- const FunctionDecl *FunDecl = getCalleeDecl(CE);
- return getCalleeName(FunDecl);
- }
-
- /// \brief Returns true if the callee is an externally-visible function in the
- /// top-level namespace, such as \c malloc.
- ///
- /// If a name is provided, the function must additionally match the given
- /// name.
- ///
- /// Note that this deliberately excludes C++ library functions in the \c std
- /// namespace, but will include C library functions accessed through the
- /// \c std namespace. This also does not check if the function is declared
- /// as 'extern "C"', or if it uses C++ name mangling.
- static bool isCLibraryFunction(const FunctionDecl *FD,
- StringRef Name = StringRef());
-
- /// \brief Depending on wither the location corresponds to a macro, return
- /// either the macro name or the token spelling.
- ///
- /// This could be useful when checkers' logic depends on whether a function
- /// is called with a given macro argument. For example:
- /// s = socket(AF_INET,..)
- /// If AF_INET is a macro, the result should be treated as a source of taint.
- ///
- /// \sa clang::Lexer::getSpelling(), clang::Lexer::getImmediateMacroName().
- StringRef getMacroNameOrSpelling(SourceLocation &Loc);
-
-private:
- ExplodedNode *addTransitionImpl(ProgramStateRef State,
- bool MarkAsSink,
- ExplodedNode *P = nullptr,
- const ProgramPointTag *Tag = nullptr) {
- // The analyzer may stop exploring if it sees a state it has previously
- // visited ("cache out"). The early return here is a defensive check to
- // prevent accidental caching out by checker API clients. Unless there is a
- // tag or the client checker has requested that the generated node be
- // marked as a sink, we assume that a client requesting a transition to a
- // state that is the same as the predecessor state has made a mistake. We
- // return the predecessor rather than cache out.
- //
- // TODO: We could potentially change the return to an assertion to alert
- // clients to their mistake, but several checkers (including
- // DereferenceChecker, CallAndMessageChecker, and DynamicTypePropagation)
- // rely upon the defensive behavior and would need to be updated.
- if (!State || (State == Pred->getState() && !Tag && !MarkAsSink))
- return Pred;
-
- Changed = true;
- const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
- if (!P)
- P = Pred;
-
- ExplodedNode *node;
- if (MarkAsSink)
- node = NB.generateSink(LocalLoc, State, P);
- else
- node = NB.generateNode(LocalLoc, State, P);
- return node;
- }
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
deleted file mode 100644
index 8dda636..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//== CheckerHelpers.h - Helper functions for checkers ------------*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines CheckerVisitor.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H
-
-#include "clang/AST/Stmt.h"
-#include <tuple>
-
-namespace clang {
-
-class Expr;
-class VarDecl;
-
-namespace ento {
-
-bool containsMacro(const Stmt *S);
-bool containsEnum(const Stmt *S);
-bool containsStaticLocal(const Stmt *S);
-bool containsBuiltinOffsetOf(const Stmt *S);
-template <class T> bool containsStmt(const Stmt *S) {
- if (isa<T>(S))
- return true;
-
- for (const Stmt *Child : S->children())
- if (Child && containsStmt<T>(Child))
- return true;
-
- return false;
-}
-
-std::pair<const clang::VarDecl *, const clang::Expr *>
-parseAssignment(const Stmt *S);
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
deleted file mode 100644
index 9a858c2..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
+++ /dev/null
@@ -1,188 +0,0 @@
-//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defined the interface to manage constraints on symbolic values.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/Support/SaveAndRestore.h"
-
-namespace llvm {
-class APSInt;
-}
-
-namespace clang {
-namespace ento {
-
-class SubEngine;
-
-class ConditionTruthVal {
- Optional<bool> Val;
-public:
- /// Construct a ConditionTruthVal indicating the constraint is constrained
- /// to either true or false, depending on the boolean value provided.
- ConditionTruthVal(bool constraint) : Val(constraint) {}
-
- /// Construct a ConstraintVal indicating the constraint is underconstrained.
- ConditionTruthVal() {}
-
- /// Return true if the constraint is perfectly constrained to 'true'.
- bool isConstrainedTrue() const {
- return Val.hasValue() && Val.getValue();
- }
-
- /// Return true if the constraint is perfectly constrained to 'false'.
- bool isConstrainedFalse() const {
- return Val.hasValue() && !Val.getValue();
- }
-
- /// Return true if the constrained is perfectly constrained.
- bool isConstrained() const {
- return Val.hasValue();
- }
-
- /// Return true if the constrained is underconstrained and we do not know
- /// if the constraint is true of value.
- bool isUnderconstrained() const {
- return !Val.hasValue();
- }
-};
-
-class ConstraintManager {
-public:
- ConstraintManager() : NotifyAssumeClients(true) {}
-
- virtual ~ConstraintManager();
- virtual ProgramStateRef assume(ProgramStateRef state,
- DefinedSVal Cond,
- bool Assumption) = 0;
-
- typedef std::pair<ProgramStateRef, ProgramStateRef> ProgramStatePair;
-
- /// Returns a pair of states (StTrue, StFalse) where the given condition is
- /// assumed to be true or false, respectively.
- ProgramStatePair assumeDual(ProgramStateRef State, DefinedSVal Cond) {
- ProgramStateRef StTrue = assume(State, Cond, true);
-
- // If StTrue is infeasible, asserting the falseness of Cond is unnecessary
- // because the existing constraints already establish this.
- if (!StTrue) {
-#ifndef __OPTIMIZE__
- // This check is expensive and should be disabled even in Release+Asserts
- // builds.
- // FIXME: __OPTIMIZE__ is a GNU extension that Clang implements but MSVC
- // does not. Is there a good equivalent there?
- assert(assume(State, Cond, false) && "System is over constrained.");
-#endif
- return ProgramStatePair((ProgramStateRef)nullptr, State);
- }
-
- ProgramStateRef StFalse = assume(State, Cond, false);
- if (!StFalse) {
- // We are careful to return the original state, /not/ StTrue,
- // because we want to avoid having callers generate a new node
- // in the ExplodedGraph.
- return ProgramStatePair(State, (ProgramStateRef)nullptr);
- }
-
- return ProgramStatePair(StTrue, StFalse);
- }
-
- virtual ProgramStateRef assumeWithinInclusiveRange(ProgramStateRef State,
- NonLoc Value,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool InBound) = 0;
-
- virtual ProgramStatePair assumeWithinInclusiveRangeDual(
- ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
- const llvm::APSInt &To) {
- ProgramStateRef StInRange = assumeWithinInclusiveRange(State, Value, From,
- To, true);
-
- // If StTrue is infeasible, asserting the falseness of Cond is unnecessary
- // because the existing constraints already establish this.
- if (!StInRange)
- return ProgramStatePair((ProgramStateRef)nullptr, State);
-
- ProgramStateRef StOutOfRange = assumeWithinInclusiveRange(State, Value,
- From, To, false);
- if (!StOutOfRange) {
- // We are careful to return the original state, /not/ StTrue,
- // because we want to avoid having callers generate a new node
- // in the ExplodedGraph.
- return ProgramStatePair(State, (ProgramStateRef)nullptr);
- }
-
- return ProgramStatePair(StInRange, StOutOfRange);
- }
-
- /// \brief If a symbol is perfectly constrained to a constant, attempt
- /// to return the concrete value.
- ///
- /// Note that a ConstraintManager is not obligated to return a concretized
- /// value for a symbol, even if it is perfectly constrained.
- virtual const llvm::APSInt* getSymVal(ProgramStateRef state,
- SymbolRef sym) const {
- return nullptr;
- }
-
- virtual ProgramStateRef removeDeadBindings(ProgramStateRef state,
- SymbolReaper& SymReaper) = 0;
-
- virtual void print(ProgramStateRef state,
- raw_ostream &Out,
- const char* nl,
- const char *sep) = 0;
-
- virtual void EndPath(ProgramStateRef state) {}
-
- /// Convenience method to query the state to see if a symbol is null or
- /// not null, or if neither assumption can be made.
- ConditionTruthVal isNull(ProgramStateRef State, SymbolRef Sym) {
- SaveAndRestore<bool> DisableNotify(NotifyAssumeClients, false);
-
- return checkNull(State, Sym);
- }
-
-protected:
- /// A flag to indicate that clients should be notified of assumptions.
- /// By default this is the case, but sometimes this needs to be restricted
- /// to avoid infinite recursions within the ConstraintManager.
- ///
- /// Note that this flag allows the ConstraintManager to be re-entrant,
- /// but not thread-safe.
- bool NotifyAssumeClients;
-
- /// canReasonAbout - Not all ConstraintManagers can accurately reason about
- /// all SVal values. This method returns true if the ConstraintManager can
- /// reasonably handle a given SVal value. This is typically queried by
- /// ExprEngine to determine if the value should be replaced with a
- /// conjured symbolic value in order to recover some precision.
- virtual bool canReasonAbout(SVal X) const = 0;
-
- /// Returns whether or not a symbol is known to be null ("true"), known to be
- /// non-null ("false"), or may be either ("underconstrained").
- virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym);
-};
-
-std::unique_ptr<ConstraintManager>
-CreateRangeConstraintManager(ProgramStateManager &statemgr,
- SubEngine *subengine);
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
deleted file mode 100644
index d5822e2..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
+++ /dev/null
@@ -1,547 +0,0 @@
-//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a generic engine for intraprocedural, path-sensitive,
-// dataflow analysis via graph reachability.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H
-
-#include "clang/AST/Expr.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h"
-#include <memory>
-
-namespace clang {
-
-class ProgramPointTag;
-
-namespace ento {
-
-class NodeBuilder;
-
-//===----------------------------------------------------------------------===//
-/// CoreEngine - Implements the core logic of the graph-reachability
-/// analysis. It traverses the CFG and generates the ExplodedGraph.
-/// Program "states" are treated as opaque void pointers.
-/// The template class CoreEngine (which subclasses CoreEngine)
-/// provides the matching component to the engine that knows the actual types
-/// for states. Note that this engine only dispatches to transfer functions
-/// at the statement and block-level. The analyses themselves must implement
-/// any transfer function logic and the sub-expression level (if any).
-class CoreEngine {
- friend struct NodeBuilderContext;
- friend class NodeBuilder;
- friend class ExprEngine;
- friend class CommonNodeBuilder;
- friend class IndirectGotoNodeBuilder;
- friend class SwitchNodeBuilder;
- friend class EndOfFunctionNodeBuilder;
-public:
- typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
- BlocksExhausted;
-
- typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
- BlocksAborted;
-
-private:
-
- SubEngine& SubEng;
-
- /// G - The simulation graph. Each node is a (location,state) pair.
- mutable ExplodedGraph G;
-
- /// WList - A set of queued nodes that need to be processed by the
- /// worklist algorithm. It is up to the implementation of WList to decide
- /// the order that nodes are processed.
- std::unique_ptr<WorkList> WList;
-
- /// BCounterFactory - A factory object for created BlockCounter objects.
- /// These are used to record for key nodes in the ExplodedGraph the
- /// number of times different CFGBlocks have been visited along a path.
- BlockCounter::Factory BCounterFactory;
-
- /// The locations where we stopped doing work because we visited a location
- /// too many times.
- BlocksExhausted blocksExhausted;
-
- /// The locations where we stopped because the engine aborted analysis,
- /// usually because it could not reason about something.
- BlocksAborted blocksAborted;
-
- /// The information about functions shared by the whole translation unit.
- /// (This data is owned by AnalysisConsumer.)
- FunctionSummariesTy *FunctionSummaries;
-
- void generateNode(const ProgramPoint &Loc,
- ProgramStateRef State,
- ExplodedNode *Pred);
-
- void HandleBlockEdge(const BlockEdge &E, ExplodedNode *Pred);
- void HandleBlockEntrance(const BlockEntrance &E, ExplodedNode *Pred);
- void HandleBlockExit(const CFGBlock *B, ExplodedNode *Pred);
- void HandlePostStmt(const CFGBlock *B, unsigned StmtIdx, ExplodedNode *Pred);
-
- void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B,
- ExplodedNode *Pred);
- void HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
- const CFGBlock *B, ExplodedNode *Pred);
-
- /// Handle conditional logic for running static initializers.
- void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B,
- ExplodedNode *Pred);
-
-private:
- CoreEngine(const CoreEngine &) = delete;
- void operator=(const CoreEngine &) = delete;
-
- ExplodedNode *generateCallExitBeginNode(ExplodedNode *N);
-
-public:
- /// Construct a CoreEngine object to analyze the provided CFG.
- CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS)
- : SubEng(subengine), WList(WorkList::makeDFS()),
- BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {}
-
- /// getGraph - Returns the exploded graph.
- ExplodedGraph &getGraph() { return G; }
-
- /// ExecuteWorkList - Run the worklist algorithm for a maximum number of
- /// steps. Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkList(const LocationContext *L, unsigned Steps,
- ProgramStateRef InitState);
- /// Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkListWithInitialState(const LocationContext *L,
- unsigned Steps,
- ProgramStateRef InitState,
- ExplodedNodeSet &Dst);
-
- /// Dispatch the work list item based on the given location information.
- /// Use Pred parameter as the predecessor state.
- void dispatchWorkItem(ExplodedNode* Pred, ProgramPoint Loc,
- const WorkListUnit& WU);
-
- // Functions for external checking of whether we have unfinished work
- bool wasBlockAborted() const { return !blocksAborted.empty(); }
- bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
- bool hasWorkRemaining() const { return wasBlocksExhausted() ||
- WList->hasWork() ||
- wasBlockAborted(); }
-
- /// Inform the CoreEngine that a basic block was aborted because
- /// it could not be completely analyzed.
- void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
- blocksAborted.push_back(std::make_pair(block, node));
- }
-
- WorkList *getWorkList() const { return WList.get(); }
-
- BlocksExhausted::const_iterator blocks_exhausted_begin() const {
- return blocksExhausted.begin();
- }
- BlocksExhausted::const_iterator blocks_exhausted_end() const {
- return blocksExhausted.end();
- }
- BlocksAborted::const_iterator blocks_aborted_begin() const {
- return blocksAborted.begin();
- }
- BlocksAborted::const_iterator blocks_aborted_end() const {
- return blocksAborted.end();
- }
-
- /// \brief Enqueue the given set of nodes onto the work list.
- void enqueue(ExplodedNodeSet &Set);
-
- /// \brief Enqueue nodes that were created as a result of processing
- /// a statement onto the work list.
- void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx);
-
- /// \brief enqueue the nodes corresponding to the end of function onto the
- /// end of path / work list.
- void enqueueEndOfFunction(ExplodedNodeSet &Set);
-
- /// \brief Enqueue a single node created as a result of statement processing.
- void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx);
-};
-
-// TODO: Turn into a calss.
-struct NodeBuilderContext {
- const CoreEngine &Eng;
- const CFGBlock *Block;
- const LocationContext *LC;
- NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N)
- : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); }
-
- /// \brief Return the CFGBlock associated with this builder.
- const CFGBlock *getBlock() const { return Block; }
-
- /// \brief Returns the number of times the current basic block has been
- /// visited on the exploded graph path.
- unsigned blockCount() const {
- return Eng.WList->getBlockCounter().getNumVisited(
- LC->getCurrentStackFrame(),
- Block->getBlockID());
- }
-};
-
-/// \class NodeBuilder
-/// \brief This is the simplest builder which generates nodes in the
-/// ExplodedGraph.
-///
-/// The main benefit of the builder is that it automatically tracks the
-/// frontier nodes (or destination set). This is the set of nodes which should
-/// be propagated to the next step / builder. They are the nodes which have been
-/// added to the builder (either as the input node set or as the newly
-/// constructed nodes) but did not have any outgoing transitions added.
-class NodeBuilder {
- virtual void anchor();
-protected:
- const NodeBuilderContext &C;
-
- /// Specifies if the builder results have been finalized. For example, if it
- /// is set to false, autotransitions are yet to be generated.
- bool Finalized;
- bool HasGeneratedNodes;
- /// \brief The frontier set - a set of nodes which need to be propagated after
- /// the builder dies.
- ExplodedNodeSet &Frontier;
-
- /// Checkes if the results are ready.
- virtual bool checkResults() {
- if (!Finalized)
- return false;
- return true;
- }
-
- bool hasNoSinksInFrontier() {
- for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) {
- if ((*I)->isSink())
- return false;
- }
- return true;
- }
-
- /// Allow subclasses to finalize results before result_begin() is executed.
- virtual void finalizeResults() {}
-
- ExplodedNode *generateNodeImpl(const ProgramPoint &PP,
- ProgramStateRef State,
- ExplodedNode *Pred,
- bool MarkAsSink = false);
-
-public:
- NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &Ctx, bool F = true)
- : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
- Frontier.Add(SrcNode);
- }
-
- NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &Ctx, bool F = true)
- : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) {
- Frontier.insert(SrcSet);
- assert(hasNoSinksInFrontier());
- }
-
- virtual ~NodeBuilder() {}
-
- /// \brief Generates a node in the ExplodedGraph.
- ExplodedNode *generateNode(const ProgramPoint &PP,
- ProgramStateRef State,
- ExplodedNode *Pred) {
- return generateNodeImpl(PP, State, Pred, false);
- }
-
- /// \brief Generates a sink in the ExplodedGraph.
- ///
- /// When a node is marked as sink, the exploration from the node is stopped -
- /// the node becomes the last node on the path and certain kinds of bugs are
- /// suppressed.
- ExplodedNode *generateSink(const ProgramPoint &PP,
- ProgramStateRef State,
- ExplodedNode *Pred) {
- return generateNodeImpl(PP, State, Pred, true);
- }
-
- const ExplodedNodeSet &getResults() {
- finalizeResults();
- assert(checkResults());
- return Frontier;
- }
-
- typedef ExplodedNodeSet::iterator iterator;
- /// \brief Iterators through the results frontier.
- inline iterator begin() {
- finalizeResults();
- assert(checkResults());
- return Frontier.begin();
- }
- inline iterator end() {
- finalizeResults();
- return Frontier.end();
- }
-
- const NodeBuilderContext &getContext() { return C; }
- bool hasGeneratedNodes() { return HasGeneratedNodes; }
-
- void takeNodes(const ExplodedNodeSet &S) {
- for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I )
- Frontier.erase(*I);
- }
- void takeNodes(ExplodedNode *N) { Frontier.erase(N); }
- void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); }
- void addNodes(ExplodedNode *N) { Frontier.Add(N); }
-};
-
-/// \class NodeBuilderWithSinks
-/// \brief This node builder keeps track of the generated sink nodes.
-class NodeBuilderWithSinks: public NodeBuilder {
- void anchor() override;
-protected:
- SmallVector<ExplodedNode*, 2> sinksGenerated;
- ProgramPoint &Location;
-
-public:
- NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &Ctx, ProgramPoint &L)
- : NodeBuilder(Pred, DstSet, Ctx), Location(L) {}
-
- ExplodedNode *generateNode(ProgramStateRef State,
- ExplodedNode *Pred,
- const ProgramPointTag *Tag = nullptr) {
- const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
- return NodeBuilder::generateNode(LocalLoc, State, Pred);
- }
-
- ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred,
- const ProgramPointTag *Tag = nullptr) {
- const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location);
- ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred);
- if (N && N->isSink())
- sinksGenerated.push_back(N);
- return N;
- }
-
- const SmallVectorImpl<ExplodedNode*> &getSinks() const {
- return sinksGenerated;
- }
-};
-
-/// \class StmtNodeBuilder
-/// \brief This builder class is useful for generating nodes that resulted from
-/// visiting a statement. The main difference from its parent NodeBuilder is
-/// that it creates a statement specific ProgramPoint.
-class StmtNodeBuilder: public NodeBuilder {
- NodeBuilder *EnclosingBldr;
-public:
-
- /// \brief Constructs a StmtNodeBuilder. If the builder is going to process
- /// nodes currently owned by another builder(with larger scope), use
- /// Enclosing builder to transfer ownership.
- StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &Ctx,
- NodeBuilder *Enclosing = nullptr)
- : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) {
- if (EnclosingBldr)
- EnclosingBldr->takeNodes(SrcNode);
- }
-
- StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &Ctx,
- NodeBuilder *Enclosing = nullptr)
- : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) {
- if (EnclosingBldr)
- for (ExplodedNodeSet::iterator I = SrcSet.begin(),
- E = SrcSet.end(); I != E; ++I )
- EnclosingBldr->takeNodes(*I);
- }
-
- ~StmtNodeBuilder() override;
-
- using NodeBuilder::generateNode;
- using NodeBuilder::generateSink;
-
- ExplodedNode *generateNode(const Stmt *S,
- ExplodedNode *Pred,
- ProgramStateRef St,
- const ProgramPointTag *tag = nullptr,
- ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
- const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
- Pred->getLocationContext(), tag);
- return NodeBuilder::generateNode(L, St, Pred);
- }
-
- ExplodedNode *generateSink(const Stmt *S,
- ExplodedNode *Pred,
- ProgramStateRef St,
- const ProgramPointTag *tag = nullptr,
- ProgramPoint::Kind K = ProgramPoint::PostStmtKind){
- const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
- Pred->getLocationContext(), tag);
- return NodeBuilder::generateSink(L, St, Pred);
- }
-};
-
-/// \brief BranchNodeBuilder is responsible for constructing the nodes
-/// corresponding to the two branches of the if statement - true and false.
-class BranchNodeBuilder: public NodeBuilder {
- void anchor() override;
- const CFGBlock *DstT;
- const CFGBlock *DstF;
-
- bool InFeasibleTrue;
- bool InFeasibleFalse;
-
-public:
- BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &C,
- const CFGBlock *dstT, const CFGBlock *dstF)
- : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF),
- InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
- // The branch node builder does not generate autotransitions.
- // If there are no successors it means that both branches are infeasible.
- takeNodes(SrcNode);
- }
-
- BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet,
- const NodeBuilderContext &C,
- const CFGBlock *dstT, const CFGBlock *dstF)
- : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF),
- InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) {
- takeNodes(SrcSet);
- }
-
- ExplodedNode *generateNode(ProgramStateRef State, bool branch,
- ExplodedNode *Pred);
-
- const CFGBlock *getTargetBlock(bool branch) const {
- return branch ? DstT : DstF;
- }
-
- void markInfeasible(bool branch) {
- if (branch)
- InFeasibleTrue = true;
- else
- InFeasibleFalse = true;
- }
-
- bool isFeasible(bool branch) {
- return branch ? !InFeasibleTrue : !InFeasibleFalse;
- }
-};
-
-class IndirectGotoNodeBuilder {
- CoreEngine& Eng;
- const CFGBlock *Src;
- const CFGBlock &DispatchBlock;
- const Expr *E;
- ExplodedNode *Pred;
-
-public:
- IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
- const Expr *e, const CFGBlock *dispatch, CoreEngine* eng)
- : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {}
-
- class iterator {
- CFGBlock::const_succ_iterator I;
-
- friend class IndirectGotoNodeBuilder;
- iterator(CFGBlock::const_succ_iterator i) : I(i) {}
- public:
-
- iterator &operator++() { ++I; return *this; }
- bool operator!=(const iterator &X) const { return I != X.I; }
-
- const LabelDecl *getLabel() const {
- return cast<LabelStmt>((*I)->getLabel())->getDecl();
- }
-
- const CFGBlock *getBlock() const {
- return *I;
- }
- };
-
- iterator begin() { return iterator(DispatchBlock.succ_begin()); }
- iterator end() { return iterator(DispatchBlock.succ_end()); }
-
- ExplodedNode *generateNode(const iterator &I,
- ProgramStateRef State,
- bool isSink = false);
-
- const Expr *getTarget() const { return E; }
-
- ProgramStateRef getState() const { return Pred->State; }
-
- const LocationContext *getLocationContext() const {
- return Pred->getLocationContext();
- }
-};
-
-class SwitchNodeBuilder {
- CoreEngine& Eng;
- const CFGBlock *Src;
- const Expr *Condition;
- ExplodedNode *Pred;
-
-public:
- SwitchNodeBuilder(ExplodedNode *pred, const CFGBlock *src,
- const Expr *condition, CoreEngine* eng)
- : Eng(*eng), Src(src), Condition(condition), Pred(pred) {}
-
- class iterator {
- CFGBlock::const_succ_reverse_iterator I;
-
- friend class SwitchNodeBuilder;
- iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {}
-
- public:
- iterator &operator++() { ++I; return *this; }
- bool operator!=(const iterator &X) const { return I != X.I; }
- bool operator==(const iterator &X) const { return I == X.I; }
-
- const CaseStmt *getCase() const {
- return cast<CaseStmt>((*I)->getLabel());
- }
-
- const CFGBlock *getBlock() const {
- return *I;
- }
- };
-
- iterator begin() { return iterator(Src->succ_rbegin()+1); }
- iterator end() { return iterator(Src->succ_rend()); }
-
- const SwitchStmt *getSwitch() const {
- return cast<SwitchStmt>(Src->getTerminator());
- }
-
- ExplodedNode *generateCaseStmtNode(const iterator &I,
- ProgramStateRef State);
-
- ExplodedNode *generateDefaultCaseNode(ProgramStateRef State,
- bool isSink = false);
-
- const Expr *getCondition() const { return Condition; }
-
- ProgramStateRef getState() const { return Pred->State; }
-
- const LocationContext *getLocationContext() const {
- return Pred->getLocationContext();
- }
-};
-
-} // end ento namespace
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
deleted file mode 100644
index e13c641..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//== DynamicTypeInfo.h - Runtime type information ----------------*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H
-
-#include "clang/AST/Type.h"
-
-namespace clang {
-namespace ento {
-
-/// \brief Stores the currently inferred strictest bound on the runtime type
-/// of a region in a given state along the analysis path.
-class DynamicTypeInfo {
-private:
- QualType T;
- bool CanBeASubClass;
-
-public:
-
- DynamicTypeInfo() : T(QualType()) {}
- DynamicTypeInfo(QualType WithType, bool CanBeSub = true)
- : T(WithType), CanBeASubClass(CanBeSub) {}
-
- /// \brief Return false if no dynamic type info is available.
- bool isValid() const { return !T.isNull(); }
-
- /// \brief Returns the currently inferred upper bound on the runtime type.
- QualType getType() const { return T; }
-
- /// \brief Returns false if the type information is precise (the type T is
- /// the only type in the lattice), true otherwise.
- bool canBeASubClass() const { return CanBeASubClass; }
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- ID.Add(T);
- ID.AddInteger((unsigned)CanBeASubClass);
- }
- bool operator==(const DynamicTypeInfo &X) const {
- return T == X.T && CanBeASubClass == X.CanBeASubClass;
- }
-};
-
-} // end ento
-} // end clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
deleted file mode 100644
index 555191d..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides APIs for tracking dynamic type information.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "llvm/ADT/ImmutableMap.h"
-
-namespace clang {
-namespace ento {
-
-/// The GDM component containing the dynamic type info. This is a map from a
-/// symbol to its most likely type.
-struct DynamicTypeMap {};
-typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>
- DynamicTypeMapImpl;
-template <>
-struct ProgramStateTrait<DynamicTypeMap>
- : public ProgramStatePartialTrait<DynamicTypeMapImpl> {
- static void *GDMIndex() {
- static int index = 0;
- return &index;
- }
-};
-
-/// \brief Get dynamic type information for a region.
-DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg);
-
-/// \brief Set dynamic type information of the region; return the new state.
-ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg,
- DynamicTypeInfo NewTy);
-
-/// \brief Set dynamic type information of the region; return the new state.
-inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State,
- const MemRegion *Reg, QualType NewTy,
- bool CanBeSubClassed = true) {
- return setDynamicTypeInfo(State, Reg,
- DynamicTypeInfo(NewTy, CanBeSubClassed));
-}
-
-} // ento
-} // clang
-
-#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
deleted file mode 100644
index cc3779d..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ /dev/null
@@ -1,127 +0,0 @@
-//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defined the Environment and EnvironmentManager classes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H
-
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/ADT/ImmutableMap.h"
-
-namespace clang {
-
-class LiveVariables;
-
-namespace ento {
-
-class EnvironmentManager;
-class SValBuilder;
-
-/// An entry in the environment consists of a Stmt and an LocationContext.
-/// This allows the environment to manage context-sensitive bindings,
-/// which is essentially for modeling recursive function analysis, among
-/// other things.
-class EnvironmentEntry : public std::pair<const Stmt*,
- const StackFrameContext *> {
-public:
- EnvironmentEntry(const Stmt *s, const LocationContext *L);
-
- const Stmt *getStmt() const { return first; }
- const LocationContext *getLocationContext() const { return second; }
-
- /// Profile an EnvironmentEntry for inclusion in a FoldingSet.
- static void Profile(llvm::FoldingSetNodeID &ID,
- const EnvironmentEntry &E) {
- ID.AddPointer(E.getStmt());
- ID.AddPointer(E.getLocationContext());
- }
-
- void Profile(llvm::FoldingSetNodeID &ID) const {
- Profile(ID, *this);
- }
-};
-
-/// An immutable map from EnvironemntEntries to SVals.
-class Environment {
-private:
- friend class EnvironmentManager;
-
- // Type definitions.
- typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy;
-
- // Data.
- BindingsTy ExprBindings;
-
- Environment(BindingsTy eb)
- : ExprBindings(eb) {}
-
- SVal lookupExpr(const EnvironmentEntry &E) const;
-
-public:
- typedef BindingsTy::iterator iterator;
- iterator begin() const { return ExprBindings.begin(); }
- iterator end() const { return ExprBindings.end(); }
-
- /// Fetches the current binding of the expression in the
- /// Environment.
- SVal getSVal(const EnvironmentEntry &E, SValBuilder &svalBuilder) const;
-
- /// Profile - Profile the contents of an Environment object for use
- /// in a FoldingSet.
- static void Profile(llvm::FoldingSetNodeID& ID, const Environment* env) {
- env->ExprBindings.Profile(ID);
- }
-
- /// Profile - Used to profile the contents of this object for inclusion
- /// in a FoldingSet.
- void Profile(llvm::FoldingSetNodeID& ID) const {
- Profile(ID, this);
- }
-
- bool operator==(const Environment& RHS) const {
- return ExprBindings == RHS.ExprBindings;
- }
-
- void print(raw_ostream &Out, const char *NL, const char *Sep) const;
-
-private:
- void printAux(raw_ostream &Out, bool printLocations,
- const char *NL, const char *Sep) const;
-};
-
-class EnvironmentManager {
-private:
- typedef Environment::BindingsTy::Factory FactoryTy;
- FactoryTy F;
-
-public:
- EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {}
-
- Environment getInitialEnvironment() {
- return Environment(F.getEmptyMap());
- }
-
- /// Bind a symbolic value to the given environment entry.
- Environment bindExpr(Environment Env, const EnvironmentEntry &E, SVal V,
- bool Invalidate);
-
- Environment removeDeadBindings(Environment Env,
- SymbolReaper &SymReaper,
- ProgramStateRef state);
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
deleted file mode 100644
index cfb1b92..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h
+++ /dev/null
@@ -1,497 +0,0 @@
-//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the template classes ExplodedNode and ExplodedGraph,
-// which represent a path-sensitive, intra-procedural "exploded graph."
-// See "Precise interprocedural dataflow analysis via graph reachability"
-// by Reps, Horwitz, and Sagiv
-// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an
-// exploded graph.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H
-
-#include "clang/AST/Decl.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/Analysis/Support/BumpVector.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "llvm/ADT/DepthFirstIterator.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/GraphTraits.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Casting.h"
-#include <memory>
-#include <vector>
-
-namespace clang {
-
-class CFG;
-
-namespace ento {
-
-class ExplodedGraph;
-
-//===----------------------------------------------------------------------===//
-// ExplodedGraph "implementation" classes. These classes are not typed to
-// contain a specific kind of state. Typed-specialized versions are defined
-// on top of these classes.
-//===----------------------------------------------------------------------===//
-
-// ExplodedNode is not constified all over the engine because we need to add
-// successors to it at any time after creating it.
-
-class ExplodedNode : public llvm::FoldingSetNode {
- friend class ExplodedGraph;
- friend class CoreEngine;
- friend class NodeBuilder;
- friend class BranchNodeBuilder;
- friend class IndirectGotoNodeBuilder;
- friend class SwitchNodeBuilder;
- friend class EndOfFunctionNodeBuilder;
-
- /// Efficiently stores a list of ExplodedNodes, or an optional flag.
- ///
- /// NodeGroup provides opaque storage for a list of ExplodedNodes, optimizing
- /// for the case when there is only one node in the group. This is a fairly
- /// common case in an ExplodedGraph, where most nodes have only one
- /// predecessor and many have only one successor. It can also be used to
- /// store a flag rather than a node list, which ExplodedNode uses to mark
- /// whether a node is a sink. If the flag is set, the group is implicitly
- /// empty and no nodes may be added.
- class NodeGroup {
- // Conceptually a discriminated union. If the low bit is set, the node is
- // a sink. If the low bit is not set, the pointer refers to the storage
- // for the nodes in the group.
- // This is not a PointerIntPair in order to keep the storage type opaque.
- uintptr_t P;
-
- public:
- NodeGroup(bool Flag = false) : P(Flag) {
- assert(getFlag() == Flag);
- }
-
- ExplodedNode * const *begin() const;
-
- ExplodedNode * const *end() const;
-
- unsigned size() const;
-
- bool empty() const { return P == 0 || getFlag() != 0; }
-
- /// Adds a node to the list.
- ///
- /// The group must not have been created with its flag set.
- void addNode(ExplodedNode *N, ExplodedGraph &G);
-
- /// Replaces the single node in this group with a new node.
- ///
- /// Note that this should only be used when you know the group was not
- /// created with its flag set, and that the group is empty or contains
- /// only a single node.
- void replaceNode(ExplodedNode *node);
-
- /// Returns whether this group was created with its flag set.
- bool getFlag() const {
- return (P & 1);
- }
- };
-
- /// Location - The program location (within a function body) associated
- /// with this node.
- const ProgramPoint Location;
-
- /// State - The state associated with this node.
- ProgramStateRef State;
-
- /// Preds - The predecessors of this node.
- NodeGroup Preds;
-
- /// Succs - The successors of this node.
- NodeGroup Succs;
-
-public:
-
- explicit ExplodedNode(const ProgramPoint &loc, ProgramStateRef state,
- bool IsSink)
- : Location(loc), State(state), Succs(IsSink) {
- assert(isSink() == IsSink);
- }
-
- /// getLocation - Returns the edge associated with the given node.
- ProgramPoint getLocation() const { return Location; }
-
- const LocationContext *getLocationContext() const {
- return getLocation().getLocationContext();
- }
-
- const StackFrameContext *getStackFrame() const {
- return getLocationContext()->getCurrentStackFrame();
- }
-
- const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); }
-
- CFG &getCFG() const { return *getLocationContext()->getCFG(); }
-
- ParentMap &getParentMap() const {return getLocationContext()->getParentMap();}
-
- template <typename T>
- T &getAnalysis() const {
- return *getLocationContext()->getAnalysis<T>();
- }
-
- const ProgramStateRef &getState() const { return State; }
-
- template <typename T>
- Optional<T> getLocationAs() const LLVM_LVALUE_FUNCTION {
- return Location.getAs<T>();
- }
-
- static void Profile(llvm::FoldingSetNodeID &ID,
- const ProgramPoint &Loc,
- const ProgramStateRef &state,
- bool IsSink) {
- ID.Add(Loc);
- ID.AddPointer(state.get());
- ID.AddBoolean(IsSink);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- // We avoid copy constructors by not using accessors.
- Profile(ID, Location, State, isSink());
- }
-
- /// addPredeccessor - Adds a predecessor to the current node, and
- /// in tandem add this node as a successor of the other node.
- void addPredecessor(ExplodedNode *V, ExplodedGraph &G);
-
- unsigned succ_size() const { return Succs.size(); }
- unsigned pred_size() const { return Preds.size(); }
- bool succ_empty() const { return Succs.empty(); }
- bool pred_empty() const { return Preds.empty(); }
-
- bool isSink() const { return Succs.getFlag(); }
-
- bool hasSinglePred() const {
- return (pred_size() == 1);
- }
-
- ExplodedNode *getFirstPred() {
- return pred_empty() ? nullptr : *(pred_begin());
- }
-
- const ExplodedNode *getFirstPred() const {
- return const_cast<ExplodedNode*>(this)->getFirstPred();
- }
-
- const ExplodedNode *getFirstSucc() const {
- return succ_empty() ? nullptr : *(succ_begin());
- }
-
- // Iterators over successor and predecessor vertices.
- typedef ExplodedNode* const * succ_iterator;
- typedef const ExplodedNode* const * const_succ_iterator;
- typedef ExplodedNode* const * pred_iterator;
- typedef const ExplodedNode* const * const_pred_iterator;
-
- pred_iterator pred_begin() { return Preds.begin(); }
- pred_iterator pred_end() { return Preds.end(); }
-
- const_pred_iterator pred_begin() const {
- return const_cast<ExplodedNode*>(this)->pred_begin();
- }
- const_pred_iterator pred_end() const {
- return const_cast<ExplodedNode*>(this)->pred_end();
- }
-
- succ_iterator succ_begin() { return Succs.begin(); }
- succ_iterator succ_end() { return Succs.end(); }
-
- const_succ_iterator succ_begin() const {
- return const_cast<ExplodedNode*>(this)->succ_begin();
- }
- const_succ_iterator succ_end() const {
- return const_cast<ExplodedNode*>(this)->succ_end();
- }
-
- // For debugging.
-
-public:
-
- class Auditor {
- public:
- virtual ~Auditor();
- virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0;
- };
-
- static void SetAuditor(Auditor* A);
-
-private:
- void replaceSuccessor(ExplodedNode *node) { Succs.replaceNode(node); }
- void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); }
-};
-
-typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>
- InterExplodedGraphMap;
-
-class ExplodedGraph {
-protected:
- friend class CoreEngine;
-
- // Type definitions.
- typedef std::vector<ExplodedNode *> NodeVector;
-
- /// The roots of the simulation graph. Usually there will be only
- /// one, but clients are free to establish multiple subgraphs within a single
- /// SimulGraph. Moreover, these subgraphs can often merge when paths from
- /// different roots reach the same state at the same program location.
- NodeVector Roots;
-
- /// The nodes in the simulation graph which have been
- /// specially marked as the endpoint of an abstract simulation path.
- NodeVector EndNodes;
-
- /// Nodes - The nodes in the graph.
- llvm::FoldingSet<ExplodedNode> Nodes;
-
- /// BVC - Allocator and context for allocating nodes and their predecessor
- /// and successor groups.
- BumpVectorContext BVC;
-
- /// NumNodes - The number of nodes in the graph.
- unsigned NumNodes;
-
- /// A list of recently allocated nodes that can potentially be recycled.
- NodeVector ChangedNodes;
-
- /// A list of nodes that can be reused.
- NodeVector FreeNodes;
-
- /// Determines how often nodes are reclaimed.
- ///
- /// If this is 0, nodes will never be reclaimed.
- unsigned ReclaimNodeInterval;
-
- /// Counter to determine when to reclaim nodes.
- unsigned ReclaimCounter;
-
-public:
-
- /// \brief Retrieve the node associated with a (Location,State) pair,
- /// where the 'Location' is a ProgramPoint in the CFG. If no node for
- /// this pair exists, it is created. IsNew is set to true if
- /// the node was freshly created.
- ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State,
- bool IsSink = false,
- bool* IsNew = nullptr);
-
- std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const {
- return llvm::make_unique<ExplodedGraph>();
- }
-
- /// addRoot - Add an untyped node to the set of roots.
- ExplodedNode *addRoot(ExplodedNode *V) {
- Roots.push_back(V);
- return V;
- }
-
- /// addEndOfPath - Add an untyped node to the set of EOP nodes.
- ExplodedNode *addEndOfPath(ExplodedNode *V) {
- EndNodes.push_back(V);
- return V;
- }
-
- ExplodedGraph();
-
- ~ExplodedGraph();
-
- unsigned num_roots() const { return Roots.size(); }
- unsigned num_eops() const { return EndNodes.size(); }
-
- bool empty() const { return NumNodes == 0; }
- unsigned size() const { return NumNodes; }
-
- // Iterators.
- typedef ExplodedNode NodeTy;
- typedef llvm::FoldingSet<ExplodedNode> AllNodesTy;
- typedef NodeVector::iterator roots_iterator;
- typedef NodeVector::const_iterator const_roots_iterator;
- typedef NodeVector::iterator eop_iterator;
- typedef NodeVector::const_iterator const_eop_iterator;
- typedef AllNodesTy::iterator node_iterator;
- typedef AllNodesTy::const_iterator const_node_iterator;
-
- node_iterator nodes_begin() { return Nodes.begin(); }
-
- node_iterator nodes_end() { return Nodes.end(); }
-
- const_node_iterator nodes_begin() const { return Nodes.begin(); }
-
- const_node_iterator nodes_end() const { return Nodes.end(); }
-
- roots_iterator roots_begin() { return Roots.begin(); }
-
- roots_iterator roots_end() { return Roots.end(); }
-
- const_roots_iterator roots_begin() const { return Roots.begin(); }
-
- const_roots_iterator roots_end() const { return Roots.end(); }
-
- eop_iterator eop_begin() { return EndNodes.begin(); }
-
- eop_iterator eop_end() { return EndNodes.end(); }
-
- const_eop_iterator eop_begin() const { return EndNodes.begin(); }
-
- const_eop_iterator eop_end() const { return EndNodes.end(); }
-
- llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); }
- BumpVectorContext &getNodeAllocator() { return BVC; }
-
- typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap;
-
- /// Creates a trimmed version of the graph that only contains paths leading
- /// to the given nodes.
- ///
- /// \param Nodes The nodes which must appear in the final graph. Presumably
- /// these are end-of-path nodes (i.e. they have no successors).
- /// \param[out] ForwardMap A optional map from nodes in this graph to nodes in
- /// the returned graph.
- /// \param[out] InverseMap An optional map from nodes in the returned graph to
- /// nodes in this graph.
- /// \returns The trimmed graph
- std::unique_ptr<ExplodedGraph>
- trim(ArrayRef<const NodeTy *> Nodes,
- InterExplodedGraphMap *ForwardMap = nullptr,
- InterExplodedGraphMap *InverseMap = nullptr) const;
-
- /// Enable tracking of recently allocated nodes for potential reclamation
- /// when calling reclaimRecentlyAllocatedNodes().
- void enableNodeReclamation(unsigned Interval) {
- ReclaimCounter = ReclaimNodeInterval = Interval;
- }
-
- /// Reclaim "uninteresting" nodes created since the last time this method
- /// was called.
- void reclaimRecentlyAllocatedNodes();
-
- /// \brief Returns true if nodes for the given expression kind are always
- /// kept around.
- static bool isInterestingLValueExpr(const Expr *Ex);
-
-private:
- bool shouldCollect(const ExplodedNode *node);
- void collectNode(ExplodedNode *node);
-};
-
-class ExplodedNodeSet {
- typedef llvm::SmallPtrSet<ExplodedNode*,5> ImplTy;
- ImplTy Impl;
-
-public:
- ExplodedNodeSet(ExplodedNode *N) {
- assert (N && !static_cast<ExplodedNode*>(N)->isSink());
- Impl.insert(N);
- }
-
- ExplodedNodeSet() {}
-
- inline void Add(ExplodedNode *N) {
- if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N);
- }
-
- typedef ImplTy::iterator iterator;
- typedef ImplTy::const_iterator const_iterator;
-
- unsigned size() const { return Impl.size(); }
- bool empty() const { return Impl.empty(); }
- bool erase(ExplodedNode *N) { return Impl.erase(N); }
-
- void clear() { Impl.clear(); }
- void insert(const ExplodedNodeSet &S) {
- assert(&S != this);
- if (empty())
- Impl = S.Impl;
- else
- Impl.insert(S.begin(), S.end());
- }
-
- inline iterator begin() { return Impl.begin(); }
- inline iterator end() { return Impl.end(); }
-
- inline const_iterator begin() const { return Impl.begin(); }
- inline const_iterator end() const { return Impl.end(); }
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-// GraphTraits
-
-namespace llvm {
- template<> struct GraphTraits<clang::ento::ExplodedNode*> {
- typedef clang::ento::ExplodedNode NodeType;
- typedef NodeType::succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeType*> nodes_iterator;
-
- static inline NodeType* getEntryNode(NodeType* N) {
- return N;
- }
-
- static inline ChildIteratorType child_begin(NodeType* N) {
- return N->succ_begin();
- }
-
- static inline ChildIteratorType child_end(NodeType* N) {
- return N->succ_end();
- }
-
- static inline nodes_iterator nodes_begin(NodeType* N) {
- return df_begin(N);
- }
-
- static inline nodes_iterator nodes_end(NodeType* N) {
- return df_end(N);
- }
- };
-
- template<> struct GraphTraits<const clang::ento::ExplodedNode*> {
- typedef const clang::ento::ExplodedNode NodeType;
- typedef NodeType::const_succ_iterator ChildIteratorType;
- typedef llvm::df_iterator<NodeType*> nodes_iterator;
-
- static inline NodeType* getEntryNode(NodeType* N) {
- return N;
- }
-
- static inline ChildIteratorType child_begin(NodeType* N) {
- return N->succ_begin();
- }
-
- static inline ChildIteratorType child_end(NodeType* N) {
- return N->succ_end();
- }
-
- static inline nodes_iterator nodes_begin(NodeType* N) {
- return df_begin(N);
- }
-
- static inline nodes_iterator nodes_end(NodeType* N) {
- return df_end(N);
- }
- };
-
-} // end llvm namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
deleted file mode 100644
index 99083c9..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ /dev/null
@@ -1,646 +0,0 @@
-//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a meta-engine for path-sensitive dataflow analysis that
-// is built on CoreEngine, but provides the boilerplate to execute transfer
-// functions and build the ExplodedGraph at the expression level.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H
-
-#include "clang/AST/Expr.h"
-#include "clang/AST/Type.h"
-#include "clang/Analysis/DomainSpecific/ObjCNoReturn.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h"
-
-namespace clang {
-
-class AnalysisDeclContextManager;
-class CXXCatchStmt;
-class CXXConstructExpr;
-class CXXDeleteExpr;
-class CXXNewExpr;
-class CXXTemporaryObjectExpr;
-class CXXThisExpr;
-class MaterializeTemporaryExpr;
-class ObjCAtSynchronizedStmt;
-class ObjCForCollectionStmt;
-
-namespace ento {
-
-class AnalysisManager;
-class CallEvent;
-class CXXConstructorCall;
-
-class ExprEngine : public SubEngine {
-public:
- /// The modes of inlining, which override the default analysis-wide settings.
- enum InliningModes {
- /// Follow the default settings for inlining callees.
- Inline_Regular = 0,
- /// Do minimal inlining of callees.
- Inline_Minimal = 0x1
- };
-
-private:
- AnalysisManager &AMgr;
-
- AnalysisDeclContextManager &AnalysisDeclContexts;
-
- CoreEngine Engine;
-
- /// G - the simulation graph.
- ExplodedGraph& G;
-
- /// StateMgr - Object that manages the data for all created states.
- ProgramStateManager StateMgr;
-
- /// SymMgr - Object that manages the symbol information.
- SymbolManager& SymMgr;
-
- /// svalBuilder - SValBuilder object that creates SVals from expressions.
- SValBuilder &svalBuilder;
-
- unsigned int currStmtIdx;
- const NodeBuilderContext *currBldrCtx;
-
- /// Helper object to determine if an Objective-C message expression
- /// implicitly never returns.
- ObjCNoReturn ObjCNoRet;
-
- /// Whether or not GC is enabled in this analysis.
- bool ObjCGCEnabled;
-
- /// The BugReporter associated with this engine. It is important that
- /// this object be placed at the very end of member variables so that its
- /// destructor is called before the rest of the ExprEngine is destroyed.
- GRBugReporter BR;
-
- /// The functions which have been analyzed through inlining. This is owned by
- /// AnalysisConsumer. It can be null.
- SetOfConstDecls *VisitedCallees;
-
- /// The flag, which specifies the mode of inlining for the engine.
- InliningModes HowToInline;
-
-public:
- ExprEngine(AnalysisManager &mgr, bool gcEnabled,
- SetOfConstDecls *VisitedCalleesIn,
- FunctionSummariesTy *FS,
- InliningModes HowToInlineIn);
-
- ~ExprEngine() override;
-
- /// Returns true if there is still simulation state on the worklist.
- bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) {
- return Engine.ExecuteWorkList(L, Steps, nullptr);
- }
-
- /// Execute the work list with an initial state. Nodes that reaches the exit
- /// of the function are added into the Dst set, which represent the exit
- /// state of the function call. Returns true if there is still simulation
- /// state on the worklist.
- bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps,
- ProgramStateRef InitState,
- ExplodedNodeSet &Dst) {
- return Engine.ExecuteWorkListWithInitialState(L, Steps, InitState, Dst);
- }
-
- /// getContext - Return the ASTContext associated with this analysis.
- ASTContext &getContext() const { return AMgr.getASTContext(); }
-
- AnalysisManager &getAnalysisManager() override { return AMgr; }
-
- CheckerManager &getCheckerManager() const {
- return *AMgr.getCheckerManager();
- }
-
- SValBuilder &getSValBuilder() { return svalBuilder; }
-
- BugReporter& getBugReporter() { return BR; }
-
- const NodeBuilderContext &getBuilderContext() {
- assert(currBldrCtx);
- return *currBldrCtx;
- }
-
- bool isObjCGCEnabled() { return ObjCGCEnabled; }
-
- const Stmt *getStmt() const;
-
- void GenerateAutoTransition(ExplodedNode *N);
- void enqueueEndOfPath(ExplodedNodeSet &S);
- void GenerateCallExitNode(ExplodedNode *N);
-
- /// Visualize the ExplodedGraph created by executing the simulation.
- void ViewGraph(bool trim = false);
-
- /// Visualize a trimmed ExplodedGraph that only contains paths to the given
- /// nodes.
- void ViewGraph(ArrayRef<const ExplodedNode*> Nodes);
-
- /// getInitialState - Return the initial state used for the root vertex
- /// in the ExplodedGraph.
- ProgramStateRef getInitialState(const LocationContext *InitLoc) override;
-
- ExplodedGraph& getGraph() { return G; }
- const ExplodedGraph& getGraph() const { return G; }
-
- /// \brief Run the analyzer's garbage collection - remove dead symbols and
- /// bindings from the state.
- ///
- /// Checkers can participate in this process with two callbacks:
- /// \c checkLiveSymbols and \c checkDeadSymbols. See the CheckerDocumentation
- /// class for more information.
- ///
- /// \param Node The predecessor node, from which the processing should start.
- /// \param Out The returned set of output nodes.
- /// \param ReferenceStmt The statement which is about to be processed.
- /// Everything needed for this statement should be considered live.
- /// A null statement means that everything in child LocationContexts
- /// is dead.
- /// \param LC The location context of the \p ReferenceStmt. A null location
- /// context means that we have reached the end of analysis and that
- /// all statements and local variables should be considered dead.
- /// \param DiagnosticStmt Used as a location for any warnings that should
- /// occur while removing the dead (e.g. leaks). By default, the
- /// \p ReferenceStmt is used.
- /// \param K Denotes whether this is a pre- or post-statement purge. This
- /// must only be ProgramPoint::PostStmtPurgeDeadSymbolsKind if an
- /// entire location context is being cleared, in which case the
- /// \p ReferenceStmt must either be a ReturnStmt or \c NULL. Otherwise,
- /// it must be ProgramPoint::PreStmtPurgeDeadSymbolsKind (the default)
- /// and \p ReferenceStmt must be valid (non-null).
- void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out,
- const Stmt *ReferenceStmt, const LocationContext *LC,
- const Stmt *DiagnosticStmt = nullptr,
- ProgramPoint::Kind K = ProgramPoint::PreStmtPurgeDeadSymbolsKind);
-
- /// processCFGElement - Called by CoreEngine. Used to generate new successor
- /// nodes by processing the 'effects' of a CFG element.
- void processCFGElement(const CFGElement E, ExplodedNode *Pred,
- unsigned StmtIdx, NodeBuilderContext *Ctx) override;
-
- void ProcessStmt(const CFGStmt S, ExplodedNode *Pred);
-
- void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
-
- void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
-
- void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred);
-
- void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void ProcessDeleteDtor(const CFGDeleteDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void ProcessBaseDtor(const CFGBaseDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void ProcessMemberDtor(const CFGMemberDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
- void ProcessTemporaryDtor(const CFGTemporaryDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// Called by CoreEngine when processing the entrance of a CFGBlock.
- void processCFGBlockEntrance(const BlockEdge &L,
- NodeBuilderWithSinks &nodeBuilder,
- ExplodedNode *Pred) override;
-
- /// ProcessBranch - Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a branch condition.
- void processBranch(const Stmt *Condition, const Stmt *Term,
- NodeBuilderContext& BuilderCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) override;
-
- /// Called by CoreEngine.
- /// Used to generate successor nodes for temporary destructors depending
- /// on whether the corresponding constructor was visited.
- void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
- NodeBuilderContext &BldCtx,
- ExplodedNode *Pred, ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) override;
-
- /// Called by CoreEngine. Used to processing branching behavior
- /// at static initalizers.
- void processStaticInitializer(const DeclStmt *DS,
- NodeBuilderContext& BuilderCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) override;
-
- /// processIndirectGoto - Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a computed goto jump.
- void processIndirectGoto(IndirectGotoNodeBuilder& builder) override;
-
- /// ProcessSwitch - Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a switch statement.
- void processSwitch(SwitchNodeBuilder& builder) override;
-
- /// Called by CoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
- void processEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred) override;
-
- /// Remove dead bindings/symbols before exiting a function.
- void removeDeadOnEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// Generate the entry node of the callee.
- void processCallEnter(CallEnter CE, ExplodedNode *Pred) override;
-
- /// Generate the sequence of nodes that simulate the call exit and the post
- /// visit for CallExpr.
- void processCallExit(ExplodedNode *Pred) override;
-
- /// Called by CoreEngine when the analysis worklist has terminated.
- void processEndWorklist(bool hasWorkRemaining) override;
-
- /// evalAssume - Callback function invoked by the ConstraintManager when
- /// making assumptions about state values.
- ProgramStateRef processAssume(ProgramStateRef state, SVal cond,
- bool assumption) override;
-
- /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
- /// region change should trigger a processRegionChanges update.
- bool wantsRegionChangeUpdate(ProgramStateRef state) override;
-
- /// processRegionChanges - Called by ProgramStateManager whenever a change is made
- /// to the store. Used to update checkers that track region values.
- ProgramStateRef
- processRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call) override;
-
- /// printState - Called by ProgramStateManager to print checker-specific data.
- void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) override;
-
- ProgramStateManager& getStateManager() override { return StateMgr; }
-
- StoreManager& getStoreManager() { return StateMgr.getStoreManager(); }
-
- ConstraintManager& getConstraintManager() {
- return StateMgr.getConstraintManager();
- }
-
- // FIXME: Remove when we migrate over to just using SValBuilder.
- BasicValueFactory& getBasicVals() {
- return StateMgr.getBasicVals();
- }
-
- // FIXME: Remove when we migrate over to just using ValueManager.
- SymbolManager& getSymbolManager() { return SymMgr; }
- const SymbolManager& getSymbolManager() const { return SymMgr; }
-
- // Functions for external checking of whether we have unfinished work
- bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
- bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
- bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
-
- const CoreEngine &getCoreEngine() const { return Engine; }
-
-public:
- /// Visit - Transfer function logic for all statements. Dispatches to
- /// other functions that handle specific kinds of statements.
- void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// VisitArraySubscriptExpr - Transfer function for array accesses.
- void VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *Ex,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitGCCAsmStmt - Transfer function logic for inline asm.
- void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitMSAsmStmt - Transfer function logic for MS inline asm.
- void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitBlockExpr - Transfer function logic for BlockExprs.
- void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitLambdaExpr - Transfer function logic for LambdaExprs.
- void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitBinaryOperator - Transfer function logic for binary operators.
- void VisitBinaryOperator(const BinaryOperator* B, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
-
- /// VisitCall - Transfer function for function calls.
- void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitCast - Transfer function logic for all casts (implicit and explicit).
- void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
- void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// Transfer function logic for DeclRefExprs and BlockDeclRefExprs.
- void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// VisitDeclStmt - Transfer function logic for DeclStmts.
- void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose
- void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitLogicalExpr - Transfer function logic for '&&', '||'
- void VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitMemberExpr - Transfer function for member expressions.
- void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// Transfer function logic for ObjCAtSynchronizedStmts.
- void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// Transfer function logic for computing the lvalue of an Objective-C ivar.
- void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitObjCForCollectionStmt - Transfer function logic for
- /// ObjCForCollectionStmt.
- void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitReturnStmt - Transfer function logic for return statements.
- void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitOffsetOfExpr - Transfer function for offsetof.
- void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.
- void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- /// VisitUnaryOperator - Transfer function logic for unary operators.
- void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// Handle ++ and -- (both pre- and post-increment).
- void VisitIncrementDecrementOperator(const UnaryOperator* U,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE,
- ExplodedNodeSet &PreVisit,
- ExplodedNodeSet &Dst);
-
- void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred,
- ExplodedNodeSet & Dst);
-
- void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest,
- const Stmt *S, bool IsBaseDtor,
- ExplodedNode *Pred, ExplodedNodeSet &Dst);
-
- void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// Create a C++ temporary object for an rvalue.
- void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst);
-
- /// evalEagerlyAssumeBinOpBifurcation - Given the nodes in 'Src', eagerly assume symbolic
- /// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
- /// with those assumptions.
- void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- const Expr *Ex);
-
- std::pair<const ProgramPointTag *, const ProgramPointTag*>
- geteagerlyAssumeBinOpBifurcationTags();
-
- SVal evalMinus(SVal X) {
- return X.isValid() ? svalBuilder.evalMinus(X.castAs<NonLoc>()) : X;
- }
-
- SVal evalComplement(SVal X) {
- return X.isValid() ? svalBuilder.evalComplement(X.castAs<NonLoc>()) : X;
- }
-
-public:
-
- SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc L, NonLoc R, QualType T) {
- return svalBuilder.evalBinOpNN(state, op, L, R, T);
- }
-
- SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc L, SVal R, QualType T) {
- return R.isValid() ? svalBuilder.evalBinOpNN(state, op, L,
- R.castAs<NonLoc>(), T) : R;
- }
-
- SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op,
- SVal LHS, SVal RHS, QualType T) {
- return svalBuilder.evalBinOp(ST, Op, LHS, RHS, T);
- }
-
-protected:
- /// evalBind - Handle the semantics of binding a value to a specific location.
- /// This method is used by evalStore, VisitDeclStmt, and others.
- void evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE, ExplodedNode *Pred,
- SVal location, SVal Val, bool atDeclInit = false,
- const ProgramPoint *PP = nullptr);
-
- /// Call PointerEscape callback when a value escapes as a result of bind.
- ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
- SVal Loc, SVal Val) override;
- /// Call PointerEscape callback when a value escapes as a result of
- /// region invalidation.
- /// \param[in] ITraits Specifies invalidation traits for regions/symbols.
- ProgramStateRef notifyCheckersOfPointerEscape(
- ProgramStateRef State,
- const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call,
- RegionAndSymbolInvalidationTraits &ITraits) override;
-
-public:
- // FIXME: 'tag' should be removed, and a LocationContext should be used
- // instead.
- // FIXME: Comment on the meaning of the arguments, when 'St' may not
- // be the same as Pred->state, and when 'location' may not be the
- // same as state->getLValue(Ex).
- /// Simulate a read of the result of Ex.
- void evalLoad(ExplodedNodeSet &Dst,
- const Expr *NodeEx, /* Eventually will be a CFGStmt */
- const Expr *BoundExpr,
- ExplodedNode *Pred,
- ProgramStateRef St,
- SVal location,
- const ProgramPointTag *tag = nullptr,
- QualType LoadTy = QualType());
-
- // FIXME: 'tag' should be removed, and a LocationContext should be used
- // instead.
- void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE,
- ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val,
- const ProgramPointTag *tag = nullptr);
-
- /// \brief Create a new state in which the call return value is binded to the
- /// call origin expression.
- ProgramStateRef bindReturnValue(const CallEvent &Call,
- const LocationContext *LCtx,
- ProgramStateRef State);
-
- /// Evaluate a call, running pre- and post-call checks and allowing checkers
- /// to be responsible for handling the evaluation of the call itself.
- void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred,
- const CallEvent &Call);
-
- /// \brief Default implementation of call evaluation.
- void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred,
- const CallEvent &Call);
-private:
- void evalLoadCommon(ExplodedNodeSet &Dst,
- const Expr *NodeEx, /* Eventually will be a CFGStmt */
- const Expr *BoundEx,
- ExplodedNode *Pred,
- ProgramStateRef St,
- SVal location,
- const ProgramPointTag *tag,
- QualType LoadTy);
-
- // FIXME: 'tag' should be removed, and a LocationContext should be used
- // instead.
- void evalLocation(ExplodedNodeSet &Dst,
- const Stmt *NodeEx, /* This will eventually be a CFGStmt */
- const Stmt *BoundEx,
- ExplodedNode *Pred,
- ProgramStateRef St, SVal location,
- const ProgramPointTag *tag, bool isLoad);
-
- /// Count the stack depth and determine if the call is recursive.
- void examineStackFrames(const Decl *D, const LocationContext *LCtx,
- bool &IsRecursive, unsigned &StackDepth);
-
- /// Checks our policies and decides weither the given call should be inlined.
- bool shouldInlineCall(const CallEvent &Call, const Decl *D,
- const ExplodedNode *Pred);
-
- bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
- ExplodedNode *Pred, ProgramStateRef State);
-
- /// \brief Conservatively evaluate call by invalidating regions and binding
- /// a conjured return value.
- void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr,
- ExplodedNode *Pred, ProgramStateRef State);
-
- /// \brief Either inline or process the call conservatively (or both), based
- /// on DynamicDispatchBifurcation data.
- void BifurcateCall(const MemRegion *BifurReg,
- const CallEvent &Call, const Decl *D, NodeBuilder &Bldr,
- ExplodedNode *Pred);
-
- bool replayWithoutInlining(ExplodedNode *P, const LocationContext *CalleeLC);
-
- /// Models a trivial copy or move constructor or trivial assignment operator
- /// call with a simple bind.
- void performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
- const CallEvent &Call);
-
- /// If the value of the given expression is a NonLoc, copy it into a new
- /// temporary object region, and replace the value of the expression with
- /// that.
- ///
- /// If \p ResultE is provided, the new region will be bound to this expression
- /// instead of \p E.
- ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State,
- const LocationContext *LC,
- const Expr *E,
- const Expr *ResultE = nullptr);
-
- /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG
- /// block to find the constructor expression that directly constructed into
- /// the storage for this statement. Returns null if the constructor for this
- /// statement created a temporary object region rather than directly
- /// constructing into an existing region.
- const CXXConstructExpr *findDirectConstructorForCurrentCFGElement();
-
- /// For a CXXConstructExpr, walk forward in the current CFG block to find the
- /// CFGElement for the DeclStmt or CXXInitCtorInitializer for which is
- /// directly constructed by this constructor. Returns None if the current
- /// constructor expression did not directly construct into an existing
- /// region.
- Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor();
-
- /// For a given constructor, look forward in the current CFG block to
- /// determine the region into which an object will be constructed by \p CE.
- /// Returns either a field or local variable region if the object will be
- /// directly constructed in an existing region or a temporary object region
- /// if not.
- const MemRegion *getRegionForConstructedObject(const CXXConstructExpr *CE,
- ExplodedNode *Pred);
-};
-
-/// Traits for storing the call processing policy inside GDM.
-/// The GDM stores the corresponding CallExpr pointer.
-// FIXME: This does not use the nice trait macros because it must be accessible
-// from multiple translation units.
-struct ReplayWithoutInlining{};
-template <>
-struct ProgramStateTrait<ReplayWithoutInlining> :
- public ProgramStatePartialTrait<const void*> {
- static void *GDMIndex() { static int index = 0; return &index; }
-};
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
deleted file mode 100644
index ce81c98..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h
+++ /dev/null
@@ -1,140 +0,0 @@
-//== FunctionSummary.h - Stores summaries of functions. ------------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a summary of a function gathered/used by static analysis.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H
-
-#include "clang/AST/Decl.h"
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallBitVector.h"
-#include <deque>
-
-namespace clang {
-
-namespace ento {
-typedef std::deque<Decl*> SetOfDecls;
-typedef llvm::DenseSet<const Decl*> SetOfConstDecls;
-
-class FunctionSummariesTy {
- class FunctionSummary {
- public:
- /// Marks the IDs of the basic blocks visited during the analyzes.
- llvm::SmallBitVector VisitedBasicBlocks;
-
- /// Total number of blocks in the function.
- unsigned TotalBasicBlocks : 30;
-
- /// True if this function has been checked against the rules for which
- /// functions may be inlined.
- unsigned InlineChecked : 1;
-
- /// True if this function may be inlined.
- unsigned MayInline : 1;
-
- /// The number of times the function has been inlined.
- unsigned TimesInlined : 32;
-
- FunctionSummary() :
- TotalBasicBlocks(0),
- InlineChecked(0),
- TimesInlined(0) {}
- };
-
- typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy;
- MapTy Map;
-
-public:
- MapTy::iterator findOrInsertSummary(const Decl *D) {
- MapTy::iterator I = Map.find(D);
- if (I != Map.end())
- return I;
-
- typedef std::pair<const Decl *, FunctionSummary> KVPair;
- I = Map.insert(KVPair(D, FunctionSummary())).first;
- assert(I != Map.end());
- return I;
- }
-
- void markMayInline(const Decl *D) {
- MapTy::iterator I = findOrInsertSummary(D);
- I->second.InlineChecked = 1;
- I->second.MayInline = 1;
- }
-
- void markShouldNotInline(const Decl *D) {
- MapTy::iterator I = findOrInsertSummary(D);
- I->second.InlineChecked = 1;
- I->second.MayInline = 0;
- }
-
- void markReachedMaxBlockCount(const Decl *D) {
- markShouldNotInline(D);
- }
-
- Optional<bool> mayInline(const Decl *D) {
- MapTy::const_iterator I = Map.find(D);
- if (I != Map.end() && I->second.InlineChecked)
- return I->second.MayInline;
- return None;
- }
-
- void markVisitedBasicBlock(unsigned ID, const Decl* D, unsigned TotalIDs) {
- MapTy::iterator I = findOrInsertSummary(D);
- llvm::SmallBitVector &Blocks = I->second.VisitedBasicBlocks;
- assert(ID < TotalIDs);
- if (TotalIDs > Blocks.size()) {
- Blocks.resize(TotalIDs);
- I->second.TotalBasicBlocks = TotalIDs;
- }
- Blocks.set(ID);
- }
-
- unsigned getNumVisitedBasicBlocks(const Decl* D) {
- MapTy::const_iterator I = Map.find(D);
- if (I != Map.end())
- return I->second.VisitedBasicBlocks.count();
- return 0;
- }
-
- unsigned getNumTimesInlined(const Decl* D) {
- MapTy::const_iterator I = Map.find(D);
- if (I != Map.end())
- return I->second.TimesInlined;
- return 0;
- }
-
- void bumpNumTimesInlined(const Decl* D) {
- MapTy::iterator I = findOrInsertSummary(D);
- I->second.TimesInlined++;
- }
-
- /// Get the percentage of the reachable blocks.
- unsigned getPercentBlocksReachable(const Decl *D) {
- MapTy::const_iterator I = Map.find(D);
- if (I != Map.end())
- return ((I->second.VisitedBasicBlocks.count() * 100) /
- I->second.TotalBasicBlocks);
- return 0;
- }
-
- unsigned getTotalNumBasicBlocks();
- unsigned getTotalNumVisitedBasicBlocks();
-
-};
-
-}} // end clang ento namespaces
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
deleted file mode 100644
index 3168733..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===--- LoopWidening.h - Widen loops ---------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// This header contains the declarations of functions which are used to widen
-/// loops which do not otherwise exit. The widening is done by invalidating
-/// anything which might be modified by the body of the loop.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_LOOPWIDENING_H
-
-#include "clang/Analysis/CFG.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-
-namespace clang {
-namespace ento {
-
-/// \brief Get the states that result from widening the loop.
-///
-/// Widen the loop by invalidating anything that might be modified
-/// by the loop body in any iteration.
-ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState,
- const LocationContext *LCtx,
- unsigned BlockCount, const Stmt *LoopStmt);
-
-} // end namespace ento
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
deleted file mode 100644
index bb835c4..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ /dev/null
@@ -1,1370 +0,0 @@
-//== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines MemRegion and its subclasses. MemRegion defines a
-// partially-typed abstraction of memory useful for path-sensitive dataflow
-// analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <string>
-
-namespace clang {
-
-class LocationContext;
-class StackFrameContext;
-
-namespace ento {
-
-class CodeTextRegion;
-class MemRegionManager;
-class MemSpaceRegion;
-class SValBuilder;
-class SymbolicRegion;
-class VarRegion;
-
-/// Represent a region's offset within the top level base region.
-class RegionOffset {
- /// The base region.
- const MemRegion *R;
-
- /// The bit offset within the base region. Can be negative.
- int64_t Offset;
-
-public:
- // We're using a const instead of an enumeration due to the size required;
- // Visual Studio will only create enumerations of size int, not long long.
- static const int64_t Symbolic = INT64_MAX;
-
- RegionOffset() : R(nullptr) {}
- RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
-
- const MemRegion *getRegion() const { return R; }
-
- bool hasSymbolicOffset() const { return Offset == Symbolic; }
-
- int64_t getOffset() const {
- assert(!hasSymbolicOffset());
- return Offset;
- }
-
- bool isValid() const { return R; }
-};
-
-//===----------------------------------------------------------------------===//
-// Base region classes.
-//===----------------------------------------------------------------------===//
-
-/// MemRegion - The root abstract class for all memory regions.
-class MemRegion : public llvm::FoldingSetNode {
- friend class MemRegionManager;
-public:
- enum Kind {
- // Memory spaces.
- GenericMemSpaceRegionKind,
- StackLocalsSpaceRegionKind,
- StackArgumentsSpaceRegionKind,
- HeapSpaceRegionKind,
- UnknownSpaceRegionKind,
- StaticGlobalSpaceRegionKind,
- GlobalInternalSpaceRegionKind,
- GlobalSystemSpaceRegionKind,
- GlobalImmutableSpaceRegionKind,
- BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
- END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
- BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
- END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
- BEG_MEMSPACES = GenericMemSpaceRegionKind,
- END_MEMSPACES = GlobalImmutableSpaceRegionKind,
- // Untyped regions.
- SymbolicRegionKind,
- AllocaRegionKind,
- // Typed regions.
- BEG_TYPED_REGIONS,
- FunctionTextRegionKind = BEG_TYPED_REGIONS,
- BlockTextRegionKind,
- BlockDataRegionKind,
- BEG_TYPED_VALUE_REGIONS,
- CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS,
- CXXThisRegionKind,
- StringRegionKind,
- ObjCStringRegionKind,
- ElementRegionKind,
- // Decl Regions.
- BEG_DECL_REGIONS,
- VarRegionKind = BEG_DECL_REGIONS,
- FieldRegionKind,
- ObjCIvarRegionKind,
- END_DECL_REGIONS = ObjCIvarRegionKind,
- CXXTempObjectRegionKind,
- CXXBaseObjectRegionKind,
- END_TYPED_VALUE_REGIONS = CXXBaseObjectRegionKind,
- END_TYPED_REGIONS = CXXBaseObjectRegionKind
- };
-
-private:
- const Kind kind;
-
-protected:
- MemRegion(Kind k) : kind(k) {}
- virtual ~MemRegion();
-
-public:
- ASTContext &getContext() const;
-
- virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
-
- virtual MemRegionManager* getMemRegionManager() const = 0;
-
- const MemSpaceRegion *getMemorySpace() const;
-
- const MemRegion *getBaseRegion() const;
-
- /// Check if the region is a subregion of the given region.
- virtual bool isSubRegionOf(const MemRegion *R) const;
-
- const MemRegion *StripCasts(bool StripBaseCasts = true) const;
-
- /// \brief If this is a symbolic region, returns the region. Otherwise,
- /// goes up the base chain looking for the first symbolic base region.
- const SymbolicRegion *getSymbolicBase() const;
-
- bool hasGlobalsOrParametersStorage() const;
-
- bool hasStackStorage() const;
-
- bool hasStackNonParametersStorage() const;
-
- bool hasStackParametersStorage() const;
-
- /// Compute the offset within the top level memory object.
- RegionOffset getAsOffset() const;
-
- /// \brief Get a string representation of a region for debug use.
- std::string getString() const;
-
- virtual void dumpToStream(raw_ostream &os) const;
-
- void dump() const;
-
- /// \brief Returns true if this region can be printed in a user-friendly way.
- virtual bool canPrintPretty() const;
-
- /// \brief Print the region for use in diagnostics.
- virtual void printPretty(raw_ostream &os) const;
-
- /// \brief Returns true if this region's textual representation can be used
- /// as part of a larger expression.
- virtual bool canPrintPrettyAsExpr() const;
-
- /// \brief Print the region as expression.
- ///
- /// When this region represents a subexpression, the method is for printing
- /// an expression containing it.
- virtual void printPrettyAsExpr(raw_ostream &os) const;
-
- Kind getKind() const { return kind; }
-
- template<typename RegionTy> const RegionTy* getAs() const;
-
- virtual bool isBoundable() const { return false; }
-};
-
-/// MemSpaceRegion - A memory region that represents a "memory space";
-/// for example, the set of global variables, the stack frame, etc.
-class MemSpaceRegion : public MemRegion {
-protected:
- friend class MemRegionManager;
-
- MemRegionManager *Mgr;
-
- MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
- : MemRegion(k), Mgr(mgr) {
- assert(classof(this));
- }
-
- MemRegionManager* getMemRegionManager() const override { return Mgr; }
-
-public:
- bool isBoundable() const override { return false; }
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static bool classof(const MemRegion *R) {
- Kind k = R->getKind();
- return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
- }
-};
-
-class GlobalsSpaceRegion : public MemSpaceRegion {
- virtual void anchor();
-protected:
- GlobalsSpaceRegion(MemRegionManager *mgr, Kind k)
- : MemSpaceRegion(mgr, k) {}
-public:
- static bool classof(const MemRegion *R) {
- Kind k = R->getKind();
- return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
- }
-};
-
-/// \brief The region of the static variables within the current CodeTextRegion
-/// scope.
-///
-/// Currently, only the static locals are placed there, so we know that these
-/// variables do not get invalidated by calls to other functions.
-class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
- friend class MemRegionManager;
-
- const CodeTextRegion *CR;
-
- StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
- : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {}
-
-public:
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- const CodeTextRegion *getCodeRegion() const { return CR; }
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == StaticGlobalSpaceRegionKind;
- }
-};
-
-/// \brief The region for all the non-static global variables.
-///
-/// This class is further split into subclasses for efficient implementation of
-/// invalidating a set of related global values as is done in
-/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
-/// globals, we invalidate the whole parent region).
-class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
- friend class MemRegionManager;
-
-protected:
- NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
- : GlobalsSpaceRegion(mgr, k) {}
-
-public:
-
- static bool classof(const MemRegion *R) {
- Kind k = R->getKind();
- return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
- k <= END_NON_STATIC_GLOBAL_MEMSPACES;
- }
-};
-
-/// \brief The region containing globals which are defined in system/external
-/// headers and are considered modifiable by system calls (ex: errno).
-class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
- friend class MemRegionManager;
-
- GlobalSystemSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
-
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == GlobalSystemSpaceRegionKind;
- }
-};
-
-/// \brief The region containing globals which are considered not to be modified
-/// or point to data which could be modified as a result of a function call
-/// (system or internal). Ex: Const global scalars would be modeled as part of
-/// this region. This region also includes most system globals since they have
-/// low chance of being modified.
-class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
- friend class MemRegionManager;
-
- GlobalImmutableSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
-
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == GlobalImmutableSpaceRegionKind;
- }
-};
-
-/// \brief The region containing globals which can be modified by calls to
-/// "internally" defined functions - (for now just) functions other then system
-/// calls.
-class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
- friend class MemRegionManager;
-
- GlobalInternalSpaceRegion(MemRegionManager *mgr)
- : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
-
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == GlobalInternalSpaceRegionKind;
- }
-};
-
-class HeapSpaceRegion : public MemSpaceRegion {
- virtual void anchor();
- friend class MemRegionManager;
-
- HeapSpaceRegion(MemRegionManager *mgr)
- : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == HeapSpaceRegionKind;
- }
-};
-
-class UnknownSpaceRegion : public MemSpaceRegion {
- virtual void anchor();
- friend class MemRegionManager;
- UnknownSpaceRegion(MemRegionManager *mgr)
- : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == UnknownSpaceRegionKind;
- }
-};
-
-class StackSpaceRegion : public MemSpaceRegion {
-private:
- const StackFrameContext *SFC;
-
-protected:
- StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
- : MemSpaceRegion(mgr, k), SFC(sfc) {
- assert(classof(this));
- }
-
-public:
- const StackFrameContext *getStackFrame() const { return SFC; }
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static bool classof(const MemRegion *R) {
- Kind k = R->getKind();
- return k >= StackLocalsSpaceRegionKind &&
- k <= StackArgumentsSpaceRegionKind;
- }
-};
-
-class StackLocalsSpaceRegion : public StackSpaceRegion {
- virtual void anchor();
- friend class MemRegionManager;
- StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
- : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == StackLocalsSpaceRegionKind;
- }
-};
-
-class StackArgumentsSpaceRegion : public StackSpaceRegion {
-private:
- virtual void anchor();
- friend class MemRegionManager;
- StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
- : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
-public:
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion *R) {
- return R->getKind() == StackArgumentsSpaceRegionKind;
- }
-};
-
-
-/// SubRegion - A region that subsets another larger region. Most regions
-/// are subclasses of SubRegion.
-class SubRegion : public MemRegion {
-private:
- virtual void anchor();
-protected:
- const MemRegion* superRegion;
- SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
-public:
- const MemRegion* getSuperRegion() const {
- return superRegion;
- }
-
- /// getExtent - Returns the size of the region in bytes.
- virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
- return UnknownVal();
- }
-
- MemRegionManager* getMemRegionManager() const override;
-
- bool isSubRegionOf(const MemRegion* R) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() > END_MEMSPACES;
- }
-};
-
-//===----------------------------------------------------------------------===//
-// MemRegion subclasses.
-//===----------------------------------------------------------------------===//
-
-/// AllocaRegion - A region that represents an untyped blob of bytes created
-/// by a call to 'alloca'.
-class AllocaRegion : public SubRegion {
- friend class MemRegionManager;
-protected:
- unsigned Cnt; // Block counter. Used to distinguish different pieces of
- // memory allocated by alloca at the same call site.
- const Expr *Ex;
-
- AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion)
- : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
-
-public:
-
- const Expr *getExpr() const { return Ex; }
-
- bool isBoundable() const override { return true; }
-
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
- unsigned Cnt, const MemRegion *superRegion);
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == AllocaRegionKind;
- }
-};
-
-/// TypedRegion - An abstract class representing regions that are typed.
-class TypedRegion : public SubRegion {
-public:
- void anchor() override;
-protected:
- TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
-
-public:
- virtual QualType getLocationType() const = 0;
-
- QualType getDesugaredLocationType(ASTContext &Context) const {
- return getLocationType().getDesugaredType(Context);
- }
-
- bool isBoundable() const override { return true; }
-
- static bool classof(const MemRegion* R) {
- unsigned k = R->getKind();
- return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
- }
-};
-
-/// TypedValueRegion - An abstract class representing regions having a typed value.
-class TypedValueRegion : public TypedRegion {
-public:
- void anchor() override;
-protected:
- TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {}
-
-public:
- virtual QualType getValueType() const = 0;
-
- QualType getLocationType() const override {
- // FIXME: We can possibly optimize this later to cache this value.
- QualType T = getValueType();
- ASTContext &ctx = getContext();
- if (T->getAs<ObjCObjectType>())
- return ctx.getObjCObjectPointerType(T);
- return ctx.getPointerType(getValueType());
- }
-
- QualType getDesugaredValueType(ASTContext &Context) const {
- QualType T = getValueType();
- return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
- }
-
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
-
- static bool classof(const MemRegion* R) {
- unsigned k = R->getKind();
- return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
- }
-};
-
-
-class CodeTextRegion : public TypedRegion {
-public:
- void anchor() override;
-protected:
- CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
-public:
- bool isBoundable() const override { return false; }
-
- static bool classof(const MemRegion* R) {
- Kind k = R->getKind();
- return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
- }
-};
-
-/// FunctionTextRegion - A region that represents code texts of function.
-class FunctionTextRegion : public CodeTextRegion {
- const NamedDecl *FD;
-public:
- FunctionTextRegion(const NamedDecl *fd, const MemRegion* sreg)
- : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {
- assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
- }
-
- QualType getLocationType() const override {
- const ASTContext &Ctx = getContext();
- if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
- return Ctx.getPointerType(D->getType());
- }
-
- assert(isa<ObjCMethodDecl>(FD));
- assert(false && "Getting the type of ObjCMethod is not supported yet");
-
- // TODO: We might want to return a different type here (ex: id (*ty)(...))
- // depending on how it is used.
- return QualType();
- }
-
- const NamedDecl *getDecl() const {
- return FD;
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
- const MemRegion*);
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == FunctionTextRegionKind;
- }
-};
-
-
-/// BlockTextRegion - A region that represents code texts of blocks (closures).
-/// Blocks are represented with two kinds of regions. BlockTextRegions
-/// represent the "code", while BlockDataRegions represent instances of blocks,
-/// which correspond to "code+data". The distinction is important, because
-/// like a closure a block captures the values of externally referenced
-/// variables.
-class BlockTextRegion : public CodeTextRegion {
- friend class MemRegionManager;
-
- const BlockDecl *BD;
- AnalysisDeclContext *AC;
- CanQualType locTy;
-
- BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
- AnalysisDeclContext *ac, const MemRegion* sreg)
- : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
-
-public:
- QualType getLocationType() const override {
- return locTy;
- }
-
- const BlockDecl *getDecl() const {
- return BD;
- }
-
- AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
- CanQualType, const AnalysisDeclContext*,
- const MemRegion*);
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == BlockTextRegionKind;
- }
-};
-
-/// BlockDataRegion - A region that represents a block instance.
-/// Blocks are represented with two kinds of regions. BlockTextRegions
-/// represent the "code", while BlockDataRegions represent instances of blocks,
-/// which correspond to "code+data". The distinction is important, because
-/// like a closure a block captures the values of externally referenced
-/// variables.
-class BlockDataRegion : public TypedRegion {
- friend class MemRegionManager;
- const BlockTextRegion *BC;
- const LocationContext *LC; // Can be null */
- unsigned BlockCount;
- void *ReferencedVars;
- void *OriginalVars;
-
- BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
- unsigned count, const MemRegion *sreg)
- : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
- BlockCount(count),
- ReferencedVars(nullptr), OriginalVars(nullptr) {}
-
-public:
- const BlockTextRegion *getCodeRegion() const { return BC; }
-
- const BlockDecl *getDecl() const { return BC->getDecl(); }
-
- QualType getLocationType() const override { return BC->getLocationType(); }
-
- class referenced_vars_iterator {
- const MemRegion * const *R;
- const MemRegion * const *OriginalR;
- public:
- explicit referenced_vars_iterator(const MemRegion * const *r,
- const MemRegion * const *originalR)
- : R(r), OriginalR(originalR) {}
-
- const VarRegion *getCapturedRegion() const {
- return cast<VarRegion>(*R);
- }
- const VarRegion *getOriginalRegion() const {
- return cast<VarRegion>(*OriginalR);
- }
-
- bool operator==(const referenced_vars_iterator &I) const {
- assert((R == nullptr) == (I.R == nullptr));
- return I.R == R;
- }
- bool operator!=(const referenced_vars_iterator &I) const {
- assert((R == nullptr) == (I.R == nullptr));
- return I.R != R;
- }
- referenced_vars_iterator &operator++() {
- ++R;
- ++OriginalR;
- return *this;
- }
- };
-
- /// Return the original region for a captured region, if
- /// one exists.
- const VarRegion *getOriginalRegion(const VarRegion *VR) const;
-
- referenced_vars_iterator referenced_vars_begin() const;
- referenced_vars_iterator referenced_vars_end() const;
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
- const LocationContext *, unsigned,
- const MemRegion *);
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == BlockDataRegionKind;
- }
-private:
- void LazyInitializeReferencedVars();
- std::pair<const VarRegion *, const VarRegion *>
- getCaptureRegions(const VarDecl *VD);
-};
-
-/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
-/// classes, SymbolicRegion represents a region that serves as an alias for
-/// either a real region, a NULL pointer, etc. It essentially is used to
-/// map the concept of symbolic values into the domain of regions. Symbolic
-/// regions do not need to be typed.
-class SymbolicRegion : public SubRegion {
-protected:
- const SymbolRef sym;
-
-public:
- SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
- : SubRegion(sreg, SymbolicRegionKind), sym(s) {}
-
- SymbolRef getSymbol() const {
- return sym;
- }
-
- bool isBoundable() const override { return true; }
-
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- SymbolRef sym,
- const MemRegion* superRegion);
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == SymbolicRegionKind;
- }
-};
-
-/// StringRegion - Region associated with a StringLiteral.
-class StringRegion : public TypedValueRegion {
- friend class MemRegionManager;
- const StringLiteral* Str;
-protected:
-
- StringRegion(const StringLiteral* str, const MemRegion* sreg)
- : TypedValueRegion(sreg, StringRegionKind), Str(str) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const StringLiteral* Str,
- const MemRegion* superRegion);
-
-public:
-
- const StringLiteral* getStringLiteral() const { return Str; }
-
- QualType getValueType() const override {
- return Str->getType();
- }
-
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
-
- bool isBoundable() const override { return false; }
-
- void Profile(llvm::FoldingSetNodeID& ID) const override {
- ProfileRegion(ID, Str, superRegion);
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == StringRegionKind;
- }
-};
-
-/// The region associated with an ObjCStringLiteral.
-class ObjCStringRegion : public TypedValueRegion {
- friend class MemRegionManager;
- const ObjCStringLiteral* Str;
-protected:
-
- ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg)
- : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const ObjCStringLiteral* Str,
- const MemRegion* superRegion);
-
-public:
-
- const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
-
- QualType getValueType() const override {
- return Str->getType();
- }
-
- bool isBoundable() const override { return false; }
-
- void Profile(llvm::FoldingSetNodeID& ID) const override {
- ProfileRegion(ID, Str, superRegion);
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == ObjCStringRegionKind;
- }
-};
-
-/// CompoundLiteralRegion - A memory region representing a compound literal.
-/// Compound literals are essentially temporaries that are stack allocated
-/// or in the global constant pool.
-class CompoundLiteralRegion : public TypedValueRegion {
-private:
- friend class MemRegionManager;
- const CompoundLiteralExpr *CL;
-
- CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg)
- : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const CompoundLiteralExpr *CL,
- const MemRegion* superRegion);
-public:
- QualType getValueType() const override {
- return CL->getType();
- }
-
- bool isBoundable() const override { return !CL->isFileScope(); }
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == CompoundLiteralRegionKind;
- }
-};
-
-class DeclRegion : public TypedValueRegion {
-protected:
- const Decl *D;
-
- DeclRegion(const Decl *d, const MemRegion* sReg, Kind k)
- : TypedValueRegion(sReg, k), D(d) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
- const MemRegion* superRegion, Kind k);
-
-public:
- const Decl *getDecl() const { return D; }
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static bool classof(const MemRegion* R) {
- unsigned k = R->getKind();
- return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
- }
-};
-
-class VarRegion : public DeclRegion {
- friend class MemRegionManager;
-
- // Constructors and private methods.
- VarRegion(const VarDecl *vd, const MemRegion* sReg)
- : DeclRegion(vd, sReg, VarRegionKind) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
- const MemRegion *superRegion) {
- DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
-public:
- const VarDecl *getDecl() const { return cast<VarDecl>(D); }
-
- const StackFrameContext *getStackFrame() const;
-
- QualType getValueType() const override {
- // FIXME: We can cache this if needed.
- return getDecl()->getType();
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == VarRegionKind;
- }
-
- bool canPrintPrettyAsExpr() const override;
-
- void printPrettyAsExpr(raw_ostream &os) const override;
-};
-
-/// CXXThisRegion - Represents the region for the implicit 'this' parameter
-/// in a call to a C++ method. This region doesn't represent the object
-/// referred to by 'this', but rather 'this' itself.
-class CXXThisRegion : public TypedValueRegion {
- friend class MemRegionManager;
- CXXThisRegion(const PointerType *thisPointerTy,
- const MemRegion *sReg)
- : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID &ID,
- const PointerType *PT,
- const MemRegion *sReg);
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
-public:
- QualType getValueType() const override {
- return QualType(ThisPointerTy, 0);
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == CXXThisRegionKind;
- }
-
-private:
- const PointerType *ThisPointerTy;
-};
-
-class FieldRegion : public DeclRegion {
- friend class MemRegionManager;
-
- FieldRegion(const FieldDecl *fd, const MemRegion* sReg)
- : DeclRegion(fd, sReg, FieldRegionKind) {}
-
-public:
- const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
-
- QualType getValueType() const override {
- // FIXME: We can cache this if needed.
- return getDecl()->getType();
- }
-
- DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
- const MemRegion* superRegion) {
- DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
- }
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == FieldRegionKind;
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- bool canPrintPretty() const override;
- void printPretty(raw_ostream &os) const override;
- bool canPrintPrettyAsExpr() const override;
- void printPrettyAsExpr(raw_ostream &os) const override;
-};
-
-class ObjCIvarRegion : public DeclRegion {
-
- friend class MemRegionManager;
-
- ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg);
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
- const MemRegion* superRegion);
-
-public:
- const ObjCIvarDecl *getDecl() const;
- QualType getValueType() const override;
-
- bool canPrintPrettyAsExpr() const override;
- void printPrettyAsExpr(raw_ostream &os) const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == ObjCIvarRegionKind;
- }
-};
-//===----------------------------------------------------------------------===//
-// Auxiliary data classes for use with MemRegions.
-//===----------------------------------------------------------------------===//
-
-class ElementRegion;
-
-class RegionRawOffset {
-private:
- friend class ElementRegion;
-
- const MemRegion *Region;
- CharUnits Offset;
-
- RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
- : Region(reg), Offset(offset) {}
-
-public:
- // FIXME: Eventually support symbolic offsets.
- CharUnits getOffset() const { return Offset; }
- const MemRegion *getRegion() const { return Region; }
-
- void dumpToStream(raw_ostream &os) const;
- void dump() const;
-};
-
-/// \brief ElementRegin is used to represent both array elements and casts.
-class ElementRegion : public TypedValueRegion {
- friend class MemRegionManager;
-
- QualType ElementType;
- NonLoc Index;
-
- ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
- : TypedValueRegion(sReg, ElementRegionKind),
- ElementType(elementType), Index(Idx) {
- assert((!Idx.getAs<nonloc::ConcreteInt>() ||
- Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
- "The index must be signed");
- }
-
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
- SVal Idx, const MemRegion* superRegion);
-
-public:
-
- NonLoc getIndex() const { return Index; }
-
- QualType getValueType() const override {
- return ElementType;
- }
-
- QualType getElementType() const {
- return ElementType;
- }
- /// Compute the offset within the array. The array might also be a subobject.
- RegionRawOffset getAsArrayOffset() const;
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID& ID) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == ElementRegionKind;
- }
-};
-
-// C++ temporary object associated with an expression.
-class CXXTempObjectRegion : public TypedValueRegion {
- friend class MemRegionManager;
-
- Expr const *Ex;
-
- CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
- : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID &ID,
- Expr const *E, const MemRegion *sReg);
-
-public:
- const Expr *getExpr() const { return Ex; }
-
- QualType getValueType() const override {
- return Ex->getType();
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static bool classof(const MemRegion* R) {
- return R->getKind() == CXXTempObjectRegionKind;
- }
-};
-
-// CXXBaseObjectRegion represents a base object within a C++ object. It is
-// identified by the base class declaration and the region of its parent object.
-class CXXBaseObjectRegion : public TypedValueRegion {
- friend class MemRegionManager;
-
- llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
-
- CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
- const MemRegion *SReg)
- : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {}
-
- static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
- bool IsVirtual, const MemRegion *SReg);
-
-public:
- const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
- bool isVirtual() const { return Data.getInt(); }
-
- QualType getValueType() const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- void Profile(llvm::FoldingSetNodeID &ID) const override;
-
- static bool classof(const MemRegion *region) {
- return region->getKind() == CXXBaseObjectRegionKind;
- }
-
- bool canPrintPrettyAsExpr() const override;
-
- void printPrettyAsExpr(raw_ostream &os) const override;
-};
-
-template<typename RegionTy>
-const RegionTy* MemRegion::getAs() const {
- if (const RegionTy* RT = dyn_cast<RegionTy>(this))
- return RT;
-
- return nullptr;
-}
-
-//===----------------------------------------------------------------------===//
-// MemRegionManager - Factory object for creating regions.
-//===----------------------------------------------------------------------===//
-
-class MemRegionManager {
- ASTContext &C;
- llvm::BumpPtrAllocator& A;
- llvm::FoldingSet<MemRegion> Regions;
-
- GlobalInternalSpaceRegion *InternalGlobals;
- GlobalSystemSpaceRegion *SystemGlobals;
- GlobalImmutableSpaceRegion *ImmutableGlobals;
-
-
- llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
- StackLocalsSpaceRegions;
- llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
- StackArgumentsSpaceRegions;
- llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
- StaticsGlobalSpaceRegions;
-
- HeapSpaceRegion *heap;
- UnknownSpaceRegion *unknown;
- MemSpaceRegion *code;
-
-public:
- MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
- : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr),
- ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr),
- code(nullptr) {}
-
- ~MemRegionManager();
-
- ASTContext &getContext() { return C; }
-
- llvm::BumpPtrAllocator &getAllocator() { return A; }
-
- /// getStackLocalsRegion - Retrieve the memory region associated with the
- /// specified stack frame.
- const StackLocalsSpaceRegion *
- getStackLocalsRegion(const StackFrameContext *STC);
-
- /// getStackArgumentsRegion - Retrieve the memory region associated with
- /// function/method arguments of the specified stack frame.
- const StackArgumentsSpaceRegion *
- getStackArgumentsRegion(const StackFrameContext *STC);
-
- /// getGlobalsRegion - Retrieve the memory region associated with
- /// global variables.
- const GlobalsSpaceRegion *getGlobalsRegion(
- MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
- const CodeTextRegion *R = nullptr);
-
- /// getHeapRegion - Retrieve the memory region associated with the
- /// generic "heap".
- const HeapSpaceRegion *getHeapRegion();
-
- /// getUnknownRegion - Retrieve the memory region associated with unknown
- /// memory space.
- const MemSpaceRegion *getUnknownRegion();
-
- const MemSpaceRegion *getCodeRegion();
-
- /// getAllocaRegion - Retrieve a region associated with a call to alloca().
- const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
- const LocationContext *LC);
-
- /// getCompoundLiteralRegion - Retrieve the region associated with a
- /// given CompoundLiteral.
- const CompoundLiteralRegion*
- getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
- const LocationContext *LC);
-
- /// getCXXThisRegion - Retrieve the [artificial] region associated with the
- /// parameter 'this'.
- const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
- const LocationContext *LC);
-
- /// \brief Retrieve or create a "symbolic" memory region.
- const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
-
- /// \brief Return a unique symbolic region belonging to heap memory space.
- const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
-
- const StringRegion *getStringRegion(const StringLiteral* Str);
-
- const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
-
- /// getVarRegion - Retrieve or create the memory region associated with
- /// a specified VarDecl and LocationContext.
- const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
-
- /// getVarRegion - Retrieve or create the memory region associated with
- /// a specified VarDecl and super region.
- const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
-
- /// getElementRegion - Retrieve the memory region associated with the
- /// associated element type, index, and super region.
- const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
- const MemRegion *superRegion,
- ASTContext &Ctx);
-
- const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
- const MemRegion *superRegion) {
- return getElementRegion(ER->getElementType(), ER->getIndex(),
- superRegion, ER->getContext());
- }
-
- /// getFieldRegion - Retrieve or create the memory region associated with
- /// a specified FieldDecl. 'superRegion' corresponds to the containing
- /// memory region (which typically represents the memory representing
- /// a structure or class).
- const FieldRegion *getFieldRegion(const FieldDecl *fd,
- const MemRegion* superRegion);
-
- const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
- const MemRegion *superRegion) {
- return getFieldRegion(FR->getDecl(), superRegion);
- }
-
- /// getObjCIvarRegion - Retrieve or create the memory region associated with
- /// a specified Objective-c instance variable. 'superRegion' corresponds
- /// to the containing region (which typically represents the Objective-C
- /// object).
- const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
- const MemRegion* superRegion);
-
- const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
- LocationContext const *LC);
-
- /// Create a CXXBaseObjectRegion with the given base class for region
- /// \p Super.
- ///
- /// The type of \p Super is assumed be a class deriving from \p BaseClass.
- const CXXBaseObjectRegion *
- getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const MemRegion *Super,
- bool IsVirtual);
-
- /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
- /// super region.
- const CXXBaseObjectRegion *
- getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
- const MemRegion *superRegion) {
- return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
- baseReg->isVirtual());
- }
-
- const FunctionTextRegion *getFunctionTextRegion(const NamedDecl *FD);
- const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
- CanQualType locTy,
- AnalysisDeclContext *AC);
-
- /// getBlockDataRegion - Get the memory region associated with an instance
- /// of a block. Unlike many other MemRegions, the LocationContext*
- /// argument is allowed to be NULL for cases where we have no known
- /// context.
- const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
- const LocationContext *lc,
- unsigned blockCount);
-
- /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
- /// by static references. This differs from getCXXTempObjectRegion in the
- /// super-region used.
- const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
-
-private:
- template <typename RegionTy, typename A1>
- RegionTy* getRegion(const A1 a1);
-
- template <typename RegionTy, typename A1>
- RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion);
-
- template <typename RegionTy, typename A1, typename A2>
- RegionTy* getRegion(const A1 a1, const A2 a2);
-
- template <typename RegionTy, typename A1, typename A2>
- RegionTy* getSubRegion(const A1 a1, const A2 a2,
- const MemRegion* superRegion);
-
- template <typename RegionTy, typename A1, typename A2, typename A3>
- RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
- const MemRegion* superRegion);
-
- template <typename REG>
- const REG* LazyAllocate(REG*& region);
-
- template <typename REG, typename ARG>
- const REG* LazyAllocate(REG*& region, ARG a);
-};
-
-//===----------------------------------------------------------------------===//
-// Out-of-line member definitions.
-//===----------------------------------------------------------------------===//
-
-inline ASTContext &MemRegion::getContext() const {
- return getMemRegionManager()->getContext();
-}
-
-//===----------------------------------------------------------------------===//
-// Means for storing region/symbol handling traits.
-//===----------------------------------------------------------------------===//
-
-/// Information about invalidation for a particular region/symbol.
-class RegionAndSymbolInvalidationTraits {
- typedef unsigned char StorageTypeForKinds;
- llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
- llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
-
- typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
- const_region_iterator;
- typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
- const_symbol_iterator;
-
-public:
- /// \brief Describes different invalidation traits.
- enum InvalidationKinds {
- /// Tells that a region's contents is not changed.
- TK_PreserveContents = 0x1,
- /// Suppress pointer-escaping of a region.
- TK_SuppressEscape = 0x2,
- // Do not invalidate super region.
- TK_DoNotInvalidateSuperRegion = 0x4,
- /// When applied to a MemSpaceRegion, indicates the entire memory space
- /// should be invalidated.
- TK_EntireMemSpace = 0x8
-
- // Do not forget to extend StorageTypeForKinds if number of traits exceed
- // the number of bits StorageTypeForKinds can store.
- };
-
- void setTrait(SymbolRef Sym, InvalidationKinds IK);
- void setTrait(const MemRegion *MR, InvalidationKinds IK);
- bool hasTrait(SymbolRef Sym, InvalidationKinds IK);
- bool hasTrait(const MemRegion *MR, InvalidationKinds IK);
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-//===----------------------------------------------------------------------===//
-// Pretty-printing regions.
-//===----------------------------------------------------------------------===//
-
-namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- const clang::ento::MemRegion* R) {
- R->dumpToStream(os);
- return os;
-}
-} // end llvm namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
deleted file mode 100644
index c4a62ec..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
+++ /dev/null
@@ -1,854 +0,0 @@
-//== ProgramState.h - Path-sensitive "State" for tracking values -*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the state of the program along the analysisa path.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H
-
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Environment.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/ImmutableMap.h"
-#include "llvm/ADT/PointerIntPair.h"
-#include "llvm/Support/Allocator.h"
-
-namespace llvm {
-class APSInt;
-}
-
-namespace clang {
-class ASTContext;
-
-namespace ento {
-
-class CallEvent;
-class CallEventManager;
-
-typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)(
- ProgramStateManager &, SubEngine *);
-typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)(
- ProgramStateManager &);
-
-//===----------------------------------------------------------------------===//
-// ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState.
-//===----------------------------------------------------------------------===//
-
-template <typename T> struct ProgramStatePartialTrait;
-
-template <typename T> struct ProgramStateTrait {
- typedef typename T::data_type data_type;
- static inline void *MakeVoidPtr(data_type D) { return (void*) D; }
- static inline data_type MakeData(void *const* P) {
- return P ? (data_type) *P : (data_type) 0;
- }
-};
-
-/// \class ProgramState
-/// ProgramState - This class encapsulates:
-///
-/// 1. A mapping from expressions to values (Environment)
-/// 2. A mapping from locations to values (Store)
-/// 3. Constraints on symbolic values (GenericDataMap)
-///
-/// Together these represent the "abstract state" of a program.
-///
-/// ProgramState is intended to be used as a functional object; that is,
-/// once it is created and made "persistent" in a FoldingSet, its
-/// values will never change.
-class ProgramState : public llvm::FoldingSetNode {
-public:
- typedef llvm::ImmutableSet<llvm::APSInt*> IntSetTy;
- typedef llvm::ImmutableMap<void*, void*> GenericDataMap;
-
-private:
- void operator=(const ProgramState& R) = delete;
-
- friend class ProgramStateManager;
- friend class ExplodedGraph;
- friend class ExplodedNode;
-
- ProgramStateManager *stateMgr;
- Environment Env; // Maps a Stmt to its current SVal.
- Store store; // Maps a location to its current value.
- GenericDataMap GDM; // Custom data stored by a client of this class.
- unsigned refCount;
-
- /// makeWithStore - Return a ProgramState with the same values as the current
- /// state with the exception of using the specified Store.
- ProgramStateRef makeWithStore(const StoreRef &store) const;
-
- void setStore(const StoreRef &storeRef);
-
-public:
- /// This ctor is used when creating the first ProgramState object.
- ProgramState(ProgramStateManager *mgr, const Environment& env,
- StoreRef st, GenericDataMap gdm);
-
- /// Copy ctor - We must explicitly define this or else the "Next" ptr
- /// in FoldingSetNode will also get copied.
- ProgramState(const ProgramState &RHS);
-
- ~ProgramState();
-
- /// Return the ProgramStateManager associated with this state.
- ProgramStateManager &getStateManager() const {
- return *stateMgr;
- }
-
- /// Return the ConstraintManager.
- ConstraintManager &getConstraintManager() const;
-
- /// getEnvironment - Return the environment associated with this state.
- /// The environment is the mapping from expressions to values.
- const Environment& getEnvironment() const { return Env; }
-
- /// Return the store associated with this state. The store
- /// is a mapping from locations to values.
- Store getStore() const { return store; }
-
-
- /// getGDM - Return the generic data map associated with this state.
- GenericDataMap getGDM() const { return GDM; }
-
- void setGDM(GenericDataMap gdm) { GDM = gdm; }
-
- /// Profile - Profile the contents of a ProgramState object for use in a
- /// FoldingSet. Two ProgramState objects are considered equal if they
- /// have the same Environment, Store, and GenericDataMap.
- static void Profile(llvm::FoldingSetNodeID& ID, const ProgramState *V) {
- V->Env.Profile(ID);
- ID.AddPointer(V->store);
- V->GDM.Profile(ID);
- }
-
- /// Profile - Used to profile the contents of this object for inclusion
- /// in a FoldingSet.
- void Profile(llvm::FoldingSetNodeID& ID) const {
- Profile(ID, this);
- }
-
- BasicValueFactory &getBasicVals() const;
- SymbolManager &getSymbolManager() const;
-
- //==---------------------------------------------------------------------==//
- // Constraints on values.
- //==---------------------------------------------------------------------==//
- //
- // Each ProgramState records constraints on symbolic values. These constraints
- // are managed using the ConstraintManager associated with a ProgramStateManager.
- // As constraints gradually accrue on symbolic values, added constraints
- // may conflict and indicate that a state is infeasible (as no real values
- // could satisfy all the constraints). This is the principal mechanism
- // for modeling path-sensitivity in ExprEngine/ProgramState.
- //
- // Various "assume" methods form the interface for adding constraints to
- // symbolic values. A call to 'assume' indicates an assumption being placed
- // on one or symbolic values. 'assume' methods take the following inputs:
- //
- // (1) A ProgramState object representing the current state.
- //
- // (2) The assumed constraint (which is specific to a given "assume" method).
- //
- // (3) A binary value "Assumption" that indicates whether the constraint is
- // assumed to be true or false.
- //
- // The output of "assume*" is a new ProgramState object with the added constraints.
- // If no new state is feasible, NULL is returned.
- //
-
- /// Assumes that the value of \p cond is zero (if \p assumption is "false")
- /// or non-zero (if \p assumption is "true").
- ///
- /// This returns a new state with the added constraint on \p cond.
- /// If no new state is feasible, NULL is returned.
- ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const;
-
- /// Assumes both "true" and "false" for \p cond, and returns both
- /// corresponding states (respectively).
- ///
- /// This is more efficient than calling assume() twice. Note that one (but not
- /// both) of the returned states may be NULL.
- std::pair<ProgramStateRef, ProgramStateRef>
- assume(DefinedOrUnknownSVal cond) const;
-
- ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx,
- DefinedOrUnknownSVal upperBound,
- bool assumption,
- QualType IndexType = QualType()) const;
-
- /// Assumes that the value of \p Val is bounded with [\p From; \p To]
- /// (if \p assumption is "true") or it is fully out of this range
- /// (if \p assumption is "false").
- ///
- /// This returns a new state with the added constraint on \p cond.
- /// If no new state is feasible, NULL is returned.
- ProgramStateRef assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool assumption) const;
-
- /// Assumes given range both "true" and "false" for \p Val, and returns both
- /// corresponding states (respectively).
- ///
- /// This is more efficient than calling assume() twice. Note that one (but not
- /// both) of the returned states may be NULL.
- std::pair<ProgramStateRef, ProgramStateRef>
- assumeWithinInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From,
- const llvm::APSInt &To) const;
-
-
- /// \brief Check if the given SVal is constrained to zero or is a zero
- /// constant.
- ConditionTruthVal isNull(SVal V) const;
-
- /// Utility method for getting regions.
- const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const;
-
- //==---------------------------------------------------------------------==//
- // Binding and retrieving values to/from the environment and symbolic store.
- //==---------------------------------------------------------------------==//
-
- /// Create a new state by binding the value 'V' to the statement 'S' in the
- /// state's environment.
- ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx,
- SVal V, bool Invalidate = true) const;
-
- ProgramStateRef bindLoc(Loc location,
- SVal V,
- bool notifyChanges = true) const;
-
- ProgramStateRef bindLoc(SVal location, SVal V) const;
-
- ProgramStateRef bindDefault(SVal loc, SVal V) const;
-
- ProgramStateRef killBinding(Loc LV) const;
-
- /// \brief Returns the state with bindings for the given regions
- /// cleared from the store.
- ///
- /// Optionally invalidates global regions as well.
- ///
- /// \param Regions the set of regions to be invalidated.
- /// \param E the expression that caused the invalidation.
- /// \param BlockCount The number of times the current basic block has been
- // visited.
- /// \param CausesPointerEscape the flag is set to true when
- /// the invalidation entails escape of a symbol (representing a
- /// pointer). For example, due to it being passed as an argument in a
- /// call.
- /// \param IS the set of invalidated symbols.
- /// \param Call if non-null, the invalidated regions represent parameters to
- /// the call and should be considered directly invalidated.
- /// \param ITraits information about special handling for a particular
- /// region/symbol.
- ProgramStateRef
- invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E,
- unsigned BlockCount, const LocationContext *LCtx,
- bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
- const CallEvent *Call = nullptr,
- RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
-
- ProgramStateRef
- invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
- unsigned BlockCount, const LocationContext *LCtx,
- bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr,
- const CallEvent *Call = nullptr,
- RegionAndSymbolInvalidationTraits *ITraits = nullptr) const;
-
- /// enterStackFrame - Returns the state for entry to the given stack frame,
- /// preserving the current state.
- ProgramStateRef enterStackFrame(const CallEvent &Call,
- const StackFrameContext *CalleeCtx) const;
-
- /// Get the lvalue for a variable reference.
- Loc getLValue(const VarDecl *D, const LocationContext *LC) const;
-
- Loc getLValue(const CompoundLiteralExpr *literal,
- const LocationContext *LC) const;
-
- /// Get the lvalue for an ivar reference.
- SVal getLValue(const ObjCIvarDecl *decl, SVal base) const;
-
- /// Get the lvalue for a field reference.
- SVal getLValue(const FieldDecl *decl, SVal Base) const;
-
- /// Get the lvalue for an indirect field reference.
- SVal getLValue(const IndirectFieldDecl *decl, SVal Base) const;
-
- /// Get the lvalue for an array index.
- SVal getLValue(QualType ElementType, SVal Idx, SVal Base) const;
-
- /// Returns the SVal bound to the statement 'S' in the state's environment.
- SVal getSVal(const Stmt *S, const LocationContext *LCtx) const;
-
- SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const;
-
- /// \brief Return the value bound to the specified location.
- /// Returns UnknownVal() if none found.
- SVal getSVal(Loc LV, QualType T = QualType()) const;
-
- /// Returns the "raw" SVal bound to LV before any value simplfication.
- SVal getRawSVal(Loc LV, QualType T= QualType()) const;
-
- /// \brief Return the value bound to the specified location.
- /// Returns UnknownVal() if none found.
- SVal getSVal(const MemRegion* R) const;
-
- SVal getSValAsScalarOrLoc(const MemRegion *R) const;
-
- /// \brief Visits the symbols reachable from the given SVal using the provided
- /// SymbolVisitor.
- ///
- /// This is a convenience API. Consider using ScanReachableSymbols class
- /// directly when making multiple scans on the same state with the same
- /// visitor to avoid repeated initialization cost.
- /// \sa ScanReachableSymbols
- bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const;
-
- /// \brief Visits the symbols reachable from the SVals in the given range
- /// using the provided SymbolVisitor.
- bool scanReachableSymbols(const SVal *I, const SVal *E,
- SymbolVisitor &visitor) const;
-
- /// \brief Visits the symbols reachable from the regions in the given
- /// MemRegions range using the provided SymbolVisitor.
- bool scanReachableSymbols(const MemRegion * const *I,
- const MemRegion * const *E,
- SymbolVisitor &visitor) const;
-
- template <typename CB> CB scanReachableSymbols(SVal val) const;
- template <typename CB> CB scanReachableSymbols(const SVal *beg,
- const SVal *end) const;
-
- template <typename CB> CB
- scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const;
-
- /// Create a new state in which the statement is marked as tainted.
- ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric) const;
-
- /// Create a new state in which the symbol is marked as tainted.
- ProgramStateRef addTaint(SymbolRef S,
- TaintTagType Kind = TaintTagGeneric) const;
-
- /// Create a new state in which the region symbol is marked as tainted.
- ProgramStateRef addTaint(const MemRegion *R,
- TaintTagType Kind = TaintTagGeneric) const;
-
- /// Check if the statement is tainted in the current state.
- bool isTainted(const Stmt *S, const LocationContext *LCtx,
- TaintTagType Kind = TaintTagGeneric) const;
- bool isTainted(SVal V, TaintTagType Kind = TaintTagGeneric) const;
- bool isTainted(SymbolRef Sym, TaintTagType Kind = TaintTagGeneric) const;
- bool isTainted(const MemRegion *Reg, TaintTagType Kind=TaintTagGeneric) const;
-
- //==---------------------------------------------------------------------==//
- // Accessing the Generic Data Map (GDM).
- //==---------------------------------------------------------------------==//
-
- void *const* FindGDM(void *K) const;
-
- template<typename T>
- ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const;
-
- template <typename T>
- typename ProgramStateTrait<T>::data_type
- get() const {
- return ProgramStateTrait<T>::MakeData(FindGDM(ProgramStateTrait<T>::GDMIndex()));
- }
-
- template<typename T>
- typename ProgramStateTrait<T>::lookup_type
- get(typename ProgramStateTrait<T>::key_type key) const {
- void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
- return ProgramStateTrait<T>::Lookup(ProgramStateTrait<T>::MakeData(d), key);
- }
-
- template <typename T>
- typename ProgramStateTrait<T>::context_type get_context() const;
-
-
- template<typename T>
- ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const;
-
- template<typename T>
- ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::context_type C) const;
- template <typename T>
- ProgramStateRef remove() const;
-
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const;
-
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E) const;
-
- template<typename T>
- ProgramStateRef set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E,
- typename ProgramStateTrait<T>::context_type C) const;
-
- template<typename T>
- bool contains(typename ProgramStateTrait<T>::key_type key) const {
- void *const* d = FindGDM(ProgramStateTrait<T>::GDMIndex());
- return ProgramStateTrait<T>::Contains(ProgramStateTrait<T>::MakeData(d), key);
- }
-
- // Pretty-printing.
- void print(raw_ostream &Out, const char *nl = "\n",
- const char *sep = "") const;
- void printDOT(raw_ostream &Out) const;
- void printTaint(raw_ostream &Out, const char *nl = "\n",
- const char *sep = "") const;
-
- void dump() const;
- void dumpTaint() const;
-
-private:
- friend void ProgramStateRetain(const ProgramState *state);
- friend void ProgramStateRelease(const ProgramState *state);
-
- /// \sa invalidateValues()
- /// \sa invalidateRegions()
- ProgramStateRef
- invalidateRegionsImpl(ArrayRef<SVal> Values,
- const Expr *E, unsigned BlockCount,
- const LocationContext *LCtx,
- bool ResultsInSymbolEscape,
- InvalidatedSymbols *IS,
- RegionAndSymbolInvalidationTraits *HTraits,
- const CallEvent *Call) const;
-};
-
-//===----------------------------------------------------------------------===//
-// ProgramStateManager - Factory object for ProgramStates.
-//===----------------------------------------------------------------------===//
-
-class ProgramStateManager {
- friend class ProgramState;
- friend void ProgramStateRelease(const ProgramState *state);
-private:
- /// Eng - The SubEngine that owns this state manager.
- SubEngine *Eng; /* Can be null. */
-
- EnvironmentManager EnvMgr;
- std::unique_ptr<StoreManager> StoreMgr;
- std::unique_ptr<ConstraintManager> ConstraintMgr;
-
- ProgramState::GenericDataMap::Factory GDMFactory;
-
- typedef llvm::DenseMap<void*,std::pair<void*,void (*)(void*)> > GDMContextsTy;
- GDMContextsTy GDMContexts;
-
- /// StateSet - FoldingSet containing all the states created for analyzing
- /// a particular function. This is used to unique states.
- llvm::FoldingSet<ProgramState> StateSet;
-
- /// Object that manages the data for all created SVals.
- std::unique_ptr<SValBuilder> svalBuilder;
-
- /// Manages memory for created CallEvents.
- std::unique_ptr<CallEventManager> CallEventMgr;
-
- /// A BumpPtrAllocator to allocate states.
- llvm::BumpPtrAllocator &Alloc;
-
- /// A vector of ProgramStates that we can reuse.
- std::vector<ProgramState *> freeStates;
-
-public:
- ProgramStateManager(ASTContext &Ctx,
- StoreManagerCreator CreateStoreManager,
- ConstraintManagerCreator CreateConstraintManager,
- llvm::BumpPtrAllocator& alloc,
- SubEngine *subeng);
-
- ~ProgramStateManager();
-
- ProgramStateRef getInitialState(const LocationContext *InitLoc);
-
- ASTContext &getContext() { return svalBuilder->getContext(); }
- const ASTContext &getContext() const { return svalBuilder->getContext(); }
-
- BasicValueFactory &getBasicVals() {
- return svalBuilder->getBasicValueFactory();
- }
-
- SValBuilder &getSValBuilder() {
- return *svalBuilder;
- }
-
- SymbolManager &getSymbolManager() {
- return svalBuilder->getSymbolManager();
- }
- const SymbolManager &getSymbolManager() const {
- return svalBuilder->getSymbolManager();
- }
-
- llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
-
- MemRegionManager& getRegionManager() {
- return svalBuilder->getRegionManager();
- }
- const MemRegionManager& getRegionManager() const {
- return svalBuilder->getRegionManager();
- }
-
- CallEventManager &getCallEventManager() { return *CallEventMgr; }
-
- StoreManager& getStoreManager() { return *StoreMgr; }
- ConstraintManager& getConstraintManager() { return *ConstraintMgr; }
- SubEngine* getOwningEngine() { return Eng; }
-
- ProgramStateRef removeDeadBindings(ProgramStateRef St,
- const StackFrameContext *LCtx,
- SymbolReaper& SymReaper);
-
-public:
-
- SVal ArrayToPointer(Loc Array, QualType ElementTy) {
- return StoreMgr->ArrayToPointer(Array, ElementTy);
- }
-
- // Methods that manipulate the GDM.
- ProgramStateRef addGDM(ProgramStateRef St, void *Key, void *Data);
- ProgramStateRef removeGDM(ProgramStateRef state, void *Key);
-
- // Methods that query & manipulate the Store.
-
- void iterBindings(ProgramStateRef state, StoreManager::BindingsHandler& F) {
- StoreMgr->iterBindings(state->getStore(), F);
- }
-
- ProgramStateRef getPersistentState(ProgramState &Impl);
- ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState,
- ProgramStateRef GDMState);
-
- bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) {
- return S1->Env == S2->Env;
- }
-
- bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) {
- return S1->store == S2->store;
- }
-
- //==---------------------------------------------------------------------==//
- // Generic Data Map methods.
- //==---------------------------------------------------------------------==//
- //
- // ProgramStateManager and ProgramState support a "generic data map" that allows
- // different clients of ProgramState objects to embed arbitrary data within a
- // ProgramState object. The generic data map is essentially an immutable map
- // from a "tag" (that acts as the "key" for a client) and opaque values.
- // Tags/keys and values are simply void* values. The typical way that clients
- // generate unique tags are by taking the address of a static variable.
- // Clients are responsible for ensuring that data values referred to by a
- // the data pointer are immutable (and thus are essentially purely functional
- // data).
- //
- // The templated methods below use the ProgramStateTrait<T> class
- // to resolve keys into the GDM and to return data values to clients.
- //
-
- // Trait based GDM dispatch.
- template <typename T>
- ProgramStateRef set(ProgramStateRef st, typename ProgramStateTrait<T>::data_type D) {
- return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
- ProgramStateTrait<T>::MakeVoidPtr(D));
- }
-
- template<typename T>
- ProgramStateRef set(ProgramStateRef st,
- typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type V,
- typename ProgramStateTrait<T>::context_type C) {
-
- return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
- ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Set(st->get<T>(), K, V, C)));
- }
-
- template <typename T>
- ProgramStateRef add(ProgramStateRef st,
- typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::context_type C) {
- return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
- ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Add(st->get<T>(), K, C)));
- }
-
- template <typename T>
- ProgramStateRef remove(ProgramStateRef st,
- typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::context_type C) {
-
- return addGDM(st, ProgramStateTrait<T>::GDMIndex(),
- ProgramStateTrait<T>::MakeVoidPtr(ProgramStateTrait<T>::Remove(st->get<T>(), K, C)));
- }
-
- template <typename T>
- ProgramStateRef remove(ProgramStateRef st) {
- return removeGDM(st, ProgramStateTrait<T>::GDMIndex());
- }
-
- void *FindGDMContext(void *index,
- void *(*CreateContext)(llvm::BumpPtrAllocator&),
- void (*DeleteContext)(void*));
-
- template <typename T>
- typename ProgramStateTrait<T>::context_type get_context() {
- void *p = FindGDMContext(ProgramStateTrait<T>::GDMIndex(),
- ProgramStateTrait<T>::CreateContext,
- ProgramStateTrait<T>::DeleteContext);
-
- return ProgramStateTrait<T>::MakeContext(p);
- }
-
- void EndPath(ProgramStateRef St) {
- ConstraintMgr->EndPath(St);
- }
-};
-
-
-//===----------------------------------------------------------------------===//
-// Out-of-line method definitions for ProgramState.
-//===----------------------------------------------------------------------===//
-
-inline ConstraintManager &ProgramState::getConstraintManager() const {
- return stateMgr->getConstraintManager();
-}
-
-inline const VarRegion* ProgramState::getRegion(const VarDecl *D,
- const LocationContext *LC) const
-{
- return getStateManager().getRegionManager().getVarRegion(D, LC);
-}
-
-inline ProgramStateRef ProgramState::assume(DefinedOrUnknownSVal Cond,
- bool Assumption) const {
- if (Cond.isUnknown())
- return this;
-
- return getStateManager().ConstraintMgr
- ->assume(this, Cond.castAs<DefinedSVal>(), Assumption);
-}
-
-inline std::pair<ProgramStateRef , ProgramStateRef >
-ProgramState::assume(DefinedOrUnknownSVal Cond) const {
- if (Cond.isUnknown())
- return std::make_pair(this, this);
-
- return getStateManager().ConstraintMgr
- ->assumeDual(this, Cond.castAs<DefinedSVal>());
-}
-
-inline ProgramStateRef
-ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To,
- bool Assumption) const {
- if (Val.isUnknown())
- return this;
-
- assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
-
- return getStateManager().ConstraintMgr->assumeWithinInclusiveRange(
- this, Val.castAs<NonLoc>(), From, To, Assumption);
-}
-
-inline std::pair<ProgramStateRef, ProgramStateRef>
-ProgramState::assumeWithinInclusiveRange(DefinedOrUnknownSVal Val,
- const llvm::APSInt &From,
- const llvm::APSInt &To) const {
- if (Val.isUnknown())
- return std::make_pair(this, this);
-
- assert(Val.getAs<NonLoc>() && "Only NonLocs are supported!");
-
- return getStateManager().ConstraintMgr
- ->assumeWithinInclusiveRangeDual(this, Val.castAs<NonLoc>(), From, To);
-}
-
-inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
- if (Optional<Loc> L = LV.getAs<Loc>())
- return bindLoc(*L, V);
- return this;
-}
-
-inline Loc ProgramState::getLValue(const VarDecl *VD,
- const LocationContext *LC) const {
- return getStateManager().StoreMgr->getLValueVar(VD, LC);
-}
-
-inline Loc ProgramState::getLValue(const CompoundLiteralExpr *literal,
- const LocationContext *LC) const {
- return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC);
-}
-
-inline SVal ProgramState::getLValue(const ObjCIvarDecl *D, SVal Base) const {
- return getStateManager().StoreMgr->getLValueIvar(D, Base);
-}
-
-inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
- return getStateManager().StoreMgr->getLValueField(D, Base);
-}
-
-inline SVal ProgramState::getLValue(const IndirectFieldDecl *D,
- SVal Base) const {
- StoreManager &SM = *getStateManager().StoreMgr;
- for (const auto *I : D->chain()) {
- Base = SM.getLValueField(cast<FieldDecl>(I), Base);
- }
-
- return Base;
-}
-
-inline SVal ProgramState::getLValue(QualType ElementType, SVal Idx, SVal Base) const{
- if (Optional<NonLoc> N = Idx.getAs<NonLoc>())
- return getStateManager().StoreMgr->getLValueElement(ElementType, *N, Base);
- return UnknownVal();
-}
-
-inline SVal ProgramState::getSVal(const Stmt *Ex,
- const LocationContext *LCtx) const{
- return Env.getSVal(EnvironmentEntry(Ex, LCtx),
- *getStateManager().svalBuilder);
-}
-
-inline SVal
-ProgramState::getSValAsScalarOrLoc(const Stmt *S,
- const LocationContext *LCtx) const {
- if (const Expr *Ex = dyn_cast<Expr>(S)) {
- QualType T = Ex->getType();
- if (Ex->isGLValue() || Loc::isLocType(T) ||
- T->isIntegralOrEnumerationType())
- return getSVal(S, LCtx);
- }
-
- return UnknownVal();
-}
-
-inline SVal ProgramState::getRawSVal(Loc LV, QualType T) const {
- return getStateManager().StoreMgr->getBinding(getStore(), LV, T);
-}
-
-inline SVal ProgramState::getSVal(const MemRegion* R) const {
- return getStateManager().StoreMgr->getBinding(getStore(),
- loc::MemRegionVal(R));
-}
-
-inline BasicValueFactory &ProgramState::getBasicVals() const {
- return getStateManager().getBasicVals();
-}
-
-inline SymbolManager &ProgramState::getSymbolManager() const {
- return getStateManager().getSymbolManager();
-}
-
-template<typename T>
-ProgramStateRef ProgramState::add(typename ProgramStateTrait<T>::key_type K) const {
- return getStateManager().add<T>(this, K, get_context<T>());
-}
-
-template <typename T>
-typename ProgramStateTrait<T>::context_type ProgramState::get_context() const {
- return getStateManager().get_context<T>();
-}
-
-template<typename T>
-ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K) const {
- return getStateManager().remove<T>(this, K, get_context<T>());
-}
-
-template<typename T>
-ProgramStateRef ProgramState::remove(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::context_type C) const {
- return getStateManager().remove<T>(this, K, C);
-}
-
-template <typename T>
-ProgramStateRef ProgramState::remove() const {
- return getStateManager().remove<T>(this);
-}
-
-template<typename T>
-ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::data_type D) const {
- return getStateManager().set<T>(this, D);
-}
-
-template<typename T>
-ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E) const {
- return getStateManager().set<T>(this, K, E, get_context<T>());
-}
-
-template<typename T>
-ProgramStateRef ProgramState::set(typename ProgramStateTrait<T>::key_type K,
- typename ProgramStateTrait<T>::value_type E,
- typename ProgramStateTrait<T>::context_type C) const {
- return getStateManager().set<T>(this, K, E, C);
-}
-
-template <typename CB>
-CB ProgramState::scanReachableSymbols(SVal val) const {
- CB cb(this);
- scanReachableSymbols(val, cb);
- return cb;
-}
-
-template <typename CB>
-CB ProgramState::scanReachableSymbols(const SVal *beg, const SVal *end) const {
- CB cb(this);
- scanReachableSymbols(beg, end, cb);
- return cb;
-}
-
-template <typename CB>
-CB ProgramState::scanReachableSymbols(const MemRegion * const *beg,
- const MemRegion * const *end) const {
- CB cb(this);
- scanReachableSymbols(beg, end, cb);
- return cb;
-}
-
-/// \class ScanReachableSymbols
-/// A Utility class that allows to visit the reachable symbols using a custom
-/// SymbolVisitor.
-class ScanReachableSymbols {
- typedef llvm::DenseSet<const void*> VisitedItems;
-
- VisitedItems visited;
- ProgramStateRef state;
- SymbolVisitor &visitor;
-public:
-
- ScanReachableSymbols(ProgramStateRef st, SymbolVisitor& v)
- : state(st), visitor(v) {}
-
- bool scan(nonloc::LazyCompoundVal val);
- bool scan(nonloc::CompoundVal val);
- bool scan(SVal val);
- bool scan(const MemRegion *R);
- bool scan(const SymExpr *sym);
-};
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
deleted file mode 100644
index 6b4da7d..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
+++ /dev/null
@@ -1,245 +0,0 @@
-//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines partial implementations of template specializations of
-// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState
-// to implement set/get methods for manipulating a ProgramState's
-// generic data map.
-//
-//===----------------------------------------------------------------------===//
-
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
-
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
- template <typename K, typename D, typename I> class ImmutableMap;
- template <typename K, typename I> class ImmutableSet;
- template <typename T> class ImmutableList;
- template <typename T> class ImmutableListImpl;
-}
-
-namespace clang {
-
-namespace ento {
- template <typename T> 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<Name> \
- : public ProgramStatePartialTrait<Name ## Ty> { \
- static void *GDMIndex() { static int Index; return &Index; } \
- }; \
- } \
- }
-
-
- // Partial-specialization for ImmutableMap.
-
- template <typename Key, typename Data, typename Info>
- struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
- typedef llvm::ImmutableMap<Key,Data,Info> data_type;
- typedef typename data_type::Factory& context_type;
- typedef Key key_type;
- typedef Data value_type;
- typedef const value_type* lookup_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p)
- : data_type(nullptr);
- }
- static inline void *MakeVoidPtr(data_type B) {
- return B.getRoot();
- }
- static lookup_type Lookup(data_type B, key_type K) {
- return B.lookup(K);
- }
- static data_type Set(data_type B, key_type K, value_type E,context_type F){
- return F.add(B, K, E);
- }
-
- static data_type Remove(data_type B, key_type K, context_type F) {
- return F.remove(B, K);
- }
-
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
- }
-
- static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
- return new typename data_type::Factory(Alloc);
- }
-
- static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
- }
- };
-
- /// 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> > {
- typedef llvm::ImmutableSet<Key,Info> data_type;
- typedef typename data_type::Factory& context_type;
- typedef Key key_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((typename data_type::TreeTy*) *p)
- : data_type(nullptr);
- }
-
- static inline void *MakeVoidPtr(data_type B) {
- return B.getRoot();
- }
-
- static data_type Add(data_type B, key_type K, context_type F) {
- return F.add(B, K);
- }
-
- static data_type Remove(data_type B, key_type K, context_type F) {
- return F.remove(B, K);
- }
-
- static bool Contains(data_type B, key_type K) {
- return B.contains(K);
- }
-
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
- }
-
- static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
- return new typename data_type::Factory(Alloc);
- }
-
- static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
- }
- };
-
-
- // Partial-specialization for ImmutableList.
-
- template <typename T>
- struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
- typedef llvm::ImmutableList<T> data_type;
- typedef T key_type;
- typedef typename data_type::Factory& context_type;
-
- static data_type Add(data_type L, key_type K, context_type F) {
- return F.add(K, L);
- }
-
- static bool Contains(data_type L, key_type K) {
- return L.contains(K);
- }
-
- static inline data_type MakeData(void *const* p) {
- return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
- : data_type(nullptr);
- }
-
- static inline void *MakeVoidPtr(data_type D) {
- return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
- }
-
- static inline context_type MakeContext(void *p) {
- return *((typename data_type::Factory*) p);
- }
-
- static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
- return new typename data_type::Factory(Alloc);
- }
-
- static void DeleteContext(void *Ctx) {
- delete (typename data_type::Factory*) Ctx;
- }
- };
-
-
- // Partial specialization for bool.
- template <> struct ProgramStatePartialTrait<bool> {
- typedef bool data_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? (data_type) (uintptr_t) *p
- : data_type();
- }
- static inline void *MakeVoidPtr(data_type d) {
- return (void*) (uintptr_t) d;
- }
- };
-
- // Partial specialization for unsigned.
- template <> struct ProgramStatePartialTrait<unsigned> {
- typedef unsigned data_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? (data_type) (uintptr_t) *p
- : data_type();
- }
- static inline void *MakeVoidPtr(data_type d) {
- return (void*) (uintptr_t) d;
- }
- };
-
- // Partial specialization for void*.
- template <> struct ProgramStatePartialTrait<void*> {
- typedef void *data_type;
-
- static inline data_type MakeData(void *const* p) {
- return p ? *p
- : data_type();
- }
- static inline void *MakeVoidPtr(data_type d) {
- return d;
- }
- };
-
- // Partial specialization for const void *.
- template <> struct ProgramStatePartialTrait<const void *> {
- typedef const void *data_type;
-
- static inline data_type MakeData(void * const *p) {
- return p ? *p : data_type();
- }
-
- static inline void *MakeVoidPtr(data_type d) {
- return const_cast<void *>(d);
- }
- };
-
-} // end ento namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
deleted file mode 100644
index 415bb77..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//== ProgramState_Fwd.h - Incomplete declarations of ProgramState -*- C++ -*--=/
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H
-
-#include "clang/Basic/LLVM.h"
-#include "llvm/ADT/IntrusiveRefCntPtr.h"
-
-namespace clang {
-namespace ento {
- class ProgramState;
- class ProgramStateManager;
- void ProgramStateRetain(const ProgramState *state);
- void ProgramStateRelease(const ProgramState *state);
-}
-}
-
-namespace llvm {
- template <> struct IntrusiveRefCntPtrInfo<const clang::ento::ProgramState> {
- static void retain(const clang::ento::ProgramState *state) {
- clang::ento::ProgramStateRetain(state);
- }
- static void release(const clang::ento::ProgramState *state) {
- clang::ento::ProgramStateRelease(state);
- }
- };
-}
-
-namespace clang {
-namespace ento {
- typedef IntrusiveRefCntPtr<const ProgramState> ProgramStateRef;
-}
-}
-
-#endif
-
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
deleted file mode 100644
index a68d341..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ /dev/null
@@ -1,333 +0,0 @@
-// SValBuilder.h - Construction of SVals from evaluating expressions -*- C++ -*-
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines SValBuilder, a class that defines the interface for
-// "symbolical evaluators" which construct an SVal from an expression.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprObjC.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-
-namespace clang {
-
-class CXXBoolLiteralExpr;
-
-namespace ento {
-
-class SValBuilder {
- virtual void anchor();
-protected:
- ASTContext &Context;
-
- /// Manager of APSInt values.
- BasicValueFactory BasicVals;
-
- /// Manages the creation of symbols.
- SymbolManager SymMgr;
-
- /// Manages the creation of memory regions.
- MemRegionManager MemMgr;
-
- ProgramStateManager &StateMgr;
-
- /// The scalar type to use for array indices.
- const QualType ArrayIndexTy;
-
- /// The width of the scalar type used for array indices.
- const unsigned ArrayIndexWidth;
-
- virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0;
- virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0;
-
-public:
- // FIXME: Make these protected again once RegionStoreManager correctly
- // handles loads from different bound value types.
- virtual SVal dispatchCast(SVal val, QualType castTy) = 0;
-
-public:
- SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
- ProgramStateManager &stateMgr)
- : Context(context), BasicVals(context, alloc),
- SymMgr(context, BasicVals, alloc),
- MemMgr(context, alloc),
- StateMgr(stateMgr),
- ArrayIndexTy(context.IntTy),
- ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
-
- virtual ~SValBuilder() {}
-
- bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) {
- return haveSameType(Sym1->getType(), Sym2->getType());
- }
-
- bool haveSameType(QualType Ty1, QualType Ty2) {
- // FIXME: Remove the second disjunct when we support symbolic
- // truncation/extension.
- return (Context.getCanonicalType(Ty1) == Context.getCanonicalType(Ty2) ||
- (Ty1->isIntegralOrEnumerationType() &&
- Ty2->isIntegralOrEnumerationType()));
- }
-
- SVal evalCast(SVal val, QualType castTy, QualType originalType);
-
- virtual SVal evalMinus(NonLoc val) = 0;
-
- virtual SVal evalComplement(NonLoc val) = 0;
-
- /// Create a new value which represents a binary expression with two non-
- /// location operands.
- virtual SVal evalBinOpNN(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc lhs, NonLoc rhs, QualType resultTy) = 0;
-
- /// Create a new value which represents a binary expression with two memory
- /// location operands.
- virtual SVal evalBinOpLL(ProgramStateRef state, BinaryOperator::Opcode op,
- Loc lhs, Loc rhs, QualType resultTy) = 0;
-
- /// Create a new value which represents a binary expression with a memory
- /// location and non-location operands. For example, this would be used to
- /// evaluate a pointer arithmetic operation.
- virtual SVal evalBinOpLN(ProgramStateRef state, BinaryOperator::Opcode op,
- Loc lhs, NonLoc rhs, QualType resultTy) = 0;
-
- /// Evaluates a given SVal. If the SVal has only one possible (integer) value,
- /// that value is returned. Otherwise, returns NULL.
- virtual const llvm::APSInt *getKnownValue(ProgramStateRef state, SVal val) = 0;
-
- /// Constructs a symbolic expression for two non-location values.
- SVal makeSymExprValNN(ProgramStateRef state, BinaryOperator::Opcode op,
- NonLoc lhs, NonLoc rhs, QualType resultTy);
-
- SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op,
- SVal lhs, SVal rhs, QualType type);
-
- DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs,
- DefinedOrUnknownSVal rhs);
-
- ASTContext &getContext() { return Context; }
- const ASTContext &getContext() const { return Context; }
-
- ProgramStateManager &getStateManager() { return StateMgr; }
-
- QualType getConditionType() const {
- return Context.getLangOpts().CPlusPlus ? Context.BoolTy : Context.IntTy;
- }
-
- QualType getArrayIndexType() const {
- return ArrayIndexTy;
- }
-
- BasicValueFactory &getBasicValueFactory() { return BasicVals; }
- const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
-
- SymbolManager &getSymbolManager() { return SymMgr; }
- const SymbolManager &getSymbolManager() const { return SymMgr; }
-
- MemRegionManager &getRegionManager() { return MemMgr; }
- const MemRegionManager &getRegionManager() const { return MemMgr; }
-
- // Forwarding methods to SymbolManager.
-
- const SymbolConjured* conjureSymbol(const Stmt *stmt,
- const LocationContext *LCtx,
- QualType type,
- unsigned visitCount,
- const void *symbolTag = nullptr) {
- return SymMgr.conjureSymbol(stmt, LCtx, type, visitCount, symbolTag);
- }
-
- const SymbolConjured* conjureSymbol(const Expr *expr,
- const LocationContext *LCtx,
- unsigned visitCount,
- const void *symbolTag = nullptr) {
- return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag);
- }
-
- /// Construct an SVal representing '0' for the specified type.
- DefinedOrUnknownSVal makeZeroVal(QualType type);
-
- /// Make a unique symbol for value of region.
- DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region);
-
- /// \brief Create a new symbol with a unique 'name'.
- ///
- /// We resort to conjured symbols when we cannot construct a derived symbol.
- /// The advantage of symbols derived/built from other symbols is that we
- /// preserve the relation between related(or even equivalent) expressions, so
- /// conjured symbols should be used sparingly.
- DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
- const Expr *expr,
- const LocationContext *LCtx,
- unsigned count);
- DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag,
- const Expr *expr,
- const LocationContext *LCtx,
- QualType type,
- unsigned count);
-
- DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt,
- const LocationContext *LCtx,
- QualType type,
- unsigned visitCount);
- /// \brief Conjure a symbol representing heap allocated memory region.
- ///
- /// Note, the expression should represent a location.
- DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
- const LocationContext *LCtx,
- unsigned Count);
-
- DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
- SymbolRef parentSymbol, const TypedValueRegion *region);
-
- DefinedSVal getMetadataSymbolVal(
- const void *symbolTag, const MemRegion *region,
- const Expr *expr, QualType type, unsigned count);
-
- DefinedSVal getFunctionPointer(const FunctionDecl *func);
-
- DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
- const LocationContext *locContext,
- unsigned blockCount);
-
- /// Returns the value of \p E, if it can be determined in a non-path-sensitive
- /// manner.
- ///
- /// If \p E is not a constant or cannot be modeled, returns \c None.
- Optional<SVal> getConstantVal(const Expr *E);
-
- NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) {
- return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals));
- }
-
- NonLoc makeLazyCompoundVal(const StoreRef &store,
- const TypedValueRegion *region) {
- return nonloc::LazyCompoundVal(
- BasicVals.getLazyCompoundValData(store, region));
- }
-
- NonLoc makeZeroArrayIndex() {
- return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));
- }
-
- NonLoc makeArrayIndex(uint64_t idx) {
- return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy));
- }
-
- SVal convertToArrayIndex(SVal val);
-
- nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) {
- return nonloc::ConcreteInt(
- BasicVals.getValue(integer->getValue(),
- integer->getType()->isUnsignedIntegerOrEnumerationType()));
- }
-
- nonloc::ConcreteInt makeBoolVal(const ObjCBoolLiteralExpr *boolean) {
- return makeTruthVal(boolean->getValue(), boolean->getType());
- }
-
- nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean);
-
- nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) {
- return nonloc::ConcreteInt(BasicVals.getValue(integer));
- }
-
- loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) {
- return loc::ConcreteInt(BasicVals.getValue(integer));
- }
-
- NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) {
- return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned));
- }
-
- DefinedSVal makeIntVal(uint64_t integer, QualType type) {
- if (Loc::isLocType(type))
- return loc::ConcreteInt(BasicVals.getValue(integer, type));
-
- return nonloc::ConcreteInt(BasicVals.getValue(integer, type));
- }
-
- NonLoc makeIntVal(uint64_t integer, bool isUnsigned) {
- return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned));
- }
-
- NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) {
- return nonloc::ConcreteInt(
- BasicVals.getIntWithPtrWidth(integer, isUnsigned));
- }
-
- NonLoc makeLocAsInteger(Loc loc, unsigned bits) {
- return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits));
- }
-
- NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& rhs, QualType type);
-
- NonLoc makeNonLoc(const llvm::APSInt& rhs, BinaryOperator::Opcode op,
- const SymExpr *lhs, QualType type);
-
- NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
- const SymExpr *rhs, QualType type);
-
- /// \brief Create a NonLoc value for cast.
- NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy);
-
- nonloc::ConcreteInt makeTruthVal(bool b, QualType type) {
- return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type));
- }
-
- nonloc::ConcreteInt makeTruthVal(bool b) {
- return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
- }
-
- Loc makeNull() {
- return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
- }
-
- Loc makeLoc(SymbolRef sym) {
- return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
- }
-
- Loc makeLoc(const MemRegion* region) {
- return loc::MemRegionVal(region);
- }
-
- Loc makeLoc(const AddrLabelExpr *expr) {
- return loc::GotoLabel(expr->getLabel());
- }
-
- Loc makeLoc(const llvm::APSInt& integer) {
- return loc::ConcreteInt(BasicVals.getValue(integer));
- }
-
- /// Return a memory region for the 'this' object reference.
- loc::MemRegionVal getCXXThis(const CXXMethodDecl *D,
- const StackFrameContext *SFC);
-
- /// Return a memory region for the 'this' object reference.
- loc::MemRegionVal getCXXThis(const CXXRecordDecl *D,
- const StackFrameContext *SFC);
-};
-
-SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc,
- ASTContext &context,
- ProgramStateManager &stateMgr);
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
deleted file mode 100644
index 642e11a..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
+++ /dev/null
@@ -1,574 +0,0 @@
-//== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines SVal, Loc, and NonLoc, classes that represent
-// abstract r-values for use with path-sensitive value tracking.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H
-
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "llvm/ADT/ImmutableList.h"
-
-//==------------------------------------------------------------------------==//
-// Base SVal types.
-//==------------------------------------------------------------------------==//
-
-namespace clang {
-
-namespace ento {
-
-class CompoundValData;
-class LazyCompoundValData;
-class ProgramState;
-class BasicValueFactory;
-class MemRegion;
-class TypedValueRegion;
-class MemRegionManager;
-class ProgramStateManager;
-class SValBuilder;
-
-/// SVal - This represents a symbolic expression, which can be either
-/// an L-value or an R-value.
-///
-class SVal {
-public:
- enum BaseKind {
- // The enumerators must be representable using 2 bits.
- UndefinedKind = 0, // for subclass UndefinedVal (an uninitialized value)
- UnknownKind = 1, // for subclass UnknownVal (a void value)
- LocKind = 2, // for subclass Loc (an L-value)
- NonLocKind = 3 // for subclass NonLoc (an R-value that's not
- // an L-value)
- };
- enum { BaseBits = 2, BaseMask = 0x3 };
-
-protected:
- const void *Data;
-
- /// The lowest 2 bits are a BaseKind (0 -- 3).
- /// The higher bits are an unsigned "kind" value.
- unsigned Kind;
-
- explicit SVal(const void *d, bool isLoc, unsigned ValKind)
- : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {}
-
- explicit SVal(BaseKind k, const void *D = nullptr)
- : Data(D), Kind(k) {}
-
-public:
- explicit SVal() : Data(nullptr), Kind(0) {}
-
- /// \brief Convert to the specified SVal type, asserting that this SVal is of
- /// the desired type.
- template<typename T>
- T castAs() const {
- assert(T::isKind(*this));
- T t;
- SVal& sv = t;
- sv = *this;
- return t;
- }
-
- /// \brief Convert to the specified SVal type, returning None if this SVal is
- /// not of the desired type.
- template<typename T>
- Optional<T> getAs() const {
- if (!T::isKind(*this))
- return None;
- T t;
- SVal& sv = t;
- sv = *this;
- return t;
- }
-
- /// BufferTy - A temporary buffer to hold a set of SVals.
- typedef SmallVector<SVal,5> BufferTy;
-
- inline unsigned getRawKind() const { return Kind; }
- inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); }
- inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; }
-
- // This method is required for using SVal in a FoldingSetNode. It
- // extracts a unique signature for this SVal object.
- inline void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.AddInteger((unsigned) getRawKind());
- ID.AddPointer(Data);
- }
-
- inline bool operator==(const SVal& R) const {
- return getRawKind() == R.getRawKind() && Data == R.Data;
- }
-
- inline bool operator!=(const SVal& R) const {
- return !(*this == R);
- }
-
- inline bool isUnknown() const {
- return getRawKind() == UnknownKind;
- }
-
- inline bool isUndef() const {
- return getRawKind() == UndefinedKind;
- }
-
- inline bool isUnknownOrUndef() const {
- return getRawKind() <= UnknownKind;
- }
-
- inline bool isValid() const {
- return getRawKind() > UnknownKind;
- }
-
- bool isConstant() const;
-
- bool isConstant(int I) const;
-
- bool isZeroConstant() const;
-
- /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
- bool hasConjuredSymbol() const;
-
- /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
- /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl.
- /// Otherwise return 0.
- const FunctionDecl *getAsFunctionDecl() const;
-
- /// \brief If this SVal is a location and wraps a symbol, return that
- /// SymbolRef. Otherwise return 0.
- ///
- /// Casts are ignored during lookup.
- /// \param IncludeBaseRegions The boolean that controls whether the search
- /// should continue to the base regions if the region is not symbolic.
- SymbolRef getAsLocSymbol(bool IncludeBaseRegions = false) const;
-
- /// Get the symbol in the SVal or its base region.
- SymbolRef getLocSymbolInBase() const;
-
- /// \brief If this SVal wraps a symbol return that SymbolRef.
- /// Otherwise, return 0.
- ///
- /// Casts are ignored during lookup.
- /// \param IncludeBaseRegions The boolean that controls whether the search
- /// should continue to the base regions if the region is not symbolic.
- SymbolRef getAsSymbol(bool IncludeBaseRegions = false) const;
-
- /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
- /// return that expression. Otherwise return NULL.
- const SymExpr *getAsSymbolicExpression() const;
-
- const SymExpr* getAsSymExpr() const;
-
- const MemRegion *getAsRegion() const;
-
- void dumpToStream(raw_ostream &OS) const;
- void dump() const;
-
- SymExpr::symbol_iterator symbol_begin() const {
- const SymExpr *SE = getAsSymbolicExpression();
- if (SE)
- return SE->symbol_begin();
- else
- return SymExpr::symbol_iterator();
- }
-
- SymExpr::symbol_iterator symbol_end() const {
- return SymExpr::symbol_end();
- }
-};
-
-
-class UndefinedVal : public SVal {
-public:
- UndefinedVal() : SVal(UndefinedKind) {}
-
-private:
- friend class SVal;
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == UndefinedKind;
- }
-};
-
-class DefinedOrUnknownSVal : public SVal {
-private:
- // We want calling these methods to be a compiler error since they are
- // tautologically false.
- bool isUndef() const = delete;
- bool isValid() const = delete;
-
-protected:
- DefinedOrUnknownSVal() {}
- explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind)
- : SVal(d, isLoc, ValKind) {}
-
- explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr)
- : SVal(k, D) {}
-
-private:
- friend class SVal;
- static bool isKind(const SVal& V) {
- return !V.isUndef();
- }
-};
-
-class UnknownVal : public DefinedOrUnknownSVal {
-public:
- explicit UnknownVal() : DefinedOrUnknownSVal(UnknownKind) {}
-
-private:
- friend class SVal;
- static bool isKind(const SVal &V) {
- return V.getBaseKind() == UnknownKind;
- }
-};
-
-class DefinedSVal : public DefinedOrUnknownSVal {
-private:
- // We want calling these methods to be a compiler error since they are
- // tautologically true/false.
- bool isUnknown() const = delete;
- bool isUnknownOrUndef() const = delete;
- bool isValid() const = delete;
-protected:
- DefinedSVal() {}
- explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind)
- : DefinedOrUnknownSVal(d, isLoc, ValKind) {}
-private:
- friend class SVal;
- static bool isKind(const SVal& V) {
- return !V.isUnknownOrUndef();
- }
-};
-
-
-/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
-class KnownSVal : public SVal {
- KnownSVal() {}
- friend class SVal;
- static bool isKind(const SVal &V) {
- return !V.isUnknown();
- }
-public:
- KnownSVal(const DefinedSVal &V) : SVal(V) {}
- KnownSVal(const UndefinedVal &V) : SVal(V) {}
-};
-
-class NonLoc : public DefinedSVal {
-protected:
- NonLoc() {}
- explicit NonLoc(unsigned SubKind, const void *d)
- : DefinedSVal(d, false, SubKind) {}
-
-public:
- void dumpToStream(raw_ostream &Out) const;
-
-private:
- friend class SVal;
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind;
- }
-};
-
-class Loc : public DefinedSVal {
-protected:
- Loc() {}
- explicit Loc(unsigned SubKind, const void *D)
- : DefinedSVal(const_cast<void*>(D), true, SubKind) {}
-
-public:
- void dumpToStream(raw_ostream &Out) const;
-
- static inline bool isLocType(QualType T) {
- return T->isAnyPointerType() || T->isBlockPointerType() ||
- T->isReferenceType() || T->isNullPtrType();
- }
-
-private:
- friend class SVal;
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == LocKind;
- }
-};
-
-//==------------------------------------------------------------------------==//
-// Subclasses of NonLoc.
-//==------------------------------------------------------------------------==//
-
-namespace nonloc {
-
-enum Kind { ConcreteIntKind, SymbolValKind,
- LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
-
-/// \brief Represents symbolic expression.
-class SymbolVal : public NonLoc {
-public:
- SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {}
-
- SymbolRef getSymbol() const {
- return (const SymExpr*) Data;
- }
-
- bool isExpression() const {
- return !isa<SymbolData>(getSymbol());
- }
-
-private:
- friend class SVal;
- SymbolVal() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind &&
- V.getSubKind() == SymbolValKind;
- }
-
- static bool isKind(const NonLoc& V) {
- return V.getSubKind() == SymbolValKind;
- }
-};
-
-/// \brief Value representing integer constant.
-class ConcreteInt : public NonLoc {
-public:
- explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {}
-
- const llvm::APSInt& getValue() const {
- return *static_cast<const llvm::APSInt*>(Data);
- }
-
- // Transfer functions for binary/unary operations on ConcreteInts.
- SVal evalBinOp(SValBuilder &svalBuilder, BinaryOperator::Opcode Op,
- const ConcreteInt& R) const;
-
- ConcreteInt evalComplement(SValBuilder &svalBuilder) const;
-
- ConcreteInt evalMinus(SValBuilder &svalBuilder) const;
-
-private:
- friend class SVal;
- ConcreteInt() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind &&
- V.getSubKind() == ConcreteIntKind;
- }
-
- static bool isKind(const NonLoc& V) {
- return V.getSubKind() == ConcreteIntKind;
- }
-};
-
-class LocAsInteger : public NonLoc {
- friend class ento::SValBuilder;
-
- explicit LocAsInteger(const std::pair<SVal, uintptr_t> &data)
- : NonLoc(LocAsIntegerKind, &data) {
- assert (data.first.getAs<Loc>());
- }
-
-public:
-
- Loc getLoc() const {
- const std::pair<SVal, uintptr_t> *D =
- static_cast<const std::pair<SVal, uintptr_t> *>(Data);
- return D->first.castAs<Loc>();
- }
-
- Loc getPersistentLoc() const {
- const std::pair<SVal, uintptr_t> *D =
- static_cast<const std::pair<SVal, uintptr_t> *>(Data);
- const SVal& V = D->first;
- return V.castAs<Loc>();
- }
-
- unsigned getNumBits() const {
- const std::pair<SVal, uintptr_t> *D =
- static_cast<const std::pair<SVal, uintptr_t> *>(Data);
- return D->second;
- }
-
-private:
- friend class SVal;
- LocAsInteger() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind &&
- V.getSubKind() == LocAsIntegerKind;
- }
-
- static bool isKind(const NonLoc& V) {
- return V.getSubKind() == LocAsIntegerKind;
- }
-};
-
-class CompoundVal : public NonLoc {
- friend class ento::SValBuilder;
-
- explicit CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
-
-public:
- const CompoundValData* getValue() const {
- return static_cast<const CompoundValData*>(Data);
- }
-
- typedef llvm::ImmutableList<SVal>::iterator iterator;
- iterator begin() const;
- iterator end() const;
-
-private:
- friend class SVal;
- CompoundVal() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind;
- }
-
- static bool isKind(const NonLoc& V) {
- return V.getSubKind() == CompoundValKind;
- }
-};
-
-class LazyCompoundVal : public NonLoc {
- friend class ento::SValBuilder;
-
- explicit LazyCompoundVal(const LazyCompoundValData *D)
- : NonLoc(LazyCompoundValKind, D) {}
-public:
- const LazyCompoundValData *getCVData() const {
- return static_cast<const LazyCompoundValData*>(Data);
- }
- const void *getStore() const;
- const TypedValueRegion *getRegion() const;
-
-private:
- friend class SVal;
- LazyCompoundVal() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == NonLocKind &&
- V.getSubKind() == LazyCompoundValKind;
- }
- static bool isKind(const NonLoc& V) {
- return V.getSubKind() == LazyCompoundValKind;
- }
-};
-
-} // end namespace ento::nonloc
-
-//==------------------------------------------------------------------------==//
-// Subclasses of Loc.
-//==------------------------------------------------------------------------==//
-
-namespace loc {
-
-enum Kind { GotoLabelKind, MemRegionKind, ConcreteIntKind };
-
-class GotoLabel : public Loc {
-public:
- explicit GotoLabel(LabelDecl *Label) : Loc(GotoLabelKind, Label) {}
-
- const LabelDecl *getLabel() const {
- return static_cast<const LabelDecl*>(Data);
- }
-
-private:
- friend class SVal;
- GotoLabel() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind;
- }
-
- static bool isKind(const Loc& V) {
- return V.getSubKind() == GotoLabelKind;
- }
-};
-
-
-class MemRegionVal : public Loc {
-public:
- explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
-
- /// \brief Get the underlining region.
- const MemRegion* getRegion() const {
- return static_cast<const MemRegion*>(Data);
- }
-
- /// \brief Get the underlining region and strip casts.
- const MemRegion* stripCasts(bool StripBaseCasts = true) const;
-
- template <typename REGION>
- const REGION* getRegionAs() const {
- return dyn_cast<REGION>(getRegion());
- }
-
- inline bool operator==(const MemRegionVal& R) const {
- return getRegion() == R.getRegion();
- }
-
- inline bool operator!=(const MemRegionVal& R) const {
- return getRegion() != R.getRegion();
- }
-
-private:
- friend class SVal;
- MemRegionVal() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == LocKind &&
- V.getSubKind() == MemRegionKind;
- }
-
- static bool isKind(const Loc& V) {
- return V.getSubKind() == MemRegionKind;
- }
-};
-
-class ConcreteInt : public Loc {
-public:
- explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {}
-
- const llvm::APSInt& getValue() const {
- return *static_cast<const llvm::APSInt*>(Data);
- }
-
- // Transfer functions for binary/unary operations on ConcreteInts.
- SVal evalBinOp(BasicValueFactory& BasicVals, BinaryOperator::Opcode Op,
- const ConcreteInt& R) const;
-
-private:
- friend class SVal;
- ConcreteInt() {}
- static bool isKind(const SVal& V) {
- return V.getBaseKind() == LocKind &&
- V.getSubKind() == ConcreteIntKind;
- }
-
- static bool isKind(const Loc& V) {
- return V.getSubKind() == ConcreteIntKind;
- }
-};
-
-} // end ento::loc namespace
-
-} // end ento namespace
-
-} // end clang namespace
-
-namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- clang::ento::SVal V) {
- V.dumpToStream(os);
- return os;
-}
-
-template <typename T> struct isPodLike;
-template <> struct isPodLike<clang::ento::SVal> {
- static const bool value = true;
-};
-
-} // end llvm namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
deleted file mode 100644
index a03b630..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
+++ /dev/null
@@ -1,288 +0,0 @@
-//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defined the types Store and StoreManager.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Optional.h"
-
-namespace clang {
-
-class Stmt;
-class Expr;
-class ObjCIvarDecl;
-class CXXBasePath;
-class StackFrameContext;
-
-namespace ento {
-
-class CallEvent;
-class ProgramState;
-class ProgramStateManager;
-class ScanReachableSymbols;
-
-typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols;
-
-class StoreManager {
-protected:
- SValBuilder &svalBuilder;
- ProgramStateManager &StateMgr;
-
- /// MRMgr - Manages region objects associated with this StoreManager.
- MemRegionManager &MRMgr;
- ASTContext &Ctx;
-
- StoreManager(ProgramStateManager &stateMgr);
-
-public:
- virtual ~StoreManager() {}
-
- /// Return the value bound to specified location in a given state.
- /// \param[in] store The analysis state.
- /// \param[in] loc The symbolic memory location.
- /// \param[in] T An optional type that provides a hint indicating the
- /// expected type of the returned value. This is used if the value is
- /// lazily computed.
- /// \return The value bound to the location \c loc.
- virtual SVal getBinding(Store store, Loc loc, QualType T = QualType()) = 0;
-
- /// Return a state with the specified value bound to the given location.
- /// \param[in] store The analysis state.
- /// \param[in] loc The symbolic memory location.
- /// \param[in] val The value to bind to location \c loc.
- /// \return A pointer to a ProgramState object that contains the same
- /// bindings as \c state with the addition of having the value specified
- /// by \c val bound to the location given for \c loc.
- virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0;
-
- virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V);
-
- /// \brief Create a new store with the specified binding removed.
- /// \param ST the original store, that is the basis for the new store.
- /// \param L the location whose binding should be removed.
- virtual StoreRef killBinding(Store ST, Loc L) = 0;
-
- /// getInitialStore - Returns the initial "empty" store representing the
- /// value bindings upon entry to an analyzed function.
- virtual StoreRef getInitialStore(const LocationContext *InitLoc) = 0;
-
- /// getRegionManager - Returns the internal RegionManager object that is
- /// used to query and manipulate MemRegion objects.
- MemRegionManager& getRegionManager() { return MRMgr; }
-
- virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) {
- return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC));
- }
-
- Loc getLValueCompoundLiteral(const CompoundLiteralExpr *CL,
- const LocationContext *LC) {
- return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC));
- }
-
- virtual SVal getLValueIvar(const ObjCIvarDecl *decl, SVal base);
-
- virtual SVal getLValueField(const FieldDecl *D, SVal Base) {
- return getLValueFieldOrIvar(D, Base);
- }
-
- virtual SVal getLValueElement(QualType elementType, NonLoc offset, SVal Base);
-
- // FIXME: This should soon be eliminated altogether; clients should deal with
- // region extents directly.
- virtual DefinedOrUnknownSVal getSizeInElements(ProgramStateRef state,
- const MemRegion *region,
- QualType EleTy) {
- return UnknownVal();
- }
-
- /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit
- /// conversions between arrays and pointers.
- virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0;
-
- /// Evaluates a chain of derived-to-base casts through the path specified in
- /// \p Cast.
- SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast);
-
- /// Evaluates a chain of derived-to-base casts through the specified path.
- SVal evalDerivedToBase(SVal Derived, const CXXBasePath &CastPath);
-
- /// Evaluates a derived-to-base cast through a single level of derivation.
- SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType,
- bool IsVirtual);
-
- /// \brief Evaluates C++ dynamic_cast cast.
- /// The callback may result in the following 3 scenarios:
- /// - Successful cast (ex: derived is subclass of base).
- /// - Failed cast (ex: derived is definitely not a subclass of base).
- /// - We don't know (base is a symbolic region and we don't have
- /// enough info to determine if the cast will succeed at run time).
- /// The function returns an SVal representing the derived class; it's
- /// valid only if Failed flag is set to false.
- SVal evalDynamicCast(SVal Base, QualType DerivedPtrType, bool &Failed);
-
- const ElementRegion *GetElementZeroRegion(const MemRegion *R, QualType T);
-
- /// castRegion - Used by ExprEngine::VisitCast to handle casts from
- /// a MemRegion* to a specific location type. 'R' is the region being
- /// casted and 'CastToTy' the result type of the cast.
- const MemRegion *castRegion(const MemRegion *region, QualType CastToTy);
-
- virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
- SymbolReaper& SymReaper) = 0;
-
- virtual bool includedInBindings(Store store,
- const MemRegion *region) const = 0;
-
- /// If the StoreManager supports it, increment the reference count of
- /// the specified Store object.
- virtual void incrementReferenceCount(Store store) {}
-
- /// If the StoreManager supports it, decrement the reference count of
- /// the specified Store object. If the reference count hits 0, the memory
- /// associated with the object is recycled.
- virtual void decrementReferenceCount(Store store) {}
-
- typedef SmallVector<const MemRegion *, 8> InvalidatedRegions;
-
- /// invalidateRegions - Clears out the specified regions from the store,
- /// marking their values as unknown. Depending on the store, this may also
- /// invalidate additional regions that may have changed based on accessing
- /// the given regions. Optionally, invalidates non-static globals as well.
- /// \param[in] store The initial store
- /// \param[in] Values The values to invalidate.
- /// \param[in] E The current statement being evaluated. Used to conjure
- /// symbols to mark the values of invalidated regions.
- /// \param[in] Count The current block count. Used to conjure
- /// symbols to mark the values of invalidated regions.
- /// \param[in] Call The call expression which will be used to determine which
- /// globals should get invalidated.
- /// \param[in,out] IS A set to fill with any symbols that are no longer
- /// accessible. Pass \c NULL if this information will not be used.
- /// \param[in] ITraits Information about invalidation for a particular
- /// region/symbol.
- /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
- //// explicitly being invalidated. Pass \c NULL if this
- /// information will not be used.
- /// \param[in,out] Invalidated A vector to fill with any regions being
- /// invalidated. This should include any regions explicitly invalidated
- /// even if they do not currently have bindings. Pass \c NULL if this
- /// information will not be used.
- virtual StoreRef invalidateRegions(Store store,
- ArrayRef<SVal> Values,
- const Expr *E, unsigned Count,
- const LocationContext *LCtx,
- const CallEvent *Call,
- InvalidatedSymbols &IS,
- RegionAndSymbolInvalidationTraits &ITraits,
- InvalidatedRegions *InvalidatedTopLevel,
- InvalidatedRegions *Invalidated) = 0;
-
- /// enterStackFrame - Let the StoreManager to do something when execution
- /// engine is about to execute into a callee.
- StoreRef enterStackFrame(Store store,
- const CallEvent &Call,
- const StackFrameContext *CalleeCtx);
-
- /// Finds the transitive closure of symbols within the given region.
- ///
- /// Returns false if the visitor aborted the scan.
- virtual bool scanReachableSymbols(Store S, const MemRegion *R,
- ScanReachableSymbols &Visitor) = 0;
-
- virtual void print(Store store, raw_ostream &Out,
- const char* nl, const char *sep) = 0;
-
- class BindingsHandler {
- public:
- virtual ~BindingsHandler();
- virtual bool HandleBinding(StoreManager& SMgr, Store store,
- const MemRegion *region, SVal val) = 0;
- };
-
- class FindUniqueBinding :
- public BindingsHandler {
- SymbolRef Sym;
- const MemRegion* Binding;
- bool First;
-
- public:
- FindUniqueBinding(SymbolRef sym)
- : Sym(sym), Binding(nullptr), First(true) {}
-
- bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R,
- SVal val) override;
- explicit operator bool() { return First && Binding; }
- const MemRegion *getRegion() { return Binding; }
- };
-
- /// iterBindings - Iterate over the bindings in the Store.
- virtual void iterBindings(Store store, BindingsHandler& f) = 0;
-
-protected:
- const MemRegion *MakeElementRegion(const MemRegion *baseRegion,
- QualType pointeeTy, uint64_t index = 0);
-
- /// CastRetrievedVal - Used by subclasses of StoreManager to implement
- /// implicit casts that arise from loads from regions that are reinterpreted
- /// as another region.
- SVal CastRetrievedVal(SVal val, const TypedValueRegion *region,
- QualType castTy, bool performTestOnly = true);
-
-private:
- SVal getLValueFieldOrIvar(const Decl *decl, SVal base);
-};
-
-
-inline StoreRef::StoreRef(Store store, StoreManager & smgr)
- : store(store), mgr(smgr) {
- if (store)
- mgr.incrementReferenceCount(store);
-}
-
-inline StoreRef::StoreRef(const StoreRef &sr)
- : store(sr.store), mgr(sr.mgr)
-{
- if (store)
- mgr.incrementReferenceCount(store);
-}
-
-inline StoreRef::~StoreRef() {
- if (store)
- mgr.decrementReferenceCount(store);
-}
-
-inline StoreRef &StoreRef::operator=(StoreRef const &newStore) {
- assert(&newStore.mgr == &mgr);
- if (store != newStore.store) {
- mgr.incrementReferenceCount(newStore.store);
- mgr.decrementReferenceCount(store);
- store = newStore.getStore();
- }
- return *this;
-}
-
-// FIXME: Do we need to pass ProgramStateManager anymore?
-std::unique_ptr<StoreManager>
-CreateRegionStoreManager(ProgramStateManager &StMgr);
-std::unique_ptr<StoreManager>
-CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr);
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
deleted file mode 100644
index 958c8c3..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defined the type StoreRef.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H
-
-#include <cassert>
-
-namespace clang {
-namespace ento {
-
-/// Store - This opaque type encapsulates an immutable mapping from
-/// locations to values. At a high-level, it represents the symbolic
-/// memory model. Different subclasses of StoreManager may choose
-/// different types to represent the locations and values.
-typedef const void *Store;
-
-class StoreManager;
-
-class StoreRef {
- Store store;
- StoreManager &mgr;
-public:
- StoreRef(Store, StoreManager &);
- StoreRef(const StoreRef &);
- StoreRef &operator=(StoreRef const &);
-
- bool operator==(const StoreRef &x) const {
- assert(&mgr == &x.mgr);
- return x.store == store;
- }
- bool operator!=(const StoreRef &x) const { return !operator==(x); }
-
- ~StoreRef();
-
- Store getStore() const { return store; }
- const StoreManager &getStoreManager() const { return mgr; }
-};
-
-}}
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
deleted file mode 100644
index 741ba0e..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h
+++ /dev/null
@@ -1,162 +0,0 @@
-//== SubEngine.h - Interface of the subengine of CoreEngine --------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the interface of a subengine of the CoreEngine.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H
-
-#include "clang/Analysis/ProgramPoint.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
-
-namespace clang {
-
-class CFGBlock;
-class CFGElement;
-class LocationContext;
-class Stmt;
-
-namespace ento {
-
-struct NodeBuilderContext;
-class AnalysisManager;
-class ExplodedNodeSet;
-class ExplodedNode;
-class ProgramState;
-class ProgramStateManager;
-class BlockCounter;
-class BranchNodeBuilder;
-class IndirectGotoNodeBuilder;
-class SwitchNodeBuilder;
-class EndOfFunctionNodeBuilder;
-class NodeBuilderWithSinks;
-class MemRegion;
-
-class SubEngine {
- virtual void anchor();
-public:
- virtual ~SubEngine() {}
-
- virtual ProgramStateRef getInitialState(const LocationContext *InitLoc) = 0;
-
- virtual AnalysisManager &getAnalysisManager() = 0;
-
- virtual ProgramStateManager &getStateManager() = 0;
-
- /// Called by CoreEngine. Used to generate new successor
- /// nodes by processing the 'effects' of a block-level statement.
- virtual void processCFGElement(const CFGElement E, ExplodedNode* Pred,
- unsigned StmtIdx, NodeBuilderContext *Ctx)=0;
-
- /// Called by CoreEngine when it starts processing a CFGBlock. The
- /// SubEngine is expected to populate dstNodes with new nodes representing
- /// updated analysis state, or generate no nodes at all if it doesn't.
- virtual void processCFGBlockEntrance(const BlockEdge &L,
- NodeBuilderWithSinks &nodeBuilder,
- ExplodedNode *Pred) = 0;
-
- /// Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a branch condition.
- virtual void processBranch(const Stmt *Condition, const Stmt *Term,
- NodeBuilderContext& BuilderCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) = 0;
-
- /// Called by CoreEngine.
- /// Used to generate successor nodes for temporary destructors depending
- /// on whether the corresponding constructor was visited.
- virtual void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE,
- NodeBuilderContext &BldCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) = 0;
-
- /// Called by CoreEngine. Used to processing branching behavior
- /// at static initalizers.
- virtual void processStaticInitializer(const DeclStmt *DS,
- NodeBuilderContext& BuilderCtx,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst,
- const CFGBlock *DstT,
- const CFGBlock *DstF) = 0;
-
- /// Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a computed goto jump.
- virtual void processIndirectGoto(IndirectGotoNodeBuilder& builder) = 0;
-
- /// Called by CoreEngine. Used to generate successor
- /// nodes by processing the 'effects' of a switch statement.
- virtual void processSwitch(SwitchNodeBuilder& builder) = 0;
-
- /// Called by CoreEngine. Used to generate end-of-path
- /// nodes when the control reaches the end of a function.
- virtual void processEndOfFunction(NodeBuilderContext& BC,
- ExplodedNode *Pred) = 0;
-
- // Generate the entry node of the callee.
- virtual void processCallEnter(CallEnter CE, ExplodedNode *Pred) = 0;
-
- // Generate the first post callsite node.
- virtual void processCallExit(ExplodedNode *Pred) = 0;
-
- /// Called by ConstraintManager. Used to call checker-specific
- /// logic for handling assumptions on symbolic values.
- virtual ProgramStateRef processAssume(ProgramStateRef state,
- SVal cond, bool assumption) = 0;
-
- /// wantsRegionChangeUpdate - Called by ProgramStateManager to determine if a
- /// region change should trigger a processRegionChanges update.
- virtual bool wantsRegionChangeUpdate(ProgramStateRef state) = 0;
-
- /// processRegionChanges - Called by ProgramStateManager whenever a change is
- /// made to the store. Used to update checkers that track region values.
- virtual ProgramStateRef
- processRegionChanges(ProgramStateRef state,
- const InvalidatedSymbols *invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call) = 0;
-
-
- inline ProgramStateRef
- processRegionChange(ProgramStateRef state,
- const MemRegion* MR) {
- return processRegionChanges(state, nullptr, MR, MR, nullptr);
- }
-
- virtual ProgramStateRef
- processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
-
- virtual ProgramStateRef
- notifyCheckersOfPointerEscape(ProgramStateRef State,
- const InvalidatedSymbols *Invalidated,
- ArrayRef<const MemRegion *> ExplicitRegions,
- ArrayRef<const MemRegion *> Regions,
- const CallEvent *Call,
- RegionAndSymbolInvalidationTraits &HTraits) = 0;
-
- /// printState - Called by ProgramStateManager to print checker-specific data.
- virtual void printState(raw_ostream &Out, ProgramStateRef State,
- const char *NL, const char *Sep) = 0;
-
- /// Called by CoreEngine when the analysis worklist is either empty or the
- // maximum number of analysis steps have been reached.
- virtual void processEndWorklist(bool hasWorkRemaining) = 0;
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
deleted file mode 100644
index ed87851..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SummaryManager.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//== SummaryManager.h - Generic handling of function summaries --*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines SummaryManager and related classes, which provides
-// a generic mechanism for managing function summaries.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_GR_SUMMARY
-#define LLVM_CLANG_GR_SUMMARY
-
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/Support/Allocator.h"
-
-namespace clang {
-
-namespace ento {
-
-namespace summMgr {
-
-
-/* Key kinds:
-
- - C functions
- - C++ functions (name + parameter types)
- - ObjC methods:
- - Class, selector (class method)
- - Class, selector (instance method)
- - Category, selector (instance method)
- - Protocol, selector (instance method)
- - C++ methods
- - Class, function name + parameter types + const
- */
-
-class SummaryKey {
-
-};
-
-} // end namespace clang::summMgr
-
-class SummaryManagerImpl {
-
-};
-
-
-template <typename T>
-class SummaryManager : SummaryManagerImpl {
-
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
deleted file mode 100644
index 9dbfab2..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ /dev/null
@@ -1,681 +0,0 @@
-//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines SymbolManager, a class that manages symbolic values
-// created for use by ExprEngine and related classes.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H
-
-#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
-#include "clang/Analysis/AnalysisContext.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DataTypes.h"
-
-namespace clang {
- class ASTContext;
- class StackFrameContext;
-
-namespace ento {
- class BasicValueFactory;
- class MemRegion;
- class SubRegion;
- class TypedValueRegion;
- class VarRegion;
-
-/// \brief Symbolic value. These values used to capture symbolic execution of
-/// the program.
-class SymExpr : public llvm::FoldingSetNode {
- virtual void anchor();
-public:
- enum Kind { RegionValueKind, ConjuredKind, DerivedKind, ExtentKind,
- MetadataKind,
- BEGIN_SYMBOLS = RegionValueKind,
- END_SYMBOLS = MetadataKind,
- SymIntKind, IntSymKind, SymSymKind,
- BEGIN_BINARYSYMEXPRS = SymIntKind,
- END_BINARYSYMEXPRS = SymSymKind,
- CastSymbolKind };
-private:
- Kind K;
-
-protected:
- SymExpr(Kind k) : K(k) {}
-
-public:
- virtual ~SymExpr() {}
-
- Kind getKind() const { return K; }
-
- virtual void dump() const;
-
- virtual void dumpToStream(raw_ostream &os) const {}
-
- virtual QualType getType() const = 0;
- virtual void Profile(llvm::FoldingSetNodeID& profile) = 0;
-
- /// \brief Iterator over symbols that the current symbol depends on.
- ///
- /// For SymbolData, it's the symbol itself; for expressions, it's the
- /// expression symbol and all the operands in it. Note, SymbolDerived is
- /// treated as SymbolData - the iterator will NOT visit the parent region.
- class symbol_iterator {
- SmallVector<const SymExpr*, 5> itr;
- void expand();
- public:
- symbol_iterator() {}
- symbol_iterator(const SymExpr *SE);
-
- symbol_iterator &operator++();
- const SymExpr* operator*();
-
- bool operator==(const symbol_iterator &X) const;
- bool operator!=(const symbol_iterator &X) const;
- };
-
- symbol_iterator symbol_begin() const {
- return symbol_iterator(this);
- }
- static symbol_iterator symbol_end() { return symbol_iterator(); }
-
- unsigned computeComplexity() const;
-};
-
-typedef const SymExpr* SymbolRef;
-typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy;
-
-typedef unsigned SymbolID;
-/// \brief A symbol representing data which can be stored in a memory location
-/// (region).
-class SymbolData : public SymExpr {
- void anchor() override;
- const SymbolID Sym;
-
-protected:
- SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {}
-
-public:
- ~SymbolData() override {}
-
- SymbolID getSymbolID() const { return Sym; }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- Kind k = SE->getKind();
- return k >= BEGIN_SYMBOLS && k <= END_SYMBOLS;
- }
-};
-
-///\brief A symbol representing the value stored at a MemRegion.
-class SymbolRegionValue : public SymbolData {
- const TypedValueRegion *R;
-
-public:
- SymbolRegionValue(SymbolID sym, const TypedValueRegion *r)
- : SymbolData(RegionValueKind, sym), R(r) {}
-
- const TypedValueRegion* getRegion() const { return R; }
-
- static void Profile(llvm::FoldingSetNodeID& profile, const TypedValueRegion* R) {
- profile.AddInteger((unsigned) RegionValueKind);
- profile.AddPointer(R);
- }
-
- void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, R);
- }
-
- void dumpToStream(raw_ostream &os) const override;
-
- QualType getType() const override;
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == RegionValueKind;
- }
-};
-
-/// A symbol representing the result of an expression in the case when we do
-/// not know anything about what the expression is.
-class SymbolConjured : public SymbolData {
- const Stmt *S;
- QualType T;
- unsigned Count;
- const LocationContext *LCtx;
- const void *SymbolTag;
-
-public:
- SymbolConjured(SymbolID sym, const Stmt *s, const LocationContext *lctx,
- QualType t, unsigned count,
- const void *symbolTag)
- : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count),
- LCtx(lctx),
- SymbolTag(symbolTag) {}
-
- const Stmt *getStmt() const { return S; }
- unsigned getCount() const { return Count; }
- const void *getTag() const { return SymbolTag; }
-
- QualType getType() const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S,
- QualType T, unsigned Count, const LocationContext *LCtx,
- const void *SymbolTag) {
- profile.AddInteger((unsigned) ConjuredKind);
- profile.AddPointer(S);
- profile.AddPointer(LCtx);
- profile.Add(T);
- profile.AddInteger(Count);
- profile.AddPointer(SymbolTag);
- }
-
- void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, S, T, Count, LCtx, SymbolTag);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == ConjuredKind;
- }
-};
-
-/// A symbol representing the value of a MemRegion whose parent region has
-/// symbolic value.
-class SymbolDerived : public SymbolData {
- SymbolRef parentSymbol;
- const TypedValueRegion *R;
-
-public:
- SymbolDerived(SymbolID sym, SymbolRef parent, const TypedValueRegion *r)
- : SymbolData(DerivedKind, sym), parentSymbol(parent), R(r) {}
-
- SymbolRef getParentSymbol() const { return parentSymbol; }
- const TypedValueRegion *getRegion() const { return R; }
-
- QualType getType() const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent,
- const TypedValueRegion *r) {
- profile.AddInteger((unsigned) DerivedKind);
- profile.AddPointer(r);
- profile.AddPointer(parent);
- }
-
- void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, parentSymbol, R);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == DerivedKind;
- }
-};
-
-/// SymbolExtent - Represents the extent (size in bytes) of a bounded region.
-/// Clients should not ask the SymbolManager for a region's extent. Always use
-/// SubRegion::getExtent instead -- the value returned may not be a symbol.
-class SymbolExtent : public SymbolData {
- const SubRegion *R;
-
-public:
- SymbolExtent(SymbolID sym, const SubRegion *r)
- : SymbolData(ExtentKind, sym), R(r) {}
-
- const SubRegion *getRegion() const { return R; }
-
- QualType getType() const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) {
- profile.AddInteger((unsigned) ExtentKind);
- profile.AddPointer(R);
- }
-
- void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, R);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == ExtentKind;
- }
-};
-
-/// SymbolMetadata - Represents path-dependent metadata about a specific region.
-/// Metadata symbols remain live as long as they are marked as in use before
-/// dead-symbol sweeping AND their associated regions are still alive.
-/// Intended for use by checkers.
-class SymbolMetadata : public SymbolData {
- const MemRegion* R;
- const Stmt *S;
- QualType T;
- unsigned Count;
- const void *Tag;
-public:
- SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t,
- unsigned count, const void *tag)
- : SymbolData(MetadataKind, sym), R(r), S(s), T(t), Count(count), Tag(tag) {}
-
- const MemRegion *getRegion() const { return R; }
- const Stmt *getStmt() const { return S; }
- unsigned getCount() const { return Count; }
- const void *getTag() const { return Tag; }
-
- QualType getType() const override;
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R,
- const Stmt *S, QualType T, unsigned Count,
- const void *Tag) {
- profile.AddInteger((unsigned) MetadataKind);
- profile.AddPointer(R);
- profile.AddPointer(S);
- profile.Add(T);
- profile.AddInteger(Count);
- profile.AddPointer(Tag);
- }
-
- void Profile(llvm::FoldingSetNodeID& profile) override {
- Profile(profile, R, S, T, Count, Tag);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == MetadataKind;
- }
-};
-
-/// \brief Represents a cast expression.
-class SymbolCast : public SymExpr {
- const SymExpr *Operand;
- /// Type of the operand.
- QualType FromTy;
- /// The type of the result.
- QualType ToTy;
-
-public:
- SymbolCast(const SymExpr *In, QualType From, QualType To) :
- SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { }
-
- QualType getType() const override { return ToTy; }
-
- const SymExpr *getOperand() const { return Operand; }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& ID,
- const SymExpr *In, QualType From, QualType To) {
- ID.AddInteger((unsigned) CastSymbolKind);
- ID.AddPointer(In);
- ID.Add(From);
- ID.Add(To);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) override {
- Profile(ID, Operand, FromTy, ToTy);
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == CastSymbolKind;
- }
-};
-
-/// \brief Represents a symbolic expression involving a binary operator
-class BinarySymExpr : public SymExpr {
- BinaryOperator::Opcode Op;
- QualType T;
-
-protected:
- BinarySymExpr(Kind k, BinaryOperator::Opcode op, QualType t)
- : SymExpr(k), Op(op), T(t) {}
-
-public:
- // FIXME: We probably need to make this out-of-line to avoid redundant
- // generation of virtual functions.
- QualType getType() const override { return T; }
-
- BinaryOperator::Opcode getOpcode() const { return Op; }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- Kind k = SE->getKind();
- return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS;
- }
-};
-
-/// \brief Represents a symbolic expression like 'x' + 3.
-class SymIntExpr : public BinarySymExpr {
- const SymExpr *LHS;
- const llvm::APSInt& RHS;
-
-public:
- SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& rhs, QualType t)
- : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {}
-
- void dumpToStream(raw_ostream &os) const override;
-
- const SymExpr *getLHS() const { return LHS; }
- const llvm::APSInt &getRHS() const { return RHS; }
-
- static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
- BinaryOperator::Opcode op, const llvm::APSInt& rhs,
- QualType t) {
- ID.AddInteger((unsigned) SymIntKind);
- ID.AddPointer(lhs);
- ID.AddInteger(op);
- ID.AddPointer(&rhs);
- ID.Add(t);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) override {
- Profile(ID, LHS, getOpcode(), RHS, getType());
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == SymIntKind;
- }
-};
-
-/// \brief Represents a symbolic expression like 3 - 'x'.
-class IntSymExpr : public BinarySymExpr {
- const llvm::APSInt& LHS;
- const SymExpr *RHS;
-
-public:
- IntSymExpr(const llvm::APSInt& lhs, BinaryOperator::Opcode op,
- const SymExpr *rhs, QualType t)
- : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {}
-
- void dumpToStream(raw_ostream &os) const override;
-
- const SymExpr *getRHS() const { return RHS; }
- const llvm::APSInt &getLHS() const { return LHS; }
-
- static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs,
- BinaryOperator::Opcode op, const SymExpr *rhs,
- QualType t) {
- ID.AddInteger((unsigned) IntSymKind);
- ID.AddPointer(&lhs);
- ID.AddInteger(op);
- ID.AddPointer(rhs);
- ID.Add(t);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) override {
- Profile(ID, LHS, getOpcode(), RHS, getType());
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == IntSymKind;
- }
-};
-
-/// \brief Represents a symbolic expression like 'x' + 'y'.
-class SymSymExpr : public BinarySymExpr {
- const SymExpr *LHS;
- const SymExpr *RHS;
-
-public:
- SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs,
- QualType t)
- : BinarySymExpr(SymSymKind, op, t), LHS(lhs), RHS(rhs) {}
-
- const SymExpr *getLHS() const { return LHS; }
- const SymExpr *getRHS() const { return RHS; }
-
- void dumpToStream(raw_ostream &os) const override;
-
- static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs,
- BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) {
- ID.AddInteger((unsigned) SymSymKind);
- ID.AddPointer(lhs);
- ID.AddInteger(op);
- ID.AddPointer(rhs);
- ID.Add(t);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) override {
- Profile(ID, LHS, getOpcode(), RHS, getType());
- }
-
- // Implement isa<T> support.
- static inline bool classof(const SymExpr *SE) {
- return SE->getKind() == SymSymKind;
- }
-};
-
-class SymbolManager {
- typedef llvm::FoldingSet<SymExpr> DataSetTy;
- typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy;
-
- DataSetTy DataSet;
- /// Stores the extra dependencies between symbols: the data should be kept
- /// alive as long as the key is live.
- SymbolDependTy SymbolDependencies;
- unsigned SymbolCounter;
- llvm::BumpPtrAllocator& BPAlloc;
- BasicValueFactory &BV;
- ASTContext &Ctx;
-
-public:
- SymbolManager(ASTContext &ctx, BasicValueFactory &bv,
- llvm::BumpPtrAllocator& bpalloc)
- : SymbolDependencies(16), SymbolCounter(0),
- BPAlloc(bpalloc), BV(bv), Ctx(ctx) {}
-
- ~SymbolManager();
-
- static bool canSymbolicate(QualType T);
-
- /// \brief Make a unique symbol for MemRegion R according to its kind.
- const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R);
-
- const SymbolConjured* conjureSymbol(const Stmt *E,
- const LocationContext *LCtx,
- QualType T,
- unsigned VisitCount,
- const void *SymbolTag = nullptr);
-
- const SymbolConjured* conjureSymbol(const Expr *E,
- const LocationContext *LCtx,
- unsigned VisitCount,
- const void *SymbolTag = nullptr) {
- return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag);
- }
-
- const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol,
- const TypedValueRegion *R);
-
- const SymbolExtent *getExtentSymbol(const SubRegion *R);
-
- /// \brief Creates a metadata symbol associated with a specific region.
- ///
- /// VisitCount can be used to differentiate regions corresponding to
- /// different loop iterations, thus, making the symbol path-dependent.
- const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S,
- QualType T, unsigned VisitCount,
- const void *SymbolTag = nullptr);
-
- const SymbolCast* getCastSymbol(const SymExpr *Operand,
- QualType From, QualType To);
-
- const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& rhs, QualType t);
-
- const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op,
- const llvm::APSInt& rhs, QualType t) {
- return getSymIntExpr(&lhs, op, rhs, t);
- }
-
- const IntSymExpr *getIntSymExpr(const llvm::APSInt& lhs,
- BinaryOperator::Opcode op,
- const SymExpr *rhs, QualType t);
-
- const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op,
- const SymExpr *rhs, QualType t);
-
- QualType getType(const SymExpr *SE) const {
- return SE->getType();
- }
-
- /// \brief Add artificial symbol dependency.
- ///
- /// The dependent symbol should stay alive as long as the primary is alive.
- void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent);
-
- const SymbolRefSmallVectorTy *getDependentSymbols(const SymbolRef Primary);
-
- ASTContext &getContext() { return Ctx; }
- BasicValueFactory &getBasicVals() { return BV; }
-};
-
-/// \brief A class responsible for cleaning up unused symbols.
-class SymbolReaper {
- enum SymbolStatus {
- NotProcessed,
- HaveMarkedDependents
- };
-
- typedef llvm::DenseSet<SymbolRef> SymbolSetTy;
- typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy;
- typedef llvm::DenseSet<const MemRegion *> RegionSetTy;
-
- SymbolMapTy TheLiving;
- SymbolSetTy MetadataInUse;
- SymbolSetTy TheDead;
-
- RegionSetTy RegionRoots;
-
- const StackFrameContext *LCtx;
- const Stmt *Loc;
- SymbolManager& SymMgr;
- StoreRef reapedStore;
- llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache;
-
-public:
- /// \brief Construct a reaper object, which removes everything which is not
- /// live before we execute statement s in the given location context.
- ///
- /// If the statement is NULL, everything is this and parent contexts is
- /// considered live.
- /// If the stack frame context is NULL, everything on stack is considered
- /// dead.
- SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
- StoreManager &storeMgr)
- : LCtx(Ctx), Loc(s), SymMgr(symmgr),
- reapedStore(nullptr, storeMgr) {}
-
- const LocationContext *getLocationContext() const { return LCtx; }
-
- bool isLive(SymbolRef sym);
- bool isLiveRegion(const MemRegion *region);
- bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const;
- bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const;
-
- /// \brief Unconditionally marks a symbol as live.
- ///
- /// This should never be
- /// used by checkers, only by the state infrastructure such as the store and
- /// environment. Checkers should instead use metadata symbols and markInUse.
- void markLive(SymbolRef sym);
-
- /// \brief Marks a symbol as important to a checker.
- ///
- /// For metadata symbols,
- /// this will keep the symbol alive as long as its associated region is also
- /// live. For other symbols, this has no effect; checkers are not permitted
- /// to influence the life of other symbols. This should be used before any
- /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback.
- void markInUse(SymbolRef sym);
-
- /// \brief If a symbol is known to be live, marks the symbol as live.
- ///
- /// Otherwise, if the symbol cannot be proven live, it is marked as dead.
- /// Returns true if the symbol is dead, false if live.
- bool maybeDead(SymbolRef sym);
-
- typedef SymbolSetTy::const_iterator dead_iterator;
- dead_iterator dead_begin() const { return TheDead.begin(); }
- dead_iterator dead_end() const { return TheDead.end(); }
-
- bool hasDeadSymbols() const {
- return !TheDead.empty();
- }
-
- typedef RegionSetTy::const_iterator region_iterator;
- region_iterator region_begin() const { return RegionRoots.begin(); }
- region_iterator region_end() const { return RegionRoots.end(); }
-
- /// \brief Returns whether or not a symbol has been confirmed dead.
- ///
- /// This should only be called once all marking of dead symbols has completed.
- /// (For checkers, this means only in the evalDeadSymbols callback.)
- bool isDead(SymbolRef sym) const {
- return TheDead.count(sym);
- }
-
- void markLive(const MemRegion *region);
- void markElementIndicesLive(const MemRegion *region);
-
- /// \brief Set to the value of the symbolic store after
- /// StoreManager::removeDeadBindings has been called.
- void setReapedStore(StoreRef st) { reapedStore = st; }
-
-private:
- /// Mark the symbols dependent on the input symbol as live.
- void markDependentsLive(SymbolRef sym);
-};
-
-class SymbolVisitor {
-protected:
- ~SymbolVisitor() = default;
-
-public:
- SymbolVisitor() = default;
- SymbolVisitor(const SymbolVisitor &) = default;
- SymbolVisitor(SymbolVisitor &&) {}
-
- /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols.
- ///
- /// The method returns \c true if symbols should continue be scanned and \c
- /// false otherwise.
- virtual bool VisitSymbol(SymbolRef sym) = 0;
- virtual bool VisitMemRegion(const MemRegion *region) { return true; }
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-namespace llvm {
-static inline raw_ostream &operator<<(raw_ostream &os,
- const clang::ento::SymExpr *SE) {
- SE->dumpToStream(os);
- return os;
-}
-} // end llvm namespace
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
deleted file mode 100644
index d39b501..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//== TaintManager.h - Managing taint --------------------------- -*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides APIs for adding, removing, querying symbol taint.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H
-
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h"
-#include "llvm/ADT/ImmutableMap.h"
-
-namespace clang {
-namespace ento {
-
-/// The GDM component containing the tainted root symbols. We lazily infer the
-/// taint of the dependent symbols. Currently, this is a map from a symbol to
-/// tag kind. TODO: Should support multiple tag kinds.
-// FIXME: This does not use the nice trait macros because it must be accessible
-// from multiple translation units.
-struct TaintMap {};
-typedef llvm::ImmutableMap<SymbolRef, TaintTagType> TaintMapImpl;
-template<> struct ProgramStateTrait<TaintMap>
- : public ProgramStatePartialTrait<TaintMapImpl> {
- static void *GDMIndex() { static int index = 0; return &index; }
-};
-
-class TaintManager {
-
- TaintManager() {}
-};
-
-}
-}
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
deleted file mode 100644
index 0c56e7d..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//== TaintTag.h - Path-sensitive "State" for tracking values -*- C++ -*--=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines a set of taint tags. Several tags are used to differentiate kinds
-// of taint.
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H
-
-namespace clang {
-namespace ento {
-
-/// The type of taint, which helps to differentiate between different types of
-/// taint.
-typedef unsigned TaintTagType;
-static const TaintTagType TaintTagGeneric = 0;
-
-}}
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
deleted file mode 100644
index 4f1a60e..0000000
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h
+++ /dev/null
@@ -1,100 +0,0 @@
-//==- WorkList.h - Worklist class used by CoreEngine ---------------*- C++ -*-//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines WorkList, a pure virtual class that represents an opaque
-// worklist used by CoreEngine to explore the reachability state space.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H
-#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H
-
-#include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h"
-#include <cassert>
-
-namespace clang {
-
-class CFGBlock;
-
-namespace ento {
-
-class WorkListUnit {
- ExplodedNode *node;
- BlockCounter counter;
- const CFGBlock *block;
- unsigned blockIdx; // This is the index of the next statement.
-
-public:
- WorkListUnit(ExplodedNode *N, BlockCounter C,
- const CFGBlock *B, unsigned idx)
- : node(N),
- counter(C),
- block(B),
- blockIdx(idx) {}
-
- explicit WorkListUnit(ExplodedNode *N, BlockCounter C)
- : node(N),
- counter(C),
- block(nullptr),
- blockIdx(0) {}
-
- /// Returns the node associated with the worklist unit.
- ExplodedNode *getNode() const { return node; }
-
- /// Returns the block counter map associated with the worklist unit.
- BlockCounter getBlockCounter() const { return counter; }
-
- /// Returns the CFGblock associated with the worklist unit.
- const CFGBlock *getBlock() const { return block; }
-
- /// Return the index within the CFGBlock for the worklist unit.
- unsigned getIndex() const { return blockIdx; }
-};
-
-class WorkList {
- BlockCounter CurrentCounter;
-public:
- virtual ~WorkList();
- virtual bool hasWork() const = 0;
-
- virtual void enqueue(const WorkListUnit& U) = 0;
-
- void enqueue(ExplodedNode *N, const CFGBlock *B, unsigned idx) {
- enqueue(WorkListUnit(N, CurrentCounter, B, idx));
- }
-
- void enqueue(ExplodedNode *N) {
- assert(N->getLocation().getKind() != ProgramPoint::PostStmtKind);
- enqueue(WorkListUnit(N, CurrentCounter));
- }
-
- virtual WorkListUnit dequeue() = 0;
-
- void setBlockCounter(BlockCounter C) { CurrentCounter = C; }
- BlockCounter getBlockCounter() const { return CurrentCounter; }
-
- class Visitor {
- public:
- Visitor() {}
- virtual ~Visitor();
- virtual bool visit(const WorkListUnit &U) = 0;
- };
- virtual bool visitItemsInWorkList(Visitor &V) = 0;
-
- static WorkList *makeDFS();
- static WorkList *makeBFS();
- static WorkList *makeBFSBlockDFSContents();
-};
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
deleted file mode 100644
index 37ea05f..0000000
--- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This header contains the functions necessary for a front-end to run various
-// analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H
-#define LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/LLVM.h"
-#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include <string>
-
-namespace clang {
-
-class Preprocessor;
-class DiagnosticsEngine;
-class CodeInjector;
-class CompilerInstance;
-
-namespace ento {
-class CheckerManager;
-
-class AnalysisASTConsumer : public ASTConsumer {
-public:
- virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0;
-};
-
-/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code
-/// analysis passes. (The set of analyses run is controlled by command-line
-/// options.)
-std::unique_ptr<AnalysisASTConsumer>
-CreateAnalysisConsumer(CompilerInstance &CI);
-
-} // end GR namespace
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
deleted file mode 100644
index 2985b7c..0000000
--- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===-- CheckerRegistration.h - Checker Registration Function ---*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
-#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H
-
-#include "clang/Basic/LLVM.h"
-#include <memory>
-#include <string>
-
-namespace clang {
- class AnalyzerOptions;
- class LangOptions;
- class DiagnosticsEngine;
-
-namespace ento {
- class CheckerManager;
-
- std::unique_ptr<CheckerManager>
- createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts,
- ArrayRef<std::string> plugins, DiagnosticsEngine &diags);
-
-} // end ento namespace
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
deleted file mode 100644
index 36afb4b..0000000
--- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H
-#define LLVM_CLANG_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H
-
-#include "clang/Frontend/FrontendAction.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang {
-
-class Stmt;
-
-namespace ento {
-
-//===----------------------------------------------------------------------===//
-// AST Consumer Actions
-//===----------------------------------------------------------------------===//
-
-class AnalysisAction : public ASTFrontendAction {
-protected:
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
-};
-
-/// \brief Frontend action to parse model files.
-///
-/// This frontend action is responsible for parsing model files. Model files can
-/// not be parsed on their own, they rely on type information that is available
-/// in another translation unit. The parsing of model files is done by a
-/// separate compiler instance that reuses the ASTContext and othen information
-/// from the main translation unit that is being compiled. After a model file is
-/// parsed, the function definitions will be collected into a StringMap.
-class ParseModelFileAction : public ASTFrontendAction {
-public:
- ParseModelFileAction(llvm::StringMap<Stmt *> &Bodies);
- bool isModelParsingAction() const override { return true; }
-
-protected:
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
-
-private:
- llvm::StringMap<Stmt *> &Bodies;
-};
-
-void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins);
-
-} // end GR namespace
-
-} // end namespace clang
-
-#endif
diff --git a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
deleted file mode 100644
index 24f8042..0000000
--- a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- ModelConsumer.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file implements clang::ento::ModelConsumer which is an
-/// ASTConsumer for model files.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_GR_MODELCONSUMER_H
-#define LLVM_CLANG_GR_MODELCONSUMER_H
-
-#include "clang/AST/ASTConsumer.h"
-#include "llvm/ADT/StringMap.h"
-
-namespace clang {
-
-class Stmt;
-
-namespace ento {
-
-/// \brief ASTConsumer to consume model files' AST.
-///
-/// This consumer collects the bodies of function definitions into a StringMap
-/// from a model file.
-class ModelConsumer : public ASTConsumer {
-public:
- ModelConsumer(llvm::StringMap<Stmt *> &Bodies);
-
- bool HandleTopLevelDecl(DeclGroupRef D) override;
-
-private:
- llvm::StringMap<Stmt *> &Bodies;
-};
-}
-}
-
-#endif
OpenPOWER on IntegriCloud