diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2013-12-22 00:07:40 +0000 |
commit | bfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch) | |
tree | df8df0b0067b381eab470a3b8f28d14a552a6340 /include/clang/StaticAnalyzer | |
parent | 6a0372513edbc473b538d2f724efac50405d6fef (diff) | |
download | src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip |
Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3):vendor/clang/clang-release_34-r197841
Notes
Notes:
svn path=/vendor/clang/dist/; revision=259701
svn path=/vendor/clang/clang-release_34-r197841/; revision=259703; tag=vendor/clang/clang-release_34-r197841
Diffstat (limited to 'include/clang/StaticAnalyzer')
21 files changed, 468 insertions, 182 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h new file mode 100644 index 000000000000..5978299701cf --- /dev/null +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -0,0 +1,223 @@ +//==-- 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_OBJCRETAINCOUNT_H +#define LLVM_CLANG_OBJCRETAINCOUNT_H + +namespace clang { 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 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 object is not owned and controlled by ARC. + ARCNotOwnedSymbol, + /// 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 || K == ARCNotOwnedSymbol; + } + + 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 MakeARCNotOwned() { + return RetEffect(ARCNotOwnedSymbol, 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. + llvm::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 index dc7945016b1a..3355f4b6949c 100644 --- a/include/clang/StaticAnalyzer/Core/Analyses.def +++ b/include/clang/StaticAnalyzer/Core/Analyses.def @@ -24,14 +24,14 @@ ANALYSIS_STORE(RegionStore, "region", "Use region-based analyzer store", CreateR ANALYSIS_CONSTRAINTS(RangeConstraints, "range", "Use constraint tracking of concrete value ranges", CreateRangeConstraintManager) #ifndef ANALYSIS_DIAGNOSTICS -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) #endif -ANALYSIS_DIAGNOSTICS(HTML, "html", "Output analysis results using HTML", createHTMLDiagnosticConsumer, false) -ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", createPlistDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(PLIST_MULTI_FILE, "plist-multi-file", "Output analysis results using Plists (allowing for mult-file bugs)", createPlistMultiFileDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticConsumer, true) -ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticConsumer, true) +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) diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index fb35f518ef02..618782e5d78c 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -52,7 +52,7 @@ NumConstraints /// AnalysisDiagClients - Set of available diagnostic clients for rendering /// analysis results. enum AnalysisDiagClients { -#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) PD_##NAME, +#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, #include "clang/StaticAnalyzer/Core/Analyses.def" NUM_ANALYSIS_DIAG_CLIENTS }; @@ -201,6 +201,9 @@ private: /// \sa mayInlineCXXContainerCtorsAndDtors Optional<bool> InlineCXXContainerCtorsAndDtors; + /// \sa mayInlineCXXSharedPtrDtor + Optional<bool> InlineCXXSharedPtrDtor; + /// \sa mayInlineObjCMethod Optional<bool> ObjCInliningMode; @@ -223,6 +226,9 @@ private: /// \sa shouldSuppressFromCXXStandardLibrary Optional<bool> SuppressFromCXXStandardLibrary; + /// \sa reportIssuesInMainSourceFile + Optional<bool> ReportIssuesInMainSourceFile; + /// \sa getGraphTrimInterval Optional<unsigned> GraphTrimInterval; @@ -291,6 +297,16 @@ public: /// accepts the values "true" and "false". bool mayInlineCXXContainerCtorsAndDtors(); + /// 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. /// @@ -326,6 +342,13 @@ public: /// 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 irrelevant parts of a bug report path should be pruned /// out of the final output. /// diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 5c560b2f0ec9..9584b8baf4f1 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_GR_BUGREPORTER #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/PathSensitive/ProgramState.h" @@ -375,6 +376,7 @@ public: 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. @@ -442,6 +444,8 @@ public: SourceManager& getSourceManager() { return D.getSourceManager(); } + AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } + virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, PathDiagnosticConsumer &PC, ArrayRef<BugReport *> &bugReports) { @@ -462,20 +466,7 @@ public: void EmitBasicReport(const Decl *DeclWithIssue, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, - SourceRange* RangeBeg, unsigned NumRanges); - - void EmitBasicReport(const Decl *DeclWithIssue, - StringRef BugName, StringRef BugCategory, - StringRef BugStr, PathDiagnosticLocation Loc) { - EmitBasicReport(DeclWithIssue, BugName, BugCategory, BugStr, Loc, 0, 0); - } - - void EmitBasicReport(const Decl *DeclWithIssue, - StringRef BugName, StringRef Category, - StringRef BugStr, PathDiagnosticLocation Loc, - SourceRange R) { - EmitBasicReport(DeclWithIssue, BugName, Category, BugStr, Loc, &R, 1); - } + ArrayRef<SourceRange> Ranges = None); private: llvm::StringMap<BugType *> StrBugTypes; diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 644aa3159301..49f9c83ba950 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE +#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include <string> @@ -31,10 +32,12 @@ private: const std::string Name; const std::string Category; bool SuppressonSink; + + virtual void anchor(); public: BugType(StringRef name, StringRef cat) : Name(name), Category(cat), SuppressonSink(false) {} - virtual ~BugType(); + virtual ~BugType() {} // FIXME: Should these be made strings as well? StringRef getName() const { return Name; } @@ -50,14 +53,14 @@ public: }; class BuiltinBug : public BugType { - virtual void anchor(); const std::string desc; + virtual void anchor(); public: BuiltinBug(const char *name, const char *description) - : BugType(name, "Logic error"), desc(description) {} + : BugType(name, categories::LogicError), desc(description) {} BuiltinBug(const char *name) - : BugType(name, "Logic error"), desc(name) {} + : BugType(name, categories::LogicError), desc(name) {} StringRef getDescription() const { return desc; } }; diff --git a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index 9d4251b1a757..3f0fe968cc11 100644 --- a/include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -7,16 +7,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H -#define LLVM_CLANG_STATIC_ANALYZER_CHECKER_CATEGORIES_H +#ifndef LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H +#define LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H // Common strings used for the "category" of many static analyzer issues. namespace clang { namespace ento { namespace categories { - extern const char *CoreFoundationObjectiveC; - extern const char *MemoryCoreFoundationObjectiveC; - extern const char *UnixAPI; + extern const char * const CoreFoundationObjectiveC; + extern const char * const LogicError; + extern const char * const MemoryCoreFoundationObjectiveC; + extern const char * const UnixAPI; } } } diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index a80b5a7a248c..b0670dad240d 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -38,6 +38,7 @@ class ParentMap; class ProgramPoint; class SourceManager; class Stmt; +class CallExpr; namespace ento { @@ -97,7 +98,6 @@ public: enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } - virtual bool supportsAllBlockEdges() const { return false; } /// Return true if the PathDiagnosticConsumer supports individual /// PathDiagnostics that span multiple files. @@ -285,11 +285,13 @@ public: 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 sucessor node. + /// \brief Retrieve the statement corresponding to the successor node. static const Stmt *getNextStmt(const ExplodedNode *N); }; @@ -331,6 +333,10 @@ 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 @@ -389,6 +395,16 @@ public: 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; }; @@ -403,6 +419,8 @@ public: flattenTo(Result, Result, ShouldFlattenMacros); return Result; } + + LLVM_ATTRIBUTE_USED void dump() const; }; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { @@ -421,7 +439,7 @@ public: PathDiagnosticLocation getLocation() const { return Pos; } virtual void flattenLocations() { Pos.flatten(); } - + virtual void Profile(llvm::FoldingSetNodeID &ID) const; static bool classof(const PathDiagnosticPiece *P) { @@ -504,7 +522,7 @@ public: } bool hasCallStackHint() { - return (CallStackHint != 0); + return CallStackHint.isValid(); } /// Produce the hint for the given node. The node contains @@ -515,6 +533,8 @@ public: return ""; } + virtual void dump() const; + static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; } @@ -582,6 +602,8 @@ public: static PathDiagnosticCallPiece *construct(PathPieces &pieces, const Decl *caller); + virtual void dump() const; + virtual void Profile(llvm::FoldingSetNodeID &ID) const; static inline bool classof(const PathDiagnosticPiece *P) { @@ -649,7 +671,9 @@ public: static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == ControlFlow; } - + + virtual void dump() const; + virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; @@ -673,7 +697,9 @@ public: static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Macro; } - + + virtual void dump() const; + virtual void Profile(llvm::FoldingSetNodeID &ID) const; }; @@ -687,7 +713,10 @@ class PathDiagnostic : public llvm::FoldingSetNode { 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; @@ -735,12 +764,23 @@ public: getActivePath().push_back(EndPiece); } + 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; @@ -759,7 +799,7 @@ public: void addMeta(StringRef s) { OtherDesc.push_back(s); } PathDiagnosticLocation getLocation() const { - assert(Loc.isValid() && "No end-of-path location set yet!"); + assert(Loc.isValid() && "No report location set yet!"); return Loc; } diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index 0dbaab033d2d..cf7cf051d225 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -320,18 +320,35 @@ public: class PointerEscape { template <typename CHECKER> static ProgramStateRef - _checkPointerEscape(void *checker, + _checkPointerEscape(void *Checker, ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, - bool IsConst) { - if (!IsConst) - return ((const CHECKER *)checker)->checkPointerEscape(State, + RegionAndSymbolInvalidationTraits *ETraits) { + + if (!ETraits) + return ((const CHECKER *)Checker)->checkPointerEscape(State, Escaped, Call, Kind); - return State; + + 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: @@ -346,18 +363,32 @@ public: class ConstPointerEscape { template <typename CHECKER> static ProgramStateRef - _checkConstPointerEscape(void *checker, + _checkConstPointerEscape(void *Checker, ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, - bool IsConst) { - if (IsConst) - return ((const CHECKER *)checker)->checkConstPointerEscape(State, - Escaped, - Call, - Kind); - return State; + 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: @@ -502,10 +533,14 @@ struct ImplicitNullDerefEvent { }; /// \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) {} - operator bool() const { return val; } + /*implicit*/ operator bool&() { return val; } + /*implicit*/ operator const bool&() const { return val; } DefaultBool &operator=(bool b) { val = b; return *this; } }; diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index b2411e6e6544..8ad67c118f01 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -19,7 +19,6 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" #include <vector> @@ -366,14 +365,16 @@ public: /// \param Escaped The list of escaped symbols. /// \param Call The corresponding CallEvent, if the symbols escape as /// parameters to the given call. - /// \param IsConst Specifies if the pointer is const. + /// \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, - bool IsConst = false); + RegionAndSymbolInvalidationTraits *ITraits); /// \brief Run checkers for handling assumptions on symbolic values. ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, @@ -465,7 +466,7 @@ public: const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, - bool IsConst)> + RegionAndSymbolInvalidationTraits *ITraits)> CheckPointerEscapeFunc; typedef CheckerFn<ProgramStateRef (ProgramStateRef, @@ -581,35 +582,12 @@ private: }; std::vector<StmtCheckerInfo> StmtCheckers; - struct CachedStmtCheckersKey { - unsigned StmtKind; - bool IsPreVisit; - - CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { } - CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit) - : StmtKind(stmtKind), IsPreVisit(isPreVisit) { } - - static CachedStmtCheckersKey getSentinel() { - return CachedStmtCheckersKey(~0U, 0); - } - unsigned getHashValue() const { - llvm::FoldingSetNodeID ID; - ID.AddInteger(StmtKind); - ID.AddBoolean(IsPreVisit); - return ID.ComputeHash(); - } - bool operator==(const CachedStmtCheckersKey &RHS) const { - return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit; - } - }; - friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>; - typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; - typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers> - CachedStmtCheckersMapTy; + typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy; CachedStmtCheckersMapTy CachedStmtCheckersMap; - CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit); + const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S, + bool isPreVisit); std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers; std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers; @@ -659,30 +637,4 @@ private: } // end clang namespace -namespace llvm { - /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key - /// in DenseMap and DenseSets. - template <> - struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> { - static inline clang::ento::CheckerManager::CachedStmtCheckersKey - getEmptyKey() { - return clang::ento::CheckerManager::CachedStmtCheckersKey(); - } - static inline clang::ento::CheckerManager::CachedStmtCheckersKey - getTombstoneKey() { - return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel(); - } - - static unsigned - getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) { - return S.getHashValue(); - } - - static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS, - clang::ento::CheckerManager::CachedStmtCheckersKey RHS) { - return LHS == RHS; - } - }; -} // end namespace llvm - #endif diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h index 4557aa40ea80..ca68a74fef96 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h @@ -54,10 +54,6 @@ // // For a complete working example, see examples/analyzer-plugin. - -namespace clang { -namespace ento { - #ifndef CLANG_ANALYZER_API_VERSION_STRING // FIXME: The Clang version string is not particularly granular; // the analyzer infrastructure can change a lot between releases. @@ -67,6 +63,9 @@ namespace ento { #define CLANG_ANALYZER_API_VERSION_STRING CLANG_VERSION_STRING #endif +namespace clang { +namespace ento { + class CheckerOptInfo; /// Manages a set of available checkers for running a static analysis. diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index b856de7dc612..43e9166b3cdc 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -27,18 +27,12 @@ namespace ento { class PathDiagnosticConsumer; typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers; -#define CREATE_CONSUMER(NAME)\ -void create ## NAME ## DiagnosticConsumer(AnalyzerOptions &AnalyzerOpts,\ - PathDiagnosticConsumers &C,\ - const std::string& prefix,\ - const Preprocessor &PP); - -CREATE_CONSUMER(HTML) -CREATE_CONSUMER(Plist) -CREATE_CONSUMER(PlistMultiFile) -CREATE_CONSUMER(TextPath) - -#undef CREATE_CONSUMER +#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 diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 458c8966e79e..d7d83ce8b17d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -65,6 +65,10 @@ public: StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; } + + AnalyzerOptions& getAnalyzerOptions() { + return options; + } ConstraintManagerCreator getConstraintManagerCreator() { return CreateConstraintMgr; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index f990b8dcd0ec..cfaf085b5f34 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -228,11 +228,6 @@ public: return false; } - /// \brief Returns true if this is a call to a variadic function or method. - virtual bool isVariadic() const { - return false; - } - /// \brief Returns a source range for the entire call, suitable for /// outputting in diagnostics. virtual SourceRange getSourceRange() const { @@ -341,6 +336,11 @@ public: /// 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; @@ -350,19 +350,13 @@ public: /// Returns an iterator over the call's formal parameters. /// - /// If UseDefinitionParams is set, this will return the parameter decls - /// used in the callee's definition (suitable for inlining). Most of the - /// time it is better to use the decl found by name lookup, which likely - /// carries more annotations. - /// /// 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). /// - /// If the call has no accessible declaration (or definition, if - /// \p UseDefinitionParams is set), \c param_begin() will be equal to - /// \c param_end(). - virtual param_iterator param_begin() const =0; + /// If the call has no accessible declaration, \c param_begin() will be equal + /// to \c param_end(). + virtual param_iterator param_begin() const = 0; /// \sa param_begin() virtual param_iterator param_end() const = 0; @@ -423,10 +417,6 @@ public: return RuntimeDefinition(); } - virtual bool isVariadic() const { - return getDecl()->isVariadic(); - } - virtual bool argumentsMayEscape() const; virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, @@ -527,10 +517,6 @@ public: return RuntimeDefinition(getBlockDecl()); } - virtual bool isVariadic() const { - return getBlockDecl()->isVariadic(); - } - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const; @@ -849,9 +835,6 @@ public: virtual const Expr *getArgExpr(unsigned Index) const { return getOriginExpr()->getArg(Index); } - virtual bool isVariadic() const { - return getDecl()->isVariadic(); - } bool isInstanceMessage() const { return getOriginExpr()->isInstanceMessage(); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index edcfc8a6c097..bf17cd807d65 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -184,7 +184,7 @@ public: bool isSink() const { return Succs.getFlag(); } - bool hasSinglePred() const { + bool hasSinglePred() const { return (pred_size() == 1); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 33e4431eb4be..d89dffe63b0a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -203,6 +203,8 @@ public: 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, @@ -476,14 +478,14 @@ protected: SVal Loc, SVal Val); /// Call PointerEscape callback when a value escapes as a result of /// region invalidation. - /// \param[in] IsConst Specifies that the pointer is const. + /// \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, - bool IsConst); + RegionAndSymbolInvalidationTraits &ITraits); public: // FIXME: 'tag' should be removed, and a LocationContext should be used diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 9b4f77dd679f..cc790c1b6b39 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -635,12 +635,14 @@ 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, - const MemRegion *sreg) + unsigned count, const MemRegion *sreg) : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), + BlockCount(count), ReferencedVars(0), OriginalVars(0) {} public: @@ -692,7 +694,8 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, - const LocationContext *, const MemRegion *); + const LocationContext *, unsigned, + const MemRegion *); static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; @@ -1270,7 +1273,13 @@ public: /// argument is allowed to be NULL for cases where we have no known /// context. const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc = NULL); + 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> @@ -1304,6 +1313,39 @@ private: 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 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 diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 42ef1db45591..03739ed9284d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -232,22 +232,21 @@ public: /// \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 ConstRegions the set of regions whose contents are accessible, - /// even though the regions themselves should not be 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 = 0, const CallEvent *Call = 0, - ArrayRef<const MemRegion *> ConstRegions = - ArrayRef<const MemRegion *>()) const; + RegionAndSymbolInvalidationTraits *ITraits = 0) const; ProgramStateRef invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS = 0, const CallEvent *Call = 0, - ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const; + RegionAndSymbolInvalidationTraits *ITraits = 0) const; /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. @@ -425,9 +424,9 @@ private: const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool ResultsInSymbolEscape, - InvalidatedSymbols &IS, - const CallEvent *Call, - ArrayRef<SVal> ConstValues) const; + InvalidatedSymbols *IS, + RegionAndSymbolInvalidationTraits *HTraits, + const CallEvent *Call) const; }; //===----------------------------------------------------------------------===// @@ -516,8 +515,8 @@ public: public: - SVal ArrayToPointer(Loc Array) { - return StoreMgr->ArrayToPointer(Array); + SVal ArrayToPointer(Loc Array, QualType ElementTy) { + return StoreMgr->ArrayToPointer(Array, ElementTy); } // Methods that manipulate the GDM. @@ -798,7 +797,7 @@ CB ProgramState::scanReachableSymbols(const MemRegion * const *beg, /// A Utility class that allows to visit the reachable symbols using a custom /// SymbolVisitor. class ScanReachableSymbols { - typedef llvm::DenseMap<const void*, unsigned> VisitedItems; + typedef llvm::DenseSet<const void*> VisitedItems; VisitedItems visited; ProgramStateRef state; @@ -808,6 +807,7 @@ 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); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index bbb56885af04..c5d0a92cabdd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -200,7 +200,8 @@ public: DefinedSVal getFunctionPointer(const FunctionDecl *func); DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy, - const LocationContext *locContext); + const LocationContext *locContext, + unsigned blockCount); /// Returns the value of \p E, if it can be determined in a non-path-sensitive /// manner. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 326e784e83d4..5a426ef00197 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -290,7 +290,7 @@ public: static inline bool isLocType(QualType T) { return T->isAnyPointerType() || T->isBlockPointerType() || - T->isReferenceType(); + T->isReferenceType() || T->isNullPtrType(); } private: diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index b219495d5f06..530dae59892a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -111,7 +111,7 @@ public: /// ArrayToPointer - Used by ExprEngine::VistCast to handle implicit /// conversions between arrays and pointers. - virtual SVal ArrayToPointer(Loc Array) = 0; + virtual SVal ArrayToPointer(Loc Array, QualType ElementTy) = 0; /// Evaluates a chain of derived-to-base casts through the path specified in /// \p Cast. @@ -164,8 +164,6 @@ public: /// 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] ConstValues The values to invalidate; these are known to be - /// const, so only regions accesible from them should be invalidated. /// \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 @@ -174,13 +172,10 @@ public: /// 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,out] ConstIS A set to fill with any symbols corresponding to - /// the ConstValues. + /// \param[in] ITraits Information about invalidation for a particular + /// region/symbol. /// \param[in,out] InvalidatedTopLevel A vector to fill with regions - //// explicitely being invalidated. Pass \c NULL if this - /// information will not be used. - /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const - //// regions explicitely being invalidated. Pass \c NULL if this + //// 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 @@ -188,14 +183,12 @@ public: /// information will not be used. virtual StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values, - ArrayRef<SVal> ConstValues, const Expr *E, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, - InvalidatedSymbols &ConstIS, + RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *InvalidatedTopLevel, - InvalidatedRegions *InvalidatedTopLevelConst, InvalidatedRegions *Invalidated) = 0; /// enterStackFrame - Let the StoreManager to do something when execution @@ -231,7 +224,7 @@ public: bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal val); - operator bool() { return First && Binding; } + LLVM_EXPLICIT operator bool() { return First && Binding; } const MemRegion *getRegion() { return Binding; } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index d4100634a785..f653c70a30f3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -134,7 +134,7 @@ public: ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, const CallEvent *Call, - bool IsConst = false) = 0; + RegionAndSymbolInvalidationTraits &HTraits) = 0; /// printState - Called by ProgramStateManager to print checker-specific data. virtual void printState(raw_ostream &Out, ProgramStateRef State, |