diff options
Diffstat (limited to 'include/clang/StaticAnalyzer')
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 ®istry); - -} // 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 ®istry) { -// 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 |