diff options
Diffstat (limited to 'include/clang/StaticAnalyzer')
29 files changed, 645 insertions, 523 deletions
diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index 5978299701cf..26335bf68dd9 100644 --- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -114,8 +114,6 @@ public: /// 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, @@ -154,7 +152,7 @@ public: } bool notOwned() const { - return K == NotOwnedSymbol || K == ARCNotOwnedSymbol; + return K == NotOwnedSymbol; } bool operator==(const RetEffect &Other) const { @@ -174,9 +172,6 @@ public: static RetEffect MakeGCNotOwned() { return RetEffect(GCNotOwnedSymbol, ObjC); } - static RetEffect MakeARCNotOwned() { - return RetEffect(ARCNotOwnedSymbol, ObjC); - } static RetEffect MakeNoRet() { return RetEffect(NoRet); } @@ -202,7 +197,7 @@ class CallEffects { public: /// Returns the argument effects for a call. - llvm::ArrayRef<ArgEffect> getArgs() const { return Args; } + ArrayRef<ArgEffect> getArgs() const { return Args; } /// Returns the effects on the receiver. ArgEffect getReceiver() const { return Receiver; } diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 618782e5d78c..978c3e20ab20 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -54,6 +54,7 @@ NumConstraints enum AnalysisDiagClients { #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN) PD_##NAME, #include "clang/StaticAnalyzer/Core/Analyses.def" +PD_NONE, NUM_ANALYSIS_DIAG_CLIENTS }; @@ -140,7 +141,7 @@ public: 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. /// @@ -198,8 +199,11 @@ private: /// \sa mayInlineTemplateFunctions Optional<bool> InlineTemplateFunctions; - /// \sa mayInlineCXXContainerCtorsAndDtors - Optional<bool> InlineCXXContainerCtorsAndDtors; + /// \sa mayInlineCXXAllocator + Optional<bool> InlineCXXAllocator; + + /// \sa mayInlineCXXContainerMethods + Optional<bool> InlineCXXContainerMethods; /// \sa mayInlineCXXSharedPtrDtor Optional<bool> InlineCXXSharedPtrDtor; @@ -229,6 +233,9 @@ private: /// \sa reportIssuesInMainSourceFile Optional<bool> ReportIssuesInMainSourceFile; + /// \sa StableReportFilename + Optional<bool> StableReportFilename; + /// \sa getGraphTrimInterval Optional<unsigned> GraphTrimInterval; @@ -290,12 +297,18 @@ public: /// accepts the values "true" and "false". bool mayInlineTemplateFunctions(); - /// Returns whether or not constructors and destructors of C++ container - /// objects may be considered for inlining. + /// 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 mayInlineCXXContainerCtorsAndDtors(); + bool mayInlineCXXContainerMethods(); /// Returns whether or not the destructor of C++ 'shared_ptr' may be /// considered for inlining. @@ -349,6 +362,12 @@ public: /// 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. /// diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 9584b8baf4f1..53712319253c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -19,6 +19,7 @@ #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" @@ -143,19 +144,18 @@ private: public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(0), Description(desc), ErrorNode(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(0), ShortDescription(shortDesc), Description(desc), - ErrorNode(errornode), ConfigurationChangeToken(0), + : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc), + Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0), DoNotPrunePath(false) {} - BugReport(BugType& bt, StringRef desc, PathDiagnosticLocation l) - : BT(bt), DeclWithIssue(0), Description(desc), Location(l), ErrorNode(0), - 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. /// @@ -166,7 +166,7 @@ public: /// 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(0), Description(desc), + : BT(bt), DeclWithIssue(nullptr), Description(desc), UniqueingLocation(LocationToUnique), UniqueingDecl(DeclToUnique), ErrorNode(errornode), ConfigurationChangeToken(0), @@ -463,7 +463,12 @@ public: /// reports. void emitReport(BugReport *R); - void EmitBasicReport(const Decl *DeclWithIssue, + 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); @@ -473,7 +478,8 @@ private: /// \brief Returns a BugType that is associated with the given name and /// category. - BugType *getBugTypeForName(StringRef name, StringRef category); + BugType *getBugTypeForName(CheckName CheckName, StringRef name, + StringRef category); }; // FIXME: Get rid of GRBugReporter. It's the wrong abstraction. @@ -505,9 +511,8 @@ public: /// /// \return True if the report was valid and a path was generated, /// false if the reports should be considered invalid. - virtual bool generatePathDiagnostic(PathDiagnostic &PD, - PathDiagnosticConsumer &PC, - ArrayRef<BugReport*> &bugReports); + bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, + ArrayRef<BugReport*> &bugReports) override; /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index 2e67180beace..f352f806eb9c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -89,7 +89,7 @@ public: /// will have to provide your own implementation.) template <class DERIVED> class BugReporterVisitorImpl : public BugReporterVisitor { - virtual BugReporterVisitor *clone() const { + BugReporterVisitor *clone() const override { return new DERIVED(*static_cast<const DERIVED *>(this)); } }; @@ -118,12 +118,12 @@ public: Satisfied(false), EnableNullFPSuppression(InEnableNullFPSuppression) {} - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; class TrackConstraintBRVisitor @@ -144,7 +144,7 @@ public: IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), IsTrackingTurnedOn(false) {} - void Profile(llvm::FoldingSetNodeID &ID) const; + 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. @@ -153,7 +153,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; private: /// Checks if the constraint is valid in the current state. @@ -166,8 +166,8 @@ private: class NilReceiverBRVisitor : public BugReporterVisitorImpl<NilReceiverBRVisitor> { public: - - void Profile(llvm::FoldingSetNodeID &ID) const { + + void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); } @@ -175,7 +175,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; /// If the statement is a message send expression with nil receiver, returns /// the receiver expression. Returns NULL otherwise. @@ -185,7 +185,7 @@ public: /// Visitor that tries to report interesting diagnostics from conditions. class ConditionBRVisitor : public BugReporterVisitorImpl<ConditionBRVisitor> { public: - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); } @@ -193,11 +193,11 @@ public: /// Return the tag associated with this visitor. This tag will be used /// to make all PathDiagnosticPieces created by this visitor. static const char *getTag(); - - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *Prev, - BugReporterContext &BRC, - BugReport &BR); + + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) override; PathDiagnosticPiece *VisitNodeImpl(const ExplodedNode *N, const ExplodedNode *Prev, @@ -257,20 +257,20 @@ public: return static_cast<void *>(&Tag); } - void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { ID.AddPointer(getTag()); } - virtual PathDiagnosticPiece *VisitNode(const ExplodedNode *N, - const ExplodedNode *Prev, - BugReporterContext &BRC, - BugReport &BR) { - return 0; + PathDiagnosticPiece *VisitNode(const ExplodedNode *N, + const ExplodedNode *Prev, + BugReporterContext &BRC, + BugReport &BR) override { + return nullptr; } - virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR); + PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override; }; /// \brief When a region containing undefined value or '0' value is passed @@ -287,7 +287,7 @@ class UndefOrNullArgVisitor public: UndefOrNullArgVisitor(const MemRegion *InR) : R(InR) {} - virtual void Profile(llvm::FoldingSetNodeID &ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const override { static int Tag = 0; ID.AddPointer(&Tag); ID.AddPointer(R); @@ -296,7 +296,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; class SuppressInlineDefensiveChecksVisitor @@ -319,7 +319,7 @@ class SuppressInlineDefensiveChecksVisitor public: SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); - void Profile(llvm::FoldingSetNodeID &ID) const; + 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. @@ -328,7 +328,7 @@ public: PathDiagnosticPiece *VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, - BugReport &BR); + BugReport &BR) override; }; namespace bugreporter { diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 49f9c83ba950..24c778552ee4 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -14,8 +14,9 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE -#include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.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> @@ -29,20 +30,25 @@ class ExprEngine; class BugType { private: + const CheckName Check; 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) {} + 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. @@ -54,14 +60,18 @@ public: class BuiltinBug : public BugType { const std::string desc; - virtual void anchor(); + void anchor() override; public: - BuiltinBug(const char *name, const char *description) - : BugType(name, categories::LogicError), desc(description) {} - - BuiltinBug(const char *name) - : BugType(name, categories::LogicError), desc(name) {} - + 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; } }; diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index b0670dad240d..5a578d015e39 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -21,13 +21,13 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" #include <deque> -#include <list> #include <iterator> +#include <list> #include <string> #include <vector> namespace clang { - +class ConditionalOperator; class AnalysisDeclContext; class BinaryOperator; class CompoundStmt; @@ -72,7 +72,9 @@ public: struct FilesMade : public llvm::FoldingSet<PDFileEntry> { llvm::BumpPtrAllocator Alloc; - + + ~FilesMade(); + void addDiagnostic(const PathDiagnostic &PD, StringRef ConsumerName, StringRef fileName); @@ -136,29 +138,29 @@ private: PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind) - : K(kind), S(0), D(0), SM(&sm), + : K(kind), S(nullptr), D(nullptr), SM(&sm), Loc(genLocation(L)), Range(genRange()) { } - FullSourceLoc - genLocation(SourceLocation L = SourceLocation(), - LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; + FullSourceLoc genLocation( + SourceLocation L = SourceLocation(), + LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const; - PathDiagnosticRange - genRange(LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext*)0) const; + PathDiagnosticRange genRange( + LocationOrAnalysisDeclContext LAC = (AnalysisDeclContext *)nullptr) const; public: /// Create an invalid location. PathDiagnosticLocation() - : K(SingleLocK), S(0), D(0), SM(0) {} + : 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 : 0), - D(0), SM(&sm), + S(K == StmtK ? s : nullptr), + D(nullptr), SM(&sm), Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { assert(K == SingleLocK || S); @@ -168,7 +170,7 @@ public: /// Create a location corresponding to the given declaration. PathDiagnosticLocation(const Decl *d, const SourceManager &sm) - : K(DeclK), S(0), D(d), SM(&sm), + : K(DeclK), S(nullptr), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) { assert(D); assert(Loc.isValid()); @@ -179,7 +181,8 @@ public: /// /// This should only be used if there are no more appropriate constructors. PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm) - : K(SingleLocK), S(0), D(0), SM(&sm), Loc(loc, sm), Range(genRange()) { + : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm), + Range(genRange()) { assert(Loc.isValid()); assert(Range.isValid()); } @@ -211,6 +214,9 @@ public: /// 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. @@ -259,7 +265,7 @@ public: } bool isValid() const { - return SM != 0; + return SM != nullptr; } FullSourceLoc asLocation() const { @@ -420,7 +426,7 @@ public: return Result; } - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; }; class PathDiagnosticSpotPiece : public PathDiagnosticPiece { @@ -437,10 +443,10 @@ public: if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); } - PathDiagnosticLocation getLocation() const { return Pos; } - virtual void flattenLocations() { Pos.flatten(); } + PathDiagnosticLocation getLocation() const override { return Pos; } + void flattenLocations() override { Pos.flatten(); } - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event || P->getKind() == Macro; @@ -476,7 +482,7 @@ public: /// \brief Search the call expression for the symbol Sym and dispatch the /// 'getMessageForX()' methods to construct a specific message. - virtual std::string getMessage(const ExplodedNode *N); + std::string getMessage(const ExplodedNode *N) override; /// Produces the message of the following form: /// 'Msg via Nth parameter' @@ -496,12 +502,12 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { /// 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. - OwningPtr<StackHintGenerator> CallStackHint; + std::unique_ptr<StackHintGenerator> CallStackHint; public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, - StackHintGenerator *stackHint = 0) + StackHintGenerator *stackHint = nullptr) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), CallStackHint(stackHint) {} @@ -520,10 +526,8 @@ public: bool isPrunable() const { return IsPrunable.hasValue() ? IsPrunable.getValue() : false; } - - bool hasCallStackHint() { - return CallStackHint.isValid(); - } + + 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. @@ -533,7 +537,7 @@ public: return ""; } - virtual void dump() const; + void dump() const override; static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; @@ -543,11 +547,11 @@ public: class PathDiagnosticCallPiece : public PathDiagnosticPiece { PathDiagnosticCallPiece(const Decl *callerD, const PathDiagnosticLocation &callReturnPos) - : PathDiagnosticPiece(Call), Caller(callerD), Callee(0), + : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr), NoExit(false), callReturn(callReturnPos) {} PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) - : PathDiagnosticPiece(Call), Caller(caller), Callee(0), + : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr), NoExit(true), path(oldPath) {} const Decl *Caller; @@ -579,7 +583,7 @@ public: CallStackMessage = st; } - virtual PathDiagnosticLocation getLocation() const { + PathDiagnosticLocation getLocation() const override { return callEnter; } @@ -588,7 +592,7 @@ public: getCallEnterWithinCallerEvent() const; IntrusiveRefCntPtr<PathDiagnosticEventPiece> getCallExitEvent() const; - virtual void flattenLocations() { + void flattenLocations() override { callEnter.flatten(); callReturn.flatten(); for (PathPieces::iterator I = path.begin(), @@ -601,10 +605,10 @@ public: static PathDiagnosticCallPiece *construct(PathPieces &pieces, const Decl *caller); - - virtual void dump() const; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void dump() const override; + + void Profile(llvm::FoldingSetNodeID &ID) const override; static inline bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Call; @@ -651,7 +655,7 @@ public: void push_back(const PathDiagnosticLocationPair &X) { LPairs.push_back(X); } - virtual PathDiagnosticLocation getLocation() const { + PathDiagnosticLocation getLocation() const override { return getStartLocation(); } @@ -659,7 +663,7 @@ public: iterator begin() { return LPairs.begin(); } iterator end() { return LPairs.end(); } - virtual void flattenLocations() { + void flattenLocations() override { for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); } @@ -672,9 +676,9 @@ public: return P->getKind() == ControlFlow; } - virtual void dump() const; + void dump() const override; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; }; class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { @@ -688,7 +692,7 @@ public: bool containsEvent() const; - virtual void flattenLocations() { + void flattenLocations() override { PathDiagnosticSpotPiece::flattenLocations(); for (PathPieces::iterator I = subPieces.begin(), E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); @@ -698,15 +702,16 @@ public: return P->getKind() == Macro; } - virtual void dump() const; + void dump() const override; - virtual void Profile(llvm::FoldingSetNodeID &ID) const; + 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; @@ -727,8 +732,8 @@ class PathDiagnostic : public llvm::FoldingSetNode { PathDiagnostic() LLVM_DELETED_FUNCTION; public: - PathDiagnostic(const Decl *DeclWithIssue, StringRef bugtype, - StringRef verboseDesc, StringRef shortDesc, + PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue, + StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique); @@ -785,6 +790,7 @@ public: StringRef getShortDescription() const { return ShortDesc.empty() ? VerboseDesc : ShortDesc; } + StringRef getCheckName() const { return CheckName; } StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index cf7cf051d225..b9a5b8a27fa9 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -453,14 +453,29 @@ public: } // end eval namespace class CheckerBase : public ProgramPointTag { + CheckName Name; + friend class ::clang::ento::CheckerManager; + public: - StringRef getTagDescription() const; + 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 CHECK2=check::_VoidCheck, typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, @@ -511,7 +526,7 @@ template <typename EVENT> class EventDispatcher { CheckerManager *Mgr; public: - EventDispatcher() : Mgr(0) { } + EventDispatcher() : Mgr(nullptr) { } template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 8ad67c118f01..b364115c99b6 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -16,8 +16,8 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LangOptions.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/Store.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> @@ -29,11 +29,11 @@ namespace clang { namespace ento { class CheckerBase; + class CheckerRegistry; class ExprEngine; class AnalysisManager; class BugReporter; class CheckerContext; - class SimpleCall; class ObjCMethodCall; class SVal; class ExplodedNode; @@ -132,9 +132,26 @@ enum PointerEscapeKind { 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() {} + CheckName(const CheckName &Other) : Name(Other.Name) {} + StringRef getName() const { return Name; } +}; + class CheckerManager { const LangOptions LangOpts; AnalyzerOptionsRef AOptions; + CheckName CurrentCheckName; + public: CheckerManager(const LangOptions &langOpts, AnalyzerOptionsRef AOptions) @@ -143,6 +160,9 @@ public: ~CheckerManager(); + void setCurrentCheckName(CheckName name) { CurrentCheckName = name; } + CheckName getCurrentCheckName() const { return CurrentCheckName; } + bool hasPathSensitiveCheckers() const; void finishedCheckerRegistration(); @@ -169,6 +189,7 @@ public: 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; @@ -183,6 +204,7 @@ public: 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; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 9502900f7e35..37be69aaba84 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_SA_CORE_APSINTTYPE_H #include "llvm/ADT/APSInt.h" +#include <tuple> namespace clang { namespace ento { @@ -97,13 +98,8 @@ public: /// Unsigned integers are considered to be better conversion types than /// signed integers of the same width. bool operator<(const APSIntType &Other) const { - if (BitWidth < Other.BitWidth) - return true; - if (BitWidth > Other.BitWidth) - return false; - if (!IsUnsigned && Other.IsUnsigned) - return true; - return false; + return std::tie(BitWidth, IsUnsigned) < + std::tie(Other.BitWidth, Other.IsUnsigned); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index d7d83ce8b17d..1a398b86484d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -65,8 +65,8 @@ public: StoreManagerCreator getStoreManagerCreator() { return CreateStoreMgr; } - - AnalyzerOptions& getAnalyzerOptions() { + + AnalyzerOptions& getAnalyzerOptions() override { return options; } @@ -76,15 +76,15 @@ public: CheckerManager *getCheckerManager() const { return CheckerMgr; } - virtual ASTContext &getASTContext() { + ASTContext &getASTContext() override { return Ctx; } - virtual SourceManager &getSourceManager() { + SourceManager &getSourceManager() override { return getASTContext().getSourceManager(); } - virtual DiagnosticsEngine &getDiagnostic() { + DiagnosticsEngine &getDiagnostic() override { return Diags; } @@ -92,7 +92,7 @@ public: return LangOpts; } - ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { + ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override { return PathConsumers; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 2c799c0db44e..08905fdf0783 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -79,9 +79,9 @@ class BasicValueFactory { const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); public: - BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator& Alloc) - : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(0), PersistentSValPairs(0), - SValListFactory(Alloc) {} + BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) + : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr), + PersistentSValPairs(nullptr), SValListFactory(Alloc) {} ~BasicValueFactory(); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index 2483a79455b2..0408070e493f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -16,9 +16,7 @@ #ifndef LLVM_CLANG_GR_BLOCKCOUNTER #define LLVM_CLANG_GR_BLOCKCOUNTER -namespace llvm { - class BumpPtrAllocator; -} +#include "llvm/Support/Allocator.h" namespace clang { @@ -35,7 +33,7 @@ class BlockCounter { BlockCounter(void *D) : Data(D) {} public: - BlockCounter() : Data(0) {} + BlockCounter() : Data(nullptr) {} unsigned getNumVisited(const StackFrameContext *CallSite, unsigned BlockID) const; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index cfaf085b5f34..4a5426b2747d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -33,9 +33,6 @@ namespace ento { enum CallEventKind { CE_Function, - CE_Block, - CE_BEG_SIMPLE_CALLS = CE_Function, - CE_END_SIMPLE_CALLS = CE_Block, CE_CXXMember, CE_CXXMemberOperator, CE_CXXDestructor, @@ -45,6 +42,7 @@ enum CallEventKind { CE_CXXAllocator, CE_BEG_FUNCTION_CALLS = CE_Function, CE_END_FUNCTION_CALLS = CE_CXXAllocator, + CE_Block, CE_ObjCMessage }; @@ -58,14 +56,14 @@ public: CallEventRef(const CallEventRef &Orig) : IntrusiveRefCntPtr<const T>(Orig) {} CallEventRef<T> cloneWithState(ProgramStateRef State) const { - return this->getPtr()->template cloneWithState<T>(State); + 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->getPtr(); + return this->get(); } }; @@ -88,15 +86,15 @@ class RuntimeDefinition { const MemRegion *R; public: - RuntimeDefinition(): D(0), R(0) {} - RuntimeDefinition(const Decl *InD): D(InD), R(0) {} + 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 != 0; } + bool mayHaveOtherDefinitions() { return R != nullptr; } /// When other definitions are possible, returns the region whose runtime type /// determines the method definition. @@ -239,7 +237,7 @@ public: /// \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 0; } + virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; } /// \brief Returns the source range for errors associated with this argument. /// @@ -295,20 +293,20 @@ public: const IdentifierInfo *getCalleeIdentifier() const { const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl()); if (!ND) - return 0; + return nullptr; return ND->getIdentifier(); } /// \brief Returns an appropriate ProgramPoint for this call. ProgramPoint getProgramPoint(bool IsPreVisit = false, - const ProgramPointTag *Tag = 0) const; + 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 = 0) const; + ProgramStateRef Orig = nullptr) const; typedef std::pair<Loc, SVal> FrameBindingTy; typedef SmallVectorImpl<FrameBindingTy> BindingsTy; @@ -344,23 +342,16 @@ public: // Iterator access to formal parameters and their types. private: typedef std::const_mem_fun_t<QualType, ParmVarDecl> get_type_fun; - -public: - typedef const ParmVarDecl * const *param_iterator; - /// Returns an iterator over the call's formal parameters. +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). - /// - /// 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; + virtual ArrayRef<ParmVarDecl*> parameters() const = 0; - typedef llvm::mapped_iterator<param_iterator, get_type_fun> + 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. @@ -369,17 +360,18 @@ public: /// definition because it represents a public interface, and probably has /// more annotations. param_type_iterator param_type_begin() const { - return llvm::map_iterator(param_begin(), + 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(param_end(), get_type_fun(&ParmVarDecl::getType)); + return llvm::map_iterator(parameters().end(), + get_type_fun(&ParmVarDecl::getType)); } // For debugging purposes only void dump(raw_ostream &Out) const; - LLVM_ATTRIBUTE_USED void dump() const; + void dump() const; }; @@ -398,11 +390,11 @@ protected: public: // This function is overridden by subclasses, but they must return // a FunctionDecl. - virtual const FunctionDecl *getDecl() const { + const FunctionDecl *getDecl() const override { return cast<FunctionDecl>(CallEvent::getDecl()); } - virtual RuntimeDefinition getRuntimeDefinition() const { + RuntimeDefinition getRuntimeDefinition() const override { const FunctionDecl *FD = getDecl(); // Note that the AnalysisDeclContext will have the FunctionDecl with // the definition (if one exists). @@ -417,13 +409,12 @@ public: return RuntimeDefinition(); } - virtual bool argumentsMayEscape() const; + bool argumentsMayEscape() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + ArrayRef<ParmVarDecl *> parameters() const override; static bool classof(const CallEvent *CA) { return CA->getKind() >= CE_BEG_FUNCTION_CALLS && @@ -431,49 +422,36 @@ public: } }; -/// \brief Represents a call to a non-C++ function, written as a CallExpr. -class SimpleCall : public AnyFunctionCall { +/// \brief Represents a C function or static C++ member function call. +/// +/// Example: \c fun() +class SimpleFunctionCall : public AnyFunctionCall { + friend class CallEventManager; + protected: - SimpleCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) + SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St, + const LocationContext *LCtx) : AnyFunctionCall(CE, St, LCtx) {} - SimpleCall(const SimpleCall &Other) : AnyFunctionCall(Other) {} + 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()); } - virtual const FunctionDecl *getDecl() const; + const FunctionDecl *getDecl() const override; - virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } - static bool classof(const CallEvent *CA) { - return CA->getKind() >= CE_BEG_SIMPLE_CALLS && - CA->getKind() <= CE_END_SIMPLE_CALLS; - } -}; - -/// \brief Represents a C function or static C++ member function call. -/// -/// Example: \c fun() -class FunctionCall : public SimpleCall { - friend class CallEventManager; - -protected: - FunctionCall(const CallExpr *CE, ProgramStateRef St, - const LocationContext *LCtx) - : SimpleCall(CE, St, LCtx) {} - - FunctionCall(const FunctionCall &Other) : SimpleCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) FunctionCall(*this); } - -public: - virtual Kind getKind() const { return CE_Function; } + Kind getKind() const override { return CE_Function; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_Function; @@ -483,47 +461,56 @@ public: /// \brief Represents a call to a block. /// /// Example: <tt>^{ /* ... */ }()</tt> -class BlockCall : public SimpleCall { +class BlockCall : public CallEvent { friend class CallEventManager; protected: BlockCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : SimpleCall(CE, St, LCtx) {} + : CallEvent(CE, St, LCtx) {} - BlockCall(const BlockCall &Other) : SimpleCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); } + BlockCall(const BlockCall &Other) : CallEvent(Other) {} + void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) 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; - /// \brief Gets the declaration of the block. - /// - /// This is not an override of getDecl() because AnyFunctionCall has already - /// assumed that it's a FunctionDecl. - const BlockDecl *getBlockDecl() const { + const BlockDecl *getDecl() const override { const BlockDataRegion *BR = getBlockRegion(); if (!BR) - return 0; + return nullptr; return BR->getDecl(); } - virtual RuntimeDefinition getRuntimeDefinition() const { - return RuntimeDefinition(getBlockDecl()); + RuntimeDefinition getRuntimeDefinition() const override { + return RuntimeDefinition(getDecl()); } - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + bool argumentsMayEscape() const override { + return true; + } - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual Kind getKind() const { return CE_Block; } + ArrayRef<ParmVarDecl*> parameters() const override; + + Kind getKind() const override { return CE_Block; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_Block; @@ -534,7 +521,7 @@ public: /// it is written. class CXXInstanceCall : public AnyFunctionCall { protected: - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) @@ -548,17 +535,17 @@ protected: public: /// \brief Returns the expression representing the implicit 'this' object. - virtual const Expr *getCXXThisExpr() const { return 0; } + virtual const Expr *getCXXThisExpr() const { return nullptr; } /// \brief Returns the value of the implicit 'this' object. virtual SVal getCXXThisVal() const; - virtual const FunctionDecl *getDecl() const; + const FunctionDecl *getDecl() const override; - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; static bool classof(const CallEvent *CA) { return CA->getKind() >= CE_BEG_CXX_INSTANCE_CALLS && @@ -578,28 +565,28 @@ protected: : CXXInstanceCall(CE, St, LCtx) {} CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXMemberCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); } public: virtual const CXXMemberCallExpr *getOriginExpr() const { return cast<CXXMemberCallExpr>(CXXInstanceCall::getOriginExpr()); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { if (const CallExpr *CE = getOriginExpr()) return CE->getNumArgs(); return 0; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } - virtual const Expr *getCXXThisExpr() const; - - virtual RuntimeDefinition getRuntimeDefinition() const; + const Expr *getCXXThisExpr() const override; - virtual Kind getKind() const { return CE_CXXMember; } + RuntimeDefinition getRuntimeDefinition() const override; + + Kind getKind() const override { return CE_CXXMember; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXMember; @@ -620,7 +607,7 @@ protected: CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { + void cloneTo(void *Dest) const override { new (Dest) CXXMemberOperatorCall(*this); } @@ -629,16 +616,16 @@ public: return cast<CXXOperatorCallExpr>(CXXInstanceCall::getOriginExpr()); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs() - 1; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index + 1); } - virtual const Expr *getCXXThisExpr() const; + const Expr *getCXXThisExpr() const override; - virtual Kind getKind() const { return CE_CXXMemberOperator; } + Kind getKind() const override { return CE_CXXMemberOperator; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXMemberOperator; @@ -671,23 +658,23 @@ protected: } CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXDestructorCall(*this); } + void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);} public: - virtual SourceRange getSourceRange() const { return Location; } - virtual unsigned getNumArgs() const { return 0; } + SourceRange getSourceRange() const override { return Location; } + unsigned getNumArgs() const override { return 0; } - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; /// \brief Returns the value of the implicit 'this' object. - virtual SVal getCXXThisVal() const; + SVal getCXXThisVal() const override; /// Returns true if this is a call to a base class destructor. bool isBaseDestructor() const { return DtorDataTy::getFromOpaqueValue(Data).getInt(); } - virtual Kind getKind() const { return CE_CXXDestructor; } + Kind getKind() const override { return CE_CXXDestructor; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXDestructor; @@ -715,32 +702,32 @@ protected: } CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} - virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; public: virtual const CXXConstructExpr *getOriginExpr() const { return cast<CXXConstructExpr>(AnyFunctionCall::getOriginExpr()); } - virtual const CXXConstructorDecl *getDecl() const { + const CXXConstructorDecl *getDecl() const override { return getOriginExpr()->getConstructor(); } - virtual unsigned getNumArgs() const { return getOriginExpr()->getNumArgs(); } + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } /// \brief Returns the value of the implicit 'this' object. SVal getCXXThisVal() const; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual Kind getKind() const { return CE_CXXConstructor; } + Kind getKind() const override { return CE_CXXConstructor; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_CXXConstructor; @@ -759,29 +746,29 @@ protected: : AnyFunctionCall(E, St, LCtx) {} CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) CXXAllocatorCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); } public: virtual const CXXNewExpr *getOriginExpr() const { return cast<CXXNewExpr>(AnyFunctionCall::getOriginExpr()); } - virtual const FunctionDecl *getDecl() const { + const FunctionDecl *getDecl() const override { return getOriginExpr()->getOperatorNew(); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumPlacementArgs() + 1; } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { // The first argument of an allocator call is the size of the allocation. if (Index == 0) - return 0; + return nullptr; return getOriginExpr()->getPlacementArg(Index - 1); } - virtual Kind getKind() const { return CE_CXXAllocator; } + Kind getKind() const override { return CE_CXXAllocator; } static bool classof(const CallEvent *CE) { return CE->getKind() == CE_CXXAllocator; @@ -810,13 +797,13 @@ protected: ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, const LocationContext *LCtx) : CallEvent(Msg, St, LCtx) { - Data = 0; + Data = nullptr; } ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {} - virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); } + void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); } - virtual void getExtraInvalidatedValues(ValueList &Values) const; + void getExtraInvalidatedValues(ValueList &Values) const override; /// Check if the selector may have multiple definitions (may have overrides). virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl, @@ -826,13 +813,13 @@ public: virtual const ObjCMessageExpr *getOriginExpr() const { return cast<ObjCMessageExpr>(CallEvent::getOriginExpr()); } - virtual const ObjCMethodDecl *getDecl() const { + const ObjCMethodDecl *getDecl() const override { return getOriginExpr()->getMethodDecl(); } - virtual unsigned getNumArgs() const { + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } - virtual const Expr *getArgExpr(unsigned Index) const { + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } @@ -846,7 +833,7 @@ public: return getOriginExpr()->getSelector(); } - virtual SourceRange getSourceRange() const; + SourceRange getSourceRange() const override; /// \brief Returns the value of the receiver at the time of this call. SVal getReceiverSVal() const; @@ -883,15 +870,16 @@ public: llvm_unreachable("Unknown message kind"); } - virtual RuntimeDefinition getRuntimeDefinition() const; + RuntimeDefinition getRuntimeDefinition() const override; - virtual void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, - BindingsTy &Bindings) const; + bool argumentsMayEscape() const override; + + void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const override; - virtual param_iterator param_begin() const; - virtual param_iterator param_end() const; + ArrayRef<ParmVarDecl*> parameters() const override; - virtual Kind getKind() const { return CE_ObjCMessage; } + Kind getKind() const override { return CE_ObjCMessage; } static bool classof(const CallEvent *CA) { return CA->getKind() == CE_ObjCMessage; @@ -911,6 +899,7 @@ class CallEventManager { llvm::BumpPtrAllocator &Alloc; SmallVector<void *, 8> Cache; + typedef SimpleFunctionCall CallEventTemplateTy; void reclaim(const void *Memory) { Cache.push_back(const_cast<void *>(Memory)); @@ -919,24 +908,30 @@ class CallEventManager { /// Returns memory that can be initialized as a CallEvent. void *allocate() { if (Cache.empty()) - return Alloc.Allocate<FunctionCall>(); + 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); } @@ -944,6 +939,8 @@ class CallEventManager { 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); } @@ -989,7 +986,8 @@ public: template <typename T> CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { assert(isa<T>(*this) && "Cloning to unrelated type"); - assert(sizeof(T) == sizeof(CallEvent) && "Subclasses may not add fields"); + static_assert(sizeof(T) == sizeof(CallEvent), + "Subclasses may not add fields"); if (NewState == State) return cast<T>(this); @@ -1026,7 +1024,7 @@ namespace llvm { static SimpleType getSimplifiedValue(clang::ento::CallEventRef<T> Val) { - return Val.getPtr(); + return Val.get(); } }; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 0b9762ac42e7..5a33bdf01b3c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -174,8 +174,13 @@ public: return Pred->getLocationContext()->getAnalysisDeclContext(); } - /// \brief If the given node corresponds to a PostStore program point, retrieve - /// the location region as it was uttered in the code. + /// \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. @@ -183,7 +188,7 @@ public: ProgramPoint L = N->getLocation(); if (Optional<PostStore> PSL = L.getAs<PostStore>()) return reinterpret_cast<const MemRegion*>(PSL->getLocationValue()); - return 0; + return nullptr; } /// \brief Get the value of arbitrary expressions at this point in the path. @@ -200,9 +205,9 @@ public: /// 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 = 0, - const ProgramPointTag *Tag = 0) { - return addTransitionImpl(State ? State : getState(), false, 0, Tag); + 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. @@ -214,15 +219,15 @@ public: /// @param Tag The tag to uniquely identify the creation site. ExplodedNode *addTransition(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0) { + const ProgramPointTag *Tag = nullptr) { return addTransitionImpl(State, false, Pred, Tag); } /// \brief Generate a sink node. Generating a sink stops exploration of the /// given path. - ExplodedNode *generateSink(ProgramStateRef State = 0, - ExplodedNode *Pred = 0, - const ProgramPointTag *Tag = 0) { + ExplodedNode *generateSink(ProgramStateRef State = nullptr, + ExplodedNode *Pred = nullptr, + const ProgramPointTag *Tag = nullptr) { return addTransitionImpl(State ? State : getState(), true, Pred, Tag); } @@ -244,7 +249,7 @@ public: if (FunDecl) return FunDecl->getIdentifier(); else - return 0; + return nullptr; } /// \brief Get the name of the called function (path-sensitive). @@ -280,8 +285,8 @@ public: private: ExplodedNode *addTransitionImpl(ProgramStateRef State, bool MarkAsSink, - ExplodedNode *P = 0, - const ProgramPointTag *Tag = 0) { + ExplodedNode *P = nullptr, + const ProgramPointTag *Tag = nullptr) { if (!State || (State == Pred->getState() && !Tag && !MarkAsSink)) return Pred; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 1e76ea6ed647..51bb89b9e1f9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -85,7 +85,7 @@ public: // does not. Is there a good equivalent there? assert(assume(State, Cond, false) && "System is over constrained."); #endif - return ProgramStatePair((ProgramStateRef)NULL, State); + return ProgramStatePair((ProgramStateRef)nullptr, State); } ProgramStateRef StFalse = assume(State, Cond, false); @@ -93,7 +93,7 @@ public: // 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)NULL); + return ProgramStatePair(State, (ProgramStateRef)nullptr); } return ProgramStatePair(StTrue, StFalse); @@ -106,7 +106,7 @@ public: /// value for a symbol, even if it is perfectly constrained. virtual const llvm::APSInt* getSymVal(ProgramStateRef state, SymbolRef sym) const { - return 0; + return nullptr; } virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index a2e211edea8b..76ace6d7cc2a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -21,7 +21,7 @@ #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" -#include "llvm/ADT/OwningPtr.h" +#include <memory> namespace clang { @@ -60,12 +60,12 @@ private: SubEngine& SubEng; /// G - The simulation graph. Each node is a (location,state) pair. - OwningPtr<ExplodedGraph> G; + std::unique_ptr<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. - OwningPtr<WorkList> WList; + 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 @@ -120,7 +120,7 @@ public: /// takeGraph - Returns the exploded graph. Ownership of the graph is /// transferred to the caller. - ExplodedGraph* takeGraph() { return G.take(); } + ExplodedGraph *takeGraph() { return G.release(); } /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. @@ -312,7 +312,7 @@ public: /// \class NodeBuilderWithSinks /// \brief This node builder keeps track of the generated sink nodes. class NodeBuilderWithSinks: public NodeBuilder { - virtual void anchor(); + void anchor() override; protected: SmallVector<ExplodedNode*, 2> sinksGenerated; ProgramPoint &Location; @@ -324,13 +324,13 @@ public: ExplodedNode *generateNode(ProgramStateRef State, ExplodedNode *Pred, - const ProgramPointTag *Tag = 0) { + 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 = 0) { + const ProgramPointTag *Tag = nullptr) { const ProgramPoint &LocalLoc = (Tag ? Location.withTag(Tag) : Location); ExplodedNode *N = NodeBuilder::generateSink(LocalLoc, State, Pred); if (N && N->isSink()) @@ -355,14 +355,16 @@ public: /// 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 = 0) + 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 = 0) + const NodeBuilderContext &Ctx, + NodeBuilder *Enclosing = nullptr) : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { if (EnclosingBldr) for (ExplodedNodeSet::iterator I = SrcSet.begin(), @@ -378,7 +380,7 @@ public: ExplodedNode *generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, - const ProgramPointTag *tag = 0, + const ProgramPointTag *tag = nullptr, ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); @@ -388,7 +390,7 @@ public: ExplodedNode *generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, - const ProgramPointTag *tag = 0, + const ProgramPointTag *tag = nullptr, ProgramPoint::Kind K = ProgramPoint::PostStmtKind){ const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, Pred->getLocationContext(), tag); @@ -399,7 +401,7 @@ public: /// \brief BranchNodeBuilder is responsible for constructing the nodes /// corresponding to the two branches of the if statement - true and false. class BranchNodeBuilder: public NodeBuilder { - virtual void anchor(); + void anchor() override; const CFGBlock *DstT; const CFGBlock *DstF; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index bf17cd807d65..98092ef00db7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -27,11 +27,11 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" -#include "llvm/ADT/OwningPtr.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 { @@ -164,7 +164,7 @@ public: const ProgramStateRef &state, bool IsSink) { ID.Add(Loc); - ID.AddPointer(state.getPtr()); + ID.AddPointer(state.get()); ID.AddBoolean(IsSink); } @@ -189,7 +189,7 @@ public: } ExplodedNode *getFirstPred() { - return pred_empty() ? NULL : *(pred_begin()); + return pred_empty() ? nullptr : *(pred_begin()); } const ExplodedNode *getFirstPred() const { @@ -197,7 +197,7 @@ public: } const ExplodedNode *getFirstSucc() const { - return succ_empty() ? NULL : *(succ_begin()); + return succ_empty() ? nullptr : *(succ_begin()); } // Iterators over successor and predecessor vertices. @@ -295,7 +295,7 @@ public: /// the node was freshly created. ExplodedNode *getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink = false, - bool* IsNew = 0); + bool* IsNew = nullptr); ExplodedGraph* MakeEmptyGraph() const { return new ExplodedGraph(); @@ -373,8 +373,8 @@ public: /// nodes in this graph. /// \returns The trimmed graph ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes, - InterExplodedGraphMap *ForwardMap = 0, - InterExplodedGraphMap *InverseMap = 0) const; + InterExplodedGraphMap *ForwardMap = nullptr, + InterExplodedGraphMap *InverseMap = nullptr) const; /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index d89dffe63b0a..0fb4a245916f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -43,7 +43,6 @@ namespace ento { class AnalysisManager; class CallEvent; -class SimpleCall; class CXXConstructorCall; class ExprEngine : public SubEngine { @@ -107,7 +106,7 @@ public: /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps = 150000) { - return Engine.ExecuteWorkList(L, Steps, 0); + return Engine.ExecuteWorkList(L, Steps, nullptr); } /// Execute the work list with an initial state. Nodes that reaches the exit @@ -123,7 +122,7 @@ public: /// getContext - Return the ASTContext associated with this analysis. ASTContext &getContext() const { return AMgr.getASTContext(); } - virtual AnalysisManager &getAnalysisManager() { return AMgr; } + AnalysisManager &getAnalysisManager() override { return AMgr; } CheckerManager &getCheckerManager() const { return *AMgr.getCheckerManager(); @@ -155,7 +154,7 @@ public: /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. - ProgramStateRef getInitialState(const LocationContext *InitLoc); + ProgramStateRef getInitialState(const LocationContext *InitLoc) override; ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } @@ -187,13 +186,13 @@ public: /// and \p ReferenceStmt must be valid (non-null). void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, - const Stmt *DiagnosticStmt = 0, + 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); + unsigned StmtIdx, NodeBuilderContext *Ctx) override; void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); @@ -201,7 +200,9 @@ public: void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred); - void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, + 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); @@ -213,10 +214,10 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst); /// Called by CoreEngine when processing the entrance of a CFGBlock. - virtual void processCFGBlockEntrance(const BlockEdge &L, - NodeBuilderWithSinks &nodeBuilder, - ExplodedNode *Pred); - + 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, @@ -224,7 +225,7 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, - const CFGBlock *DstF); + const CFGBlock *DstF) override; /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. @@ -233,20 +234,20 @@ public: ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, - const CFGBlock *DstF); + 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); + 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); + 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); + ExplodedNode *Pred) override; /// Remove dead bindings/symbols before exiting a function. void removeDeadOnEndOfFunction(NodeBuilderContext& BC, @@ -254,22 +255,23 @@ public: ExplodedNodeSet &Dst); /// Generate the entry node of the callee. - void processCallEnter(CallEnter CE, ExplodedNode *Pred); + 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); + void processCallExit(ExplodedNode *Pred) override; /// Called by CoreEngine when the analysis worklist has terminated. - void processEndWorklist(bool hasWorkRemaining); + 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); + 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); + 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. @@ -278,13 +280,13 @@ public: const InvalidatedSymbols *invalidated, ArrayRef<const MemRegion *> ExplicitRegions, ArrayRef<const MemRegion *> Regions, - const CallEvent *Call); + 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); + const char *NL, const char *Sep) override; - virtual ProgramStateManager& getStateManager() { return StateMgr; } + ProgramStateManager& getStateManager() override { return StateMgr; } StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } @@ -420,6 +422,10 @@ public: 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); @@ -471,21 +477,21 @@ protected: /// 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 = 0); + const ProgramPoint *PP = nullptr); /// Call PointerEscape callback when a value escapes as a result of bind. ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, - SVal Loc, SVal Val); + 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); + 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 @@ -500,14 +506,14 @@ public: ExplodedNode *Pred, ProgramStateRef St, SVal location, - const ProgramPointTag *tag = 0, + 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 = 0); + const ProgramPointTag *tag = nullptr); /// \brief Create a new state in which the call return value is binded to the /// call origin expression. @@ -580,7 +586,7 @@ private: ProgramStateRef createTemporaryRegionIfNeeded(ProgramStateRef State, const LocationContext *LC, const Expr *E, - const Expr *ResultE = 0); + const Expr *ResultE = nullptr); }; /// Traits for storing the call processing policy inside GDM. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index cc790c1b6b39..92b082d5215c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -23,13 +23,10 @@ #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 llvm { -class BumpPtrAllocator; -} - namespace clang { class LocationContext; @@ -57,7 +54,7 @@ public: // Visual Studio will only create enumerations of size int, not long long. static const int64_t Symbolic = INT64_MAX; - RegionOffset() : R(0) {} + RegionOffset() : R(nullptr) {} RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} const MemRegion *getRegion() const { return R; } @@ -204,12 +201,12 @@ protected: assert(classof(this)); } - MemRegionManager* getMemRegionManager() const { return Mgr; } + MemRegionManager* getMemRegionManager() const override { return Mgr; } public: - bool isBoundable() const { return false; } - - void Profile(llvm::FoldingSetNodeID &ID) const; + bool isBoundable() const override { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -243,9 +240,9 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} public: - void Profile(llvm::FoldingSetNodeID &ID) const; - - void dumpToStream(raw_ostream &os) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; + + void dumpToStream(raw_ostream &os) const override; const CodeTextRegion *getCodeRegion() const { return CR; } @@ -286,7 +283,7 @@ class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalSystemSpaceRegionKind; @@ -306,7 +303,7 @@ class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalImmutableSpaceRegionKind; @@ -324,7 +321,7 @@ class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == GlobalInternalSpaceRegionKind; @@ -339,7 +336,7 @@ class HeapSpaceRegion : public MemSpaceRegion { : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == HeapSpaceRegionKind; @@ -353,7 +350,7 @@ class UnknownSpaceRegion : public MemSpaceRegion { : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == UnknownSpaceRegionKind; @@ -373,7 +370,7 @@ protected: public: const StackFrameContext *getStackFrame() const { return SFC; } - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *R) { Kind k = R->getKind(); @@ -389,7 +386,7 @@ class StackLocalsSpaceRegion : public StackSpaceRegion { : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == StackLocalsSpaceRegionKind; @@ -404,7 +401,7 @@ private: : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} public: - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { return R->getKind() == StackArgumentsSpaceRegionKind; @@ -430,9 +427,9 @@ public: return UnknownVal(); } - MemRegionManager* getMemRegionManager() const; + MemRegionManager* getMemRegionManager() const override; - virtual bool isSubRegionOf(const MemRegion* R) const; + bool isSubRegionOf(const MemRegion* R) const override; static bool classof(const MemRegion* R) { return R->getKind() > END_MEMSPACES; @@ -459,16 +456,16 @@ public: const Expr *getExpr() const { return Ex; } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + 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; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == AllocaRegionKind; @@ -478,7 +475,7 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { public: - virtual void anchor(); + void anchor() override; protected: TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {} @@ -489,7 +486,7 @@ public: return getLocationType().getDesugaredType(Context); } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -500,14 +497,14 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { public: - virtual void anchor(); + void anchor() override; protected: TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {} public: virtual QualType getValueType() const = 0; - virtual QualType getLocationType() const { + QualType getLocationType() const override { // FIXME: We can possibly optimize this later to cache this value. QualType T = getValueType(); ASTContext &ctx = getContext(); @@ -521,7 +518,7 @@ public: return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -532,12 +529,12 @@ public: class CodeTextRegion : public TypedRegion { public: - virtual void anchor(); + void anchor() override; protected: CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: - bool isBoundable() const { return false; } - + bool isBoundable() const override { return false; } + static bool classof(const MemRegion* R) { Kind k = R->getKind(); return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; @@ -552,8 +549,8 @@ public: : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) { assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); } - - QualType getLocationType() const { + + QualType getLocationType() const override { const ASTContext &Ctx = getContext(); if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { return Ctx.getPointerType(D->getType()); @@ -570,11 +567,11 @@ public: const NamedDecl *getDecl() const { return FD; } - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) const; - + + 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*); @@ -602,7 +599,7 @@ class BlockTextRegion : public CodeTextRegion { : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} public: - QualType getLocationType() const { + QualType getLocationType() const override { return locTy; } @@ -611,11 +608,11 @@ public: } AnalysisDeclContext *getAnalysisDeclContext() const { return AC; } - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) const; - + + virtual 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*); @@ -643,15 +640,15 @@ class BlockDataRegion : public TypedRegion { unsigned count, const MemRegion *sreg) : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), BlockCount(count), - ReferencedVars(0), OriginalVars(0) {} + ReferencedVars(nullptr), OriginalVars(nullptr) {} public: const BlockTextRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } - QualType getLocationType() const { return BC->getLocationType(); } - + QualType getLocationType() const override { return BC->getLocationType(); } + class referenced_vars_iterator { const MemRegion * const *R; const MemRegion * const *OriginalR; @@ -668,11 +665,11 @@ public: } bool operator==(const referenced_vars_iterator &I) const { - assert((R == 0) == (I.R == 0)); + assert((R == nullptr) == (I.R == nullptr)); return I.R == R; } bool operator!=(const referenced_vars_iterator &I) const { - assert((R == 0) == (I.R == 0)); + assert((R == nullptr) == (I.R == nullptr)); return I.R != R; } referenced_vars_iterator &operator++() { @@ -688,11 +685,11 @@ public: referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; - - virtual void dumpToStream(raw_ostream &os) const; - - void Profile(llvm::FoldingSetNodeID& ID) 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 *); @@ -723,17 +720,17 @@ public: return sym; } - bool isBoundable() const { return true; } + bool isBoundable() const override { return true; } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, const MemRegion* superRegion); - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == SymbolicRegionKind; @@ -757,19 +754,19 @@ public: const StringLiteral* getStringLiteral() const { return Str; } - QualType getValueType() const { + QualType getValueType() const override { return Str->getType(); } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - bool isBoundable() const { return false; } + bool isBoundable() const override { return false; } - void Profile(llvm::FoldingSetNodeID& ID) const { + void Profile(llvm::FoldingSetNodeID& ID) const override { ProfileRegion(ID, Str, superRegion); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == StringRegionKind; @@ -792,19 +789,19 @@ protected: public: const ObjCStringLiteral* getObjCStringLiteral() const { return Str; } - - QualType getValueType() const { + + QualType getValueType() const override { return Str->getType(); } - - bool isBoundable() const { return false; } - - void Profile(llvm::FoldingSetNodeID& ID) const { + + bool isBoundable() const override { return false; } + + void Profile(llvm::FoldingSetNodeID& ID) const override { ProfileRegion(ID, Str, superRegion); } - - void dumpToStream(raw_ostream &os) const; - + + void dumpToStream(raw_ostream &os) const override; + static bool classof(const MemRegion* R) { return R->getKind() == ObjCStringRegionKind; } @@ -825,15 +822,15 @@ private: const CompoundLiteralExpr *CL, const MemRegion* superRegion); public: - QualType getValueType() const { + QualType getValueType() const override { return CL->getType(); } - bool isBoundable() const { return !CL->isFileScope(); } + bool isBoundable() const override { return !CL->isFileScope(); } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const CompoundLiteralExpr *getLiteralExpr() const { return CL; } @@ -854,7 +851,7 @@ protected: public: const Decl *getDecl() const { return D; } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static bool classof(const MemRegion* R) { unsigned k = R->getKind(); @@ -874,27 +871,27 @@ class VarRegion : public DeclRegion { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); } - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } const StackFrameContext *getStackFrame() const; - - QualType getValueType() const { + + QualType getValueType() const override { // FIXME: We can cache this if needed. return getDecl()->getType(); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == VarRegionKind; } - bool canPrintPrettyAsExpr() const; + bool canPrintPrettyAsExpr() const override; - void printPrettyAsExpr(raw_ostream &os) const; + void printPrettyAsExpr(raw_ostream &os) const override; }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -910,15 +907,15 @@ class CXXThisRegion : public TypedValueRegion { const PointerType *PT, const MemRegion *sReg); - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; -public: - QualType getValueType() const { +public: + QualType getValueType() const override { return QualType(ThisPointerTy, 0); } - void dumpToStream(raw_ostream &os) const; - + void dumpToStream(raw_ostream &os) const override; + static bool classof(const MemRegion* R) { return R->getKind() == CXXThisRegionKind; } @@ -936,12 +933,12 @@ class FieldRegion : public DeclRegion { public: const FieldDecl *getDecl() const { return cast<FieldDecl>(D); } - QualType getValueType() const { + QualType getValueType() const override { // FIXME: We can cache this if needed. return getDecl()->getType(); } - DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const; + DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, const MemRegion* superRegion) { @@ -952,12 +949,12 @@ public: return R->getKind() == FieldRegionKind; } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - bool canPrintPretty() const; - void printPretty(raw_ostream &os) const; - bool canPrintPrettyAsExpr() const; - void printPrettyAsExpr(raw_ostream &os) const; + 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 { @@ -971,12 +968,12 @@ class ObjCIvarRegion : public DeclRegion { public: const ObjCIvarDecl *getDecl() const; - QualType getValueType() const; + QualType getValueType() const override; - bool canPrintPrettyAsExpr() const; - void printPrettyAsExpr(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const override; + void printPrettyAsExpr(raw_ostream &os) const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion* R) { return R->getKind() == ObjCIvarRegionKind; @@ -1029,7 +1026,7 @@ public: NonLoc getIndex() const { return Index; } - QualType getValueType() const { + QualType getValueType() const override { return ElementType; } @@ -1039,9 +1036,9 @@ public: /// Compute the offset within the array. The array might also be a subobject. RegionRawOffset getAsArrayOffset() const; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID& ID) const; + void Profile(llvm::FoldingSetNodeID& ID) const override; static bool classof(const MemRegion* R) { return R->getKind() == ElementRegionKind; @@ -1063,13 +1060,13 @@ class CXXTempObjectRegion : public TypedValueRegion { public: const Expr *getExpr() const { return Ex; } - QualType getValueType() const { + QualType getValueType() const override { return Ex->getType(); } - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion* R) { return R->getKind() == CXXTempObjectRegionKind; @@ -1094,19 +1091,19 @@ public: const CXXRecordDecl *getDecl() const { return Data.getPointer(); } bool isVirtual() const { return Data.getInt(); } - QualType getValueType() const; + QualType getValueType() const override; - void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - void Profile(llvm::FoldingSetNodeID &ID) const; + void Profile(llvm::FoldingSetNodeID &ID) const override; static bool classof(const MemRegion *region) { return region->getKind() == CXXBaseObjectRegionKind; } - bool canPrintPrettyAsExpr() const; - - void printPrettyAsExpr(raw_ostream &os) const; + bool canPrintPrettyAsExpr() const override; + + void printPrettyAsExpr(raw_ostream &os) const override; }; template<typename RegionTy> @@ -1114,7 +1111,7 @@ const RegionTy* MemRegion::getAs() const { if (const RegionTy* RT = dyn_cast<RegionTy>(this)) return RT; - return NULL; + return nullptr; } //===----------------------------------------------------------------------===// @@ -1143,9 +1140,10 @@ class MemRegionManager { MemSpaceRegion *code; public: - MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0), - heap(0), unknown(0), code(0) {} + MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) + : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr), + ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr), + code(nullptr) {} ~MemRegionManager(); @@ -1167,7 +1165,7 @@ public: /// global variables. const GlobalsSpaceRegion *getGlobalsRegion( MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind, - const CodeTextRegion *R = 0); + const CodeTextRegion *R = nullptr); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 03739ed9284d..4902ef50c7fe 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -25,10 +25,10 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/Support/Allocator.h" namespace llvm { class APSInt; -class BumpPtrAllocator; } namespace clang { @@ -237,16 +237,16 @@ public: ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, - bool CausesPointerEscape, InvalidatedSymbols *IS = 0, - const CallEvent *Call = 0, - RegionAndSymbolInvalidationTraits *ITraits = 0) const; + 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 = 0, - const CallEvent *Call = 0, - RegionAndSymbolInvalidationTraits *ITraits = 0) const; + 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. @@ -441,8 +441,8 @@ private: SubEngine *Eng; /* Can be null. */ EnvironmentManager EnvMgr; - OwningPtr<StoreManager> StoreMgr; - OwningPtr<ConstraintManager> ConstraintMgr; + std::unique_ptr<StoreManager> StoreMgr; + std::unique_ptr<ConstraintManager> ConstraintMgr; ProgramState::GenericDataMap::Factory GDMFactory; @@ -454,10 +454,10 @@ private: llvm::FoldingSet<ProgramState> StateSet; /// Object that manages the data for all created SVals. - OwningPtr<SValBuilder> svalBuilder; + std::unique_ptr<SValBuilder> svalBuilder; /// Manages memory for created CallEvents. - OwningPtr<CallEventManager> CallEventMgr; + std::unique_ptr<CallEventManager> CallEventMgr; /// A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator &Alloc; @@ -676,10 +676,8 @@ inline SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const { inline SVal ProgramState::getLValue(const IndirectFieldDecl *D, SVal Base) const { StoreManager &SM = *getStateManager().StoreMgr; - for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), - E = D->chain_end(); - I != E; ++I) { - Base = SM.getLValueField(cast<FieldDecl>(*I), Base); + for (const auto *I : D->chain()) { + Base = SM.getLValueField(cast<FieldDecl>(I), Base); } return Base; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index eb52ae47bdf2..823bde798e55 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -18,10 +18,10 @@ #ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H #define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H +#include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" namespace llvm { - class BumpPtrAllocator; template <typename K, typename D, typename I> class ImmutableMap; template <typename K, typename I> class ImmutableSet; template <typename T> class ImmutableList; @@ -64,7 +64,8 @@ namespace ento { 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(0); + return p ? data_type((typename data_type::TreeTy*) *p) + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type B) { return B.getRoot(); @@ -112,7 +113,8 @@ namespace ento { typedef Key key_type; static inline data_type MakeData(void *const* p) { - return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); + return p ? data_type((typename data_type::TreeTy*) *p) + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type B) { @@ -163,7 +165,7 @@ namespace ento { static inline data_type MakeData(void *const* p) { return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) - : data_type(0); + : data_type(nullptr); } static inline void *MakeVoidPtr(data_type D) { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index c5d0a92cabdd..29fb413d1ce7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -88,7 +88,7 @@ public: virtual SVal evalComplement(NonLoc val) = 0; - /// Create a new value which represents a binary expression with two non + /// 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; @@ -99,7 +99,7 @@ public: 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 + /// 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; @@ -146,14 +146,14 @@ public: const LocationContext *LCtx, QualType type, unsigned visitCount, - const void *symbolTag = 0) { + 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 = 0) { + const void *symbolTag = nullptr) { return SymMgr.conjureSymbol(expr, LCtx, visitCount, symbolTag); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 5a426ef00197..d50c3be4bf5d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -63,11 +63,11 @@ protected: explicit SVal(const void *d, bool isLoc, unsigned ValKind) : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} - explicit SVal(BaseKind k, const void *D = NULL) + explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {} public: - explicit SVal() : Data(0), Kind(0) {} + explicit SVal() : Data(nullptr), Kind(0) {} /// \brief Convert to the specified SVal type, asserting that this SVal is of /// the desired type. @@ -211,7 +211,7 @@ protected: explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) : SVal(d, isLoc, ValKind) {} - explicit DefinedOrUnknownSVal(BaseKind k, void *D = NULL) + explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} private: diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 530dae59892a..84c31661212f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -220,10 +220,11 @@ public: bool First; public: - FindUniqueBinding(SymbolRef sym) : Sym(sym), Binding(0), First(true) {} + FindUniqueBinding(SymbolRef sym) + : Sym(sym), Binding(nullptr), First(true) {} bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, - SVal val); + SVal val) override; 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 f653c70a30f3..3482e8d27dbb 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -122,7 +122,7 @@ public: inline ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion* MR) { - return processRegionChanges(state, 0, MR, MR, 0); + return processRegionChanges(state, nullptr, MR, MR, nullptr); } virtual ProgramStateRef diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 914b2bea2d16..2b5cc18c9a29 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -23,12 +23,9 @@ #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 llvm { -class BumpPtrAllocator; -} - namespace clang { class ASTContext; class StackFrameContext; @@ -105,7 +102,7 @@ typedef unsigned SymbolID; /// \brief A symbol representing data which can be stored in a memory location /// (region). class SymbolData : public SymExpr { - virtual void anchor(); + void anchor() override; const SymbolID Sym; protected: @@ -138,13 +135,13 @@ public: profile.AddPointer(R); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R); } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; - QualType getType() const; + QualType getType() const override; // Implement isa<T> support. static inline bool classof(const SymExpr *SE) { @@ -173,9 +170,9 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return SymbolTag; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const Stmt *S, QualType T, unsigned Count, const LocationContext *LCtx, @@ -188,7 +185,7 @@ public: profile.AddPointer(SymbolTag); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, S, T, Count, LCtx, SymbolTag); } @@ -211,9 +208,9 @@ public: SymbolRef getParentSymbol() const { return parentSymbol; } const TypedValueRegion *getRegion() const { return R; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, SymbolRef parent, const TypedValueRegion *r) { @@ -222,7 +219,7 @@ public: profile.AddPointer(parent); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, parentSymbol, R); } @@ -244,16 +241,16 @@ public: const SubRegion *getRegion() const { return R; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { profile.AddInteger((unsigned) ExtentKind); profile.AddPointer(R); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R); } @@ -283,9 +280,9 @@ public: unsigned getCount() const { return Count; } const void *getTag() const { return Tag; } - QualType getType() const; + QualType getType() const override; - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& profile, const MemRegion *R, const Stmt *S, QualType T, unsigned Count, @@ -298,7 +295,7 @@ public: profile.AddPointer(Tag); } - virtual void Profile(llvm::FoldingSetNodeID& profile) { + void Profile(llvm::FoldingSetNodeID& profile) override { Profile(profile, R, S, T, Count, Tag); } @@ -320,11 +317,11 @@ public: SymbolCast(const SymExpr *In, QualType From, QualType To) : SymExpr(CastSymbolKind), Operand(In), FromTy(From), ToTy(To) { } - QualType getType() const { return ToTy; } + QualType getType() const override { return ToTy; } const SymExpr *getOperand() const { return Operand; } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *In, QualType From, QualType To) { @@ -334,7 +331,7 @@ public: ID.Add(To); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, Operand, FromTy, ToTy); } @@ -356,7 +353,7 @@ protected: public: // FIXME: We probably need to make this out-of-line to avoid redundant // generation of virtual functions. - QualType getType() const { return T; } + QualType getType() const override { return T; } BinaryOperator::Opcode getOpcode() const { return Op; } @@ -377,7 +374,7 @@ public: const llvm::APSInt& rhs, QualType t) : BinarySymExpr(SymIntKind, op, t), LHS(lhs), RHS(rhs) {} - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const SymExpr *getLHS() const { return LHS; } const llvm::APSInt &getRHS() const { return RHS; } @@ -392,7 +389,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -412,7 +409,7 @@ public: const SymExpr *rhs, QualType t) : BinarySymExpr(IntSymKind, op, t), LHS(lhs), RHS(rhs) {} - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; const SymExpr *getRHS() const { return RHS; } const llvm::APSInt &getLHS() const { return LHS; } @@ -427,7 +424,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -450,7 +447,7 @@ public: const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } - virtual void dumpToStream(raw_ostream &os) const; + void dumpToStream(raw_ostream &os) const override; static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { @@ -461,7 +458,7 @@ public: ID.Add(t); } - void Profile(llvm::FoldingSetNodeID& ID) { + void Profile(llvm::FoldingSetNodeID& ID) override { Profile(ID, LHS, getOpcode(), RHS, getType()); } @@ -501,12 +498,12 @@ public: const LocationContext *LCtx, QualType T, unsigned VisitCount, - const void *SymbolTag = 0); + const void *SymbolTag = nullptr); const SymbolConjured* conjureSymbol(const Expr *E, const LocationContext *LCtx, unsigned VisitCount, - const void *SymbolTag = 0) { + const void *SymbolTag = nullptr) { return conjureSymbol(E, LCtx, E->getType(), VisitCount, SymbolTag); } @@ -519,9 +516,9 @@ public: /// /// 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, + const SymbolMetadata *getMetadataSymbol(const MemRegion *R, const Stmt *S, QualType T, unsigned VisitCount, - const void *SymbolTag = 0); + const void *SymbolTag = nullptr); const SymbolCast* getCastSymbol(const SymExpr *Operand, QualType From, QualType To); @@ -590,7 +587,7 @@ public: SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr, StoreManager &storeMgr) : LCtx(Ctx), Loc(s), SymMgr(symmgr), - reapedStore(0, storeMgr) {} + reapedStore(nullptr, storeMgr) {} ~SymbolReaper() {} diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index d12a1514898f..3ed145dbd2b6 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -42,7 +42,7 @@ public: explicit WorkListUnit(ExplodedNode *N, BlockCounter C) : node(N), counter(C), - block(NULL), + block(nullptr), blockIdx(0) {} /// Returns the node associated with the worklist unit. diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h new file mode 100644 index 000000000000..30e5d3dd9a2b --- /dev/null +++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -0,0 +1,49 @@ +//===--- 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_GR_ANALYSISCONSUMER_H +#define LLVM_CLANG_GR_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; + +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.) +AnalysisASTConsumer *CreateAnalysisConsumer(const Preprocessor &pp, + const std::string &output, + AnalyzerOptionsRef opts, + ArrayRef<std::string> plugins); + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 838ac925533f..21ecfc234fbe 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -22,8 +22,8 @@ namespace ento { class AnalysisAction : public ASTFrontendAction { protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile); + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins); |