diff options
4 files changed, 336 insertions, 320 deletions
diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 2043896fd26..cb70c321cd8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -1,4 +1,4 @@ -//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===// +//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,20 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H +#include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include <memory> namespace clang { + +class BinaryOperator; class CFGBlock; +class DeclRefExpr; +class Expr; +class Stmt; namespace ento { @@ -99,7 +108,7 @@ class FindLastStoreBRVisitor final : public BugReporterVisitorImpl<FindLastStoreBRVisitor> { const MemRegion *R; SVal V; - bool Satisfied; + bool Satisfied = false; /// If the visitor is tracking the value directly responsible for the /// bug, we are going to employ false positive suppression. @@ -113,10 +122,7 @@ public: FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R, bool InEnableNullFPSuppression) - : R(R), - V(V), - Satisfied(false), - EnableNullFPSuppression(InEnableNullFPSuppression) {} + : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {} void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -130,18 +136,17 @@ class TrackConstraintBRVisitor final : public BugReporterVisitorImpl<TrackConstraintBRVisitor> { DefinedSVal Constraint; bool Assumption; - bool IsSatisfied; + bool IsSatisfied = false; bool IsZeroCheck; /// We should start tracking from the last node along the path in which the /// value is constrained. - bool IsTrackingTurnedOn; + bool IsTrackingTurnedOn = false; public: TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) - : Constraint(constraint), Assumption(assumption), IsSatisfied(false), - IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), - IsTrackingTurnedOn(false) {} + : Constraint(constraint), Assumption(assumption), + IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {} void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -157,7 +162,6 @@ public: private: /// Checks if the constraint is valid in the current state. bool isUnderconstrained(const ExplodedNode *N) const; - }; /// \class NilReceiverBRVisitor @@ -165,7 +169,6 @@ private: class NilReceiverBRVisitor final : public BugReporterVisitorImpl<NilReceiverBRVisitor> { public: - void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); @@ -184,7 +187,6 @@ public: /// Visitor that tries to report interesting diagnostics from conditions. class ConditionBRVisitor final : public BugReporterVisitorImpl<ConditionBRVisitor> { - // FIXME: constexpr initialization isn't supported by MSVC2013. static const char *const GenericTrueMessage; static const char *const GenericFalseMessage; @@ -277,7 +279,6 @@ public: /// if the region's contents are not modified/accessed by the call. class UndefOrNullArgVisitor final : public BugReporterVisitorImpl<UndefOrNullArgVisitor> { - /// The interesting memory region this visitor is tracking. const MemRegion *R; @@ -303,14 +304,14 @@ class SuppressInlineDefensiveChecksVisitor final DefinedSVal V; /// Track if we found the node where the constraint was first added. - bool IsSatisfied; + bool IsSatisfied = false; /// Since the visitors can be registered on nodes previous to the last /// node in the BugReport, but the path traversal always starts with the last /// node, the visitor invariant (that we start with a node in which V is null) /// might not hold when node visitation starts. We are going to start tracking /// from the last node in which the value is null. - bool IsTrackingTurnedOn; + bool IsTrackingTurnedOn = false; public: SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); @@ -328,12 +329,11 @@ public: }; class CXXSelfAssignmentBRVisitor final - : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> { - - bool Satisfied; + : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> { + bool Satisfied = false; public: - CXXSelfAssignmentBRVisitor() : Satisfied(false) {} + CXXSelfAssignmentBRVisitor() = default; void Profile(llvm::FoldingSetNodeID &ID) const override {} @@ -370,10 +370,10 @@ const Stmt *GetDenomExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); bool isDeclRefExprToReference(const Expr *E); +} // namespace bugreporter -} // end namespace clang -} // end namespace ento -} // end namespace bugreporter +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 2adc09cd8db..421369e1929 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -1,4 +1,4 @@ -//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===// +//===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,39 +14,49 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H -#include "clang/Analysis/ProgramPoint.h" +#include "clang/AST/Stmt.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include <cassert> #include <deque> #include <iterator> #include <list> #include <map> +#include <memory> #include <set> #include <string> +#include <utility> #include <vector> namespace clang { -class ConditionalOperator; + class AnalysisDeclContext; class BinaryOperator; -class CompoundStmt; +class CallEnter; +class CallExitEnd; +class CallExpr; +class ConditionalOperator; class Decl; +class Expr; class LocationContext; class MemberExpr; -class ParentMap; class ProgramPoint; class SourceManager; -class Stmt; -class CallExpr; namespace ento { class ExplodedNode; class SymExpr; -typedef const SymExpr* SymbolRef; + +using SymbolRef = const SymExpr *; //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. @@ -60,7 +70,7 @@ public: public: PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {} - typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles; + using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>; /// \brief A vector of <consumer,file> pairs. ConsumerFiles files; @@ -90,8 +100,9 @@ public: private: virtual void anchor(); + public: - PathDiagnosticConsumer() : flushed(false) {} + PathDiagnosticConsumer() = default; virtual ~PathDiagnosticConsumer(); void FlushDiagnostics(FilesMade *FilesMade); @@ -104,6 +115,7 @@ public: void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D); enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; + virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } @@ -112,7 +124,7 @@ public: virtual bool supportsCrossFileDiagnostics() const { return false; } protected: - bool flushed; + bool flushed = false; llvm::FoldingSet<PathDiagnostic> Diags; }; @@ -122,31 +134,28 @@ protected: class PathDiagnosticRange : public SourceRange { public: - bool isPoint; + bool isPoint = false; PathDiagnosticRange(SourceRange R, bool isP = false) - : SourceRange(R), isPoint(isP) {} - - PathDiagnosticRange() : isPoint(false) {} + : SourceRange(R), isPoint(isP) {} + PathDiagnosticRange() = default; }; -typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*> - LocationOrAnalysisDeclContext; +using LocationOrAnalysisDeclContext = + llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>; class PathDiagnosticLocation { private: - enum Kind { RangeK, SingleLocK, StmtK, DeclK } K; - const Stmt *S; - const Decl *D; - const SourceManager *SM; + enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK; + + const Stmt *S = nullptr; + const Decl *D = nullptr; + const SourceManager *SM = nullptr; FullSourceLoc Loc; PathDiagnosticRange Range; - PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, - Kind kind) - : K(kind), S(nullptr), D(nullptr), SM(&sm), - Loc(genLocation(L)), Range(genRange()) { - } + PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind) + : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {} FullSourceLoc genLocation( SourceLocation L = SourceLocation(), @@ -157,18 +166,15 @@ private: public: /// Create an invalid location. - PathDiagnosticLocation() - : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {} + PathDiagnosticLocation() = default; /// Create a location corresponding to the given statement. PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac) - : K(s->getLocStart().isValid() ? StmtK : SingleLocK), - S(K == StmtK ? s : nullptr), - D(nullptr), SM(&sm), - Loc(genLocation(SourceLocation(), lac)), - Range(genRange(lac)) { + : K(s->getLocStart().isValid() ? StmtK : SingleLocK), + S(K == StmtK ? s : nullptr), SM(&sm), + Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { assert(K == SingleLocK || S); assert(K == SingleLocK || Loc.isValid()); assert(K == SingleLocK || Range.isValid()); @@ -176,8 +182,7 @@ public: /// Create a location corresponding to the given declaration. PathDiagnosticLocation(const Decl *d, const SourceManager &sm) - : K(DeclK), S(nullptr), D(d), SM(&sm), - Loc(genLocation()), Range(genRange()) { + : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) { assert(D); assert(Loc.isValid()); assert(Range.isValid()); @@ -187,8 +192,7 @@ public: /// /// This should only be used if there are no more appropriate constructors. PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm) - : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm), - Range(genRange()) { + : SM(&sm), Loc(loc, sm), Range(genRange()) { assert(Loc.isValid()); assert(Range.isValid()); } @@ -250,7 +254,7 @@ public: const SourceManager &SM); /// Create a location corresponding to the given valid ExplodedNode. - static PathDiagnosticLocation create(const ProgramPoint& P, + static PathDiagnosticLocation create(const ProgramPoint &P, const SourceManager &SMng); /// Create a location corresponding to the next valid ExplodedNode as end @@ -310,10 +314,11 @@ public: class PathDiagnosticLocationPair { private: PathDiagnosticLocation Start, End; + public: PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end) - : Start(start), End(end) {} + : Start(start), End(end) {} const PathDiagnosticLocation &getStart() const { return Start; } const PathDiagnosticLocation &getEnd() const { return End; } @@ -348,7 +353,7 @@ private: /// \brief In the containing bug report, this piece is the last piece from /// the main source file. - bool LastInMainSourceFile; + bool LastInMainSourceFile = false; /// A constant string that can be used to tag the PathDiagnosticPiece, /// typically with the identification of the creator. The actual pointer @@ -358,16 +363,14 @@ private: std::vector<SourceRange> ranges; - PathDiagnosticPiece() = delete; - PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete; - void operator=(const PathDiagnosticPiece &P) = delete; - protected: PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below); - PathDiagnosticPiece(Kind k, DisplayHint hint = Below); public: + PathDiagnosticPiece() = delete; + PathDiagnosticPiece(const PathDiagnosticPiece &) = delete; + PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete; virtual ~PathDiagnosticPiece(); StringRef getString() const { return str; } @@ -422,8 +425,8 @@ public: class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> { void flattenTo(PathPieces &Primary, PathPieces &Current, bool ShouldFlattenMacros) const; -public: +public: PathPieces flatten(bool ShouldFlattenMacros) const { PathPieces Result; flattenTo(Result, Result, ShouldFlattenMacros); @@ -436,12 +439,13 @@ public: class PathDiagnosticSpotPiece : public PathDiagnosticPiece { private: PathDiagnosticLocation Pos; + public: PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange = true) - : PathDiagnosticPiece(s, k), Pos(pos) { + : PathDiagnosticPiece(s, k), Pos(pos) { assert(Pos.isValid() && Pos.asLocation().isValid() && "PathDiagnosticSpotPiece's must have a valid location."); if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); @@ -483,7 +487,7 @@ private: public: StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} - ~StackHintGeneratorForSymbol() override {} + ~StackHintGeneratorForSymbol() override = default; /// \brief Search the call expression for the symbol Sym and dispatch the /// 'getMessageForX()' methods to construct a specific message. @@ -492,9 +496,11 @@ public: /// Produces the message of the following form: /// 'Msg via Nth parameter' virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { return Msg; } + virtual std::string getMessageForSymbolNotFound() { return Msg; } @@ -513,9 +519,8 @@ public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, StackHintGenerator *stackHint = nullptr) - : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), - CallStackHint(stackHint) {} - + : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), + CallStackHint(stackHint) {} ~PathDiagnosticEventPiece() override; /// Mark the diagnostic piece as being potentially prunable. This @@ -539,30 +544,19 @@ public: std::string getCallStackMessage(const ExplodedNode *N) { if (CallStackHint) return CallStackHint->getMessage(N); - return ""; + return {}; } void dump() const override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; } }; class PathDiagnosticCallPiece : public PathDiagnosticPiece { - PathDiagnosticCallPiece(const Decl *callerD, - const PathDiagnosticLocation &callReturnPos) - : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr), - NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false), - callReturn(callReturnPos) {} - - PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) - : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr), - NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false), - path(oldPath) {} - const Decl *Caller; - const Decl *Callee; + const Decl *Callee = nullptr; // Flag signifying that this diagnostic has only call enter and no matching // call exit. @@ -570,12 +564,20 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece { // Flag signifying that the callee function is an Objective-C autosynthesized // property getter or setter. - bool IsCalleeAnAutosynthesizedPropertyAccessor; + bool IsCalleeAnAutosynthesizedPropertyAccessor = false; // The custom string, which should appear after the call Return Diagnostic. // TODO: Should we allow multiple diagnostics? std::string CallStackMessage; + PathDiagnosticCallPiece(const Decl *callerD, + const PathDiagnosticLocation &callReturnPos) + : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false), + callReturn(callReturnPos) {} + PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) + : PathDiagnosticPiece(Call), Caller(caller), NoExit(true), + path(oldPath) {} + public: PathDiagnosticLocation callEnter; PathDiagnosticLocation callEnterWithin; @@ -590,13 +592,9 @@ public: void setCallee(const CallEnter &CE, const SourceManager &SM); bool hasCallStackMessage() { return !CallStackMessage.empty(); } - void setCallStackMessage(StringRef st) { - CallStackMessage = st; - } + void setCallStackMessage(StringRef st) { CallStackMessage = st; } - PathDiagnosticLocation getLocation() const override { - return callEnter; - } + PathDiagnosticLocation getLocation() const override { return callEnter; } std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const; std::shared_ptr<PathDiagnosticEventPiece> @@ -606,8 +604,8 @@ public: void flattenLocations() override { callEnter.flatten(); callReturn.flatten(); - for (PathPieces::iterator I = path.begin(), - E = path.end(); I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : path) + I->flattenLocations(); } static std::shared_ptr<PathDiagnosticCallPiece> @@ -621,28 +619,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Call; } }; class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { std::vector<PathDiagnosticLocationPair> LPairs; + public: PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s) - : PathDiagnosticPiece(s, ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } + : PathDiagnosticPiece(s, ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos) - : PathDiagnosticPiece(ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } + : PathDiagnosticPiece(ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } - ~PathDiagnosticControlFlowPiece() override; + ~PathDiagnosticControlFlowPiece() override; PathDiagnosticLocation getStartLocation() const { assert(!LPairs.empty() && @@ -670,20 +669,23 @@ public: return getStartLocation(); } - typedef std::vector<PathDiagnosticLocationPair>::iterator iterator; + using iterator = std::vector<PathDiagnosticLocationPair>::iterator; + iterator begin() { return LPairs.begin(); } - iterator end() { return LPairs.end(); } + iterator end() { return LPairs.end(); } void flattenLocations() override { - for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); + for (auto &I : *this) + I.flatten(); } - typedef std::vector<PathDiagnosticLocationPair>::const_iterator - const_iterator; + using const_iterator = + std::vector<PathDiagnosticLocationPair>::const_iterator; + const_iterator begin() const { return LPairs.begin(); } - const_iterator end() const { return LPairs.end(); } + const_iterator end() const { return LPairs.end(); } - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == ControlFlow; } @@ -695,8 +697,7 @@ public: class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { public: PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos) - : PathDiagnosticSpotPiece(pos, "", Macro) {} - + : PathDiagnosticSpotPiece(pos, "", Macro) {} ~PathDiagnosticMacroPiece() override; PathPieces subPieces; @@ -705,11 +706,11 @@ public: void flattenLocations() override { PathDiagnosticSpotPiece::flattenLocations(); - for (PathPieces::iterator I = subPieces.begin(), - E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : subPieces) + I->flattenLocations(); } - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Macro; } @@ -723,10 +724,9 @@ public: PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange = true) : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {} - ~PathDiagnosticNotePiece() override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Note; } @@ -736,7 +736,7 @@ public: }; /// File IDs mapped to sets of line numbers. -typedef std::map<unsigned, std::set<unsigned>> FilesToLineNumsMap; +using FilesToLineNumsMap = std::map<unsigned, std::set<unsigned>>; /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces, @@ -764,14 +764,13 @@ class PathDiagnostic : public llvm::FoldingSetNode { /// Lines executed in the path. std::unique_ptr<FilesToLineNumsMap> ExecutedLines; - PathDiagnostic() = delete; public: + PathDiagnostic() = delete; PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique, std::unique_ptr<FilesToLineNumsMap> ExecutedLines); - ~PathDiagnostic(); const PathPieces &path; @@ -822,9 +821,11 @@ public: void resetDiagnosticLocationToMainFile(); StringRef getVerboseDescription() const { return VerboseDesc; } + StringRef getShortDescription() const { return ShortDesc.empty() ? VerboseDesc : ShortDesc; } + StringRef getCheckName() const { return CheckName; } StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } @@ -834,15 +835,18 @@ public: /// where the bug manifests. const Decl *getDeclWithIssue() const { return DeclWithIssue; } - typedef std::deque<std::string>::const_iterator meta_iterator; + using meta_iterator = std::deque<std::string>::const_iterator; + meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } void addMeta(StringRef s) { OtherDesc.push_back(s); } - typedef FilesToLineNumsMap::const_iterator filesmap_iterator; + using filesmap_iterator = FilesToLineNumsMap::const_iterator; + filesmap_iterator executedLines_begin() const { return ExecutedLines->begin(); } + filesmap_iterator executedLines_end() const { return ExecutedLines->end(); } PathDiagnosticLocation getLocation() const { @@ -862,8 +866,8 @@ public: void flattenLocations() { Loc.flatten(); - for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); - I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : pathImpl) + I->flattenLocations(); } /// Profiles the diagnostic, independent of the path it references. @@ -879,8 +883,8 @@ public: void FullProfile(llvm::FoldingSetNodeID &ID) const; }; -} // end GR namespace +} // namespace ento -} //end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index f5b4e7c3a70..9bc7c611156 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1,4 +1,4 @@ -// BugReporterVisitors.cpp - Helpers for reporting bugs -----------*- C++ -*--// +//===- BugReporterVisitors.cpp - Helpers for reporting bugs ---------------===// // // The LLVM Compiler Infrastructure // @@ -11,34 +11,67 @@ // enhance the diagnostics reported for a bug. // //===----------------------------------------------------------------------===// + #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/CFGStmtMap.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" +#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <deque> +#include <memory> +#include <string> +#include <utility> using namespace clang; using namespace ento; -using llvm::FoldingSetNodeID; - //===----------------------------------------------------------------------===// // Utility functions. //===----------------------------------------------------------------------===// bool bugreporter::isDeclRefExprToReference(const Expr *E) { - if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { + if (const auto *DRE = dyn_cast<DeclRefExpr>(E)) return DRE->getDecl()->getType()->isReferenceType(); - } return false; } @@ -55,18 +88,18 @@ bool bugreporter::isDeclRefExprToReference(const Expr *E) { /// x->y.z ==> x (lvalue) /// foo()->y.z ==> foo() (rvalue) const Expr *bugreporter::getDerefExpr(const Stmt *S) { - const Expr *E = dyn_cast<Expr>(S); + const auto *E = dyn_cast<Expr>(S); if (!E) return nullptr; while (true) { - if (const CastExpr *CE = dyn_cast<CastExpr>(E)) { + if (const auto *CE = dyn_cast<CastExpr>(E)) { if (CE->getCastKind() == CK_LValueToRValue) { // This cast represents the load we're looking for. break; } E = CE->getSubExpr(); - } else if (const BinaryOperator *B = dyn_cast<BinaryOperator>(E)) { + } else if (const auto *B = dyn_cast<BinaryOperator>(E)) { // Pointer arithmetic: '*(x + 2)' -> 'x') etc. if (B->getType()->isPointerType()) { if (B->getLHS()->getType()->isPointerType()) { @@ -81,7 +114,7 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { // but for now give up. break; } - } else if (const UnaryOperator *U = dyn_cast<UnaryOperator>(E)) { + } else if (const auto *U = dyn_cast<UnaryOperator>(E)) { if (U->getOpcode() == UO_Deref || U->getOpcode() == UO_AddrOf || (U->isIncrementDecrementOp() && U->getType()->isPointerType())) { // Operators '*' and '&' don't actually mean anything. @@ -94,13 +127,13 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { } } // Pattern match for a few useful cases: a[0], p->f, *p etc. - else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) { + else if (const auto *ME = dyn_cast<MemberExpr>(E)) { E = ME->getBase(); - } else if (const ObjCIvarRefExpr *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) { + } else if (const auto *IvarRef = dyn_cast<ObjCIvarRefExpr>(E)) { E = IvarRef->getBase(); - } else if (const ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(E)) { + } else if (const auto *AE = dyn_cast<ArraySubscriptExpr>(E)) { E = AE->getBase(); - } else if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) { + } else if (const auto *PE = dyn_cast<ParenExpr>(E)) { E = PE->getSubExpr(); } else { // Other arbitrary stuff. @@ -111,7 +144,7 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { // Special case: remove the final lvalue-to-rvalue cast, but do not recurse // deeper into the sub-expression. This way we return the lvalue from which // our pointer rvalue was loaded. - if (const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E)) + if (const auto *CE = dyn_cast<ImplicitCastExpr>(E)) if (CE->getCastKind() == CK_LValueToRValue) E = CE->getSubExpr(); @@ -120,14 +153,14 @@ const Expr *bugreporter::getDerefExpr(const Stmt *S) { const Stmt *bugreporter::GetDenomExpr(const ExplodedNode *N) { const Stmt *S = N->getLocationAs<PreStmt>()->getStmt(); - if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(S)) + if (const auto *BE = dyn_cast<BinaryOperator>(S)) return BE->getRHS(); return nullptr; } const Stmt *bugreporter::GetRetValExpr(const ExplodedNode *N) { const Stmt *S = N->getLocationAs<PostStmt>()->getStmt(); - if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(S)) + if (const auto *RS = dyn_cast<ReturnStmt>(S)) return RS->getRetValue(); return nullptr; } @@ -190,7 +223,6 @@ namespace { /// pointer dereference outside. class NoStoreFuncVisitor final : public BugReporterVisitorImpl<NoStoreFuncVisitor> { - const SubRegion *RegionOfInterest; static constexpr const char *DiagnosticsMsg = "Returning without writing to '"; @@ -238,7 +270,7 @@ public: const PrintingPolicy &PP = BRC.getASTContext().getPrintingPolicy(); const SourceManager &SM = BRC.getSourceManager(); - if (auto *CCall = dyn_cast<CXXConstructorCall>(Call)) { + if (const auto *CCall = dyn_cast<CXXConstructorCall>(Call)) { const MemRegion *ThisRegion = CCall->getCXXThisVal().getAsRegion(); if (RegionOfInterest->isSubRegionOf(ThisRegion) && !CCall->getDecl()->isImplicit()) @@ -323,7 +355,7 @@ private: ArrayRef<ParmVarDecl *> getCallParameters(CallEventRef<> Call) { // Use runtime definition, if available. RuntimeDefinition RD = Call->getRuntimeDefinition(); - if (auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl())) + if (const auto *FD = dyn_cast_or_null<FunctionDecl>(RD.getDecl())) return FD->parameters(); return Call->parameters(); @@ -342,7 +374,6 @@ private: CallExitBegin &CallExitLoc, const CXXConstructorCall *Call, const MemRegion *ArgRegion) { - SmallString<256> sbuf; llvm::raw_svector_ostream os(sbuf); os << DiagnosticsMsg; @@ -371,7 +402,6 @@ private: const ParmVarDecl *PVD, const MemRegion *ArgRegion, unsigned IndirectionLevel) { - PathDiagnosticLocation L = getPathDiagnosticLocation( CallExitLoc.getReturnStmt(), SM, Ctx, Call); SmallString<256> sbuf; @@ -431,14 +461,14 @@ private: if (ShouldSurround) os << "("; - for (int i=0; i<IndirectionLevel; i++) + for (int i = 0; i < IndirectionLevel; i++) os << "*"; os << TopRegionName; if (ShouldSurround) os << ")"; for (auto I = Subregions.rbegin(), E = Subregions.rend(); I != E; ++I) { - if (auto *FR = dyn_cast<FieldRegion>(*I)) { + if (const auto *FR = dyn_cast<FieldRegion>(*I)) { os << Sep; FR->getDecl()->getDeclName().print(os, PP); Sep = "."; @@ -452,13 +482,8 @@ private: } }; -} // namespace - -namespace { - class MacroNullReturnSuppressionVisitor final : public BugReporterVisitorImpl<MacroNullReturnSuppressionVisitor> { - const SubRegion *RegionOfInterest; public: @@ -516,13 +541,13 @@ private: if (!S) return None; - if (auto *DS = dyn_cast<DeclStmt>(S)) { - if (const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) + if (const auto *DS = dyn_cast<DeclStmt>(S)) { + if (const auto *VD = dyn_cast<VarDecl>(DS->getSingleDecl())) if (const Expr *RHS = VD->getInit()) if (RegionOfInterest->isSubRegionOf( State->getLValue(VD, LCtx).getAsRegion())) return RHS->getLocStart(); - } else if (auto *BO = dyn_cast<BinaryOperator>(S)) { + } else if (const auto *BO = dyn_cast<BinaryOperator>(S)) { const MemRegion *R = N->getSVal(BO->getLHS()).getAsRegion(); const Expr *RHS = BO->getRHS(); if (BO->isAssignmentOp() && RegionOfInterest->isSubRegionOf(R)) { @@ -546,13 +571,13 @@ class ReturnVisitor : public BugReporterVisitorImpl<ReturnVisitor> { Initial, MaybeUnsuppress, Satisfied - } Mode; + } Mode = Initial; bool EnableNullFPSuppression; public: ReturnVisitor(const StackFrameContext *Frame, bool Suppressed) - : StackFrame(Frame), Mode(Initial), EnableNullFPSuppression(Suppressed) {} + : StackFrame(Frame), EnableNullFPSuppression(Suppressed) {} static void *getTag() { static int Tag = 0; @@ -646,7 +671,7 @@ public: if (!SP) return nullptr; - const ReturnStmt *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); + const auto *Ret = dyn_cast<ReturnStmt>(SP->getStmt()); if (!Ret) return nullptr; @@ -724,8 +749,8 @@ public: } } else { // FIXME: We should have a more generalized location printing mechanism. - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(RetE)) - if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) + if (const auto *DR = dyn_cast<DeclRefExpr>(RetE)) + if (const auto *DD = dyn_cast<DeclaratorDecl>(DR->getDecl())) Out << " (loaded from '" << *DD << "')"; } @@ -812,10 +837,10 @@ public: return nullptr; } }; -} // end anonymous namespace +} // namespace -void FindLastStoreBRVisitor ::Profile(llvm::FoldingSetNodeID &ID) const { +void FindLastStoreBRVisitor::Profile(llvm::FoldingSetNodeID &ID) const { static int tag = 0; ID.AddPointer(&tag); ID.AddPointer(R); @@ -838,7 +863,7 @@ static bool isInitializationOfVar(const ExplodedNode *N, const VarRegion *VR) { return false; const MemSpaceRegion *VarSpace = VR->getMemorySpace(); - const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace); + const auto *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace); if (!FrameSpace) { // If we ever directly evaluate global DeclStmts, this assertion will be // invalid, but this still seems preferable to silently accepting an @@ -866,7 +891,7 @@ void showBRDiagnostics(const char *action, if (V.getAs<loc::ConcreteInt>()) { bool b = false; if (R->isBoundable()) { - if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { + if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { os << action << "nil"; b = true; @@ -881,7 +906,7 @@ void showBRDiagnostics(const char *action, } else if (DS) { if (V.isUndef()) { if (isa<VarRegion>(R)) { - const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl()); + const auto *VD = cast<VarDecl>(DS->getSingleDecl()); if (VD->getInit()) { os << (R->canPrintPretty() ? "initialized" : "Initializing") << " to a garbage value"; @@ -934,7 +959,7 @@ static void showBRDefaultDiagnostics(llvm::raw_svector_ostream& os, if (V.getAs<loc::ConcreteInt>()) { bool b = false; if (R->isBoundable()) { - if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { + if (const auto *TR = dyn_cast<TypedValueRegion>(R)) { if (TR->getValueType()->isObjCObjectPointerType()) { os << "nil object reference stored"; b = true; @@ -977,7 +1002,6 @@ std::shared_ptr<PathDiagnosticPiece> FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) { - if (Satisfied) return nullptr; @@ -986,7 +1010,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, bool IsParam = false; // First see if we reached the declaration of the region. - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { + if (const auto *VR = dyn_cast<VarRegion>(R)) { if (isInitializationOfVar(Pred, VR)) { StoreSite = Pred; InitE = VR->getDecl()->getInit(); @@ -1032,8 +1056,8 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // 'this' should never be NULL, but this visitor isn't just for NULL and // UndefinedVal.) if (Optional<CallEnter> CE = Succ->getLocationAs<CallEnter>()) { - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) { - const ParmVarDecl *Param = cast<ParmVarDecl>(VR->getDecl()); + if (const auto *VR = dyn_cast<VarRegion>(R)) { + const auto *Param = cast<ParmVarDecl>(VR->getDecl()); ProgramStateManager &StateMgr = BRC.getStateManager(); CallEventManager &CallMgr = StateMgr.getCallEventManager(); @@ -1047,7 +1071,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // If this is a CXXTempObjectRegion, the Expr responsible for its creation // is wrapped inside of it. - if (const CXXTempObjectRegion *TmpR = dyn_cast<CXXTempObjectRegion>(R)) + if (const auto *TmpR = dyn_cast<CXXTempObjectRegion>(R)) InitE = TmpR->getExpr(); } @@ -1077,8 +1101,8 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, if (Optional<PostStmt> PS = StoreSite->getLocationAs<PostStmt>()) { const Stmt *S = PS->getStmt(); const char *action = nullptr; - const DeclStmt *DS = dyn_cast<DeclStmt>(S); - const VarRegion *VR = dyn_cast<VarRegion>(R); + const auto *DS = dyn_cast<DeclStmt>(S); + const auto *VR = dyn_cast<VarRegion>(R); if (DS) { action = R->canPrintPretty() ? "initialized to " : @@ -1090,7 +1114,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // See if we can get the BlockVarRegion. ProgramStateRef State = StoreSite->getState(); SVal V = StoreSite->getSVal(S); - if (const BlockDataRegion *BDR = + if (const auto *BDR = dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) { if (Optional<KnownSVal> KV = @@ -1105,7 +1129,7 @@ FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, showBRDiagnostics(action, os, R, V, DS); } else if (StoreSite->getLocation().getAs<CallEnter>()) { - if (const VarRegion *VR = dyn_cast<VarRegion>(R)) + if (const auto *VR = dyn_cast<VarRegion>(R)) showBRParamDiagnostics(os, VR, V); } @@ -1165,7 +1189,6 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, // Check if in the previous state it was feasible for this constraint // to *not* be true. if (isUnderconstrained(PrevN)) { - IsSatisfied = true; // As a sanity check, make sure that the negation of the constraint @@ -1203,20 +1226,20 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, SuppressInlineDefensiveChecksVisitor:: SuppressInlineDefensiveChecksVisitor(DefinedSVal Value, const ExplodedNode *N) - : V(Value), IsSatisfied(false), IsTrackingTurnedOn(false) { - - // Check if the visitor is disabled. - SubEngine *Eng = N->getState()->getStateManager().getOwningEngine(); - assert(Eng && "Cannot file a bug report without an owning engine"); - AnalyzerOptions &Options = Eng->getAnalysisManager().options; - if (!Options.shouldSuppressInlinedDefensiveChecks()) - IsSatisfied = true; + : V(Value) { + // Check if the visitor is disabled. + SubEngine *Eng = N->getState()->getStateManager().getOwningEngine(); + assert(Eng && "Cannot file a bug report without an owning engine"); + AnalyzerOptions &Options = Eng->getAnalysisManager().options; + if (!Options.shouldSuppressInlinedDefensiveChecks()) + IsSatisfied = true; - assert(N->getState()->isNull(V).isConstrainedTrue() && - "The visitor only tracks the cases where V is constrained to 0"); + assert(N->getState()->isNull(V).isConstrainedTrue() && + "The visitor only tracks the cases where V is constrained to 0"); } -void SuppressInlineDefensiveChecksVisitor::Profile(FoldingSetNodeID &ID) const { +void SuppressInlineDefensiveChecksVisitor::Profile( + llvm::FoldingSetNodeID &ID) const { static int id = 0; ID.AddPointer(&id); ID.Add(V); @@ -1265,7 +1288,6 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, if (!BugPoint) return nullptr; - ProgramPoint CurPoint = Succ->getLocation(); const Stmt *CurTerminatorStmt = nullptr; if (auto BE = CurPoint.getAs<BlockEdge>()) { @@ -1301,8 +1323,8 @@ SuppressInlineDefensiveChecksVisitor::VisitNode(const ExplodedNode *Succ, static const MemRegion *getLocationRegionIfReference(const Expr *E, const ExplodedNode *N) { - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) { - if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { + if (const auto *DR = dyn_cast<DeclRefExpr>(E)) { + if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) { if (!VD->getType()->isReferenceType()) return nullptr; ProgramStateManager &StateMgr = N->getState()->getStateManager(); @@ -1323,12 +1345,12 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E, static const Expr *peelOffOuterExpr(const Expr *Ex, const ExplodedNode *N) { Ex = Ex->IgnoreParenCasts(); - if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex)) + if (const auto *EWC = dyn_cast<ExprWithCleanups>(Ex)) return peelOffOuterExpr(EWC->getSubExpr(), N); - if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex)) + if (const auto *OVE = dyn_cast<OpaqueValueExpr>(Ex)) return peelOffOuterExpr(OVE->getSourceExpr(), N); - if (auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) { - auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); + if (const auto *POE = dyn_cast<PseudoObjectExpr>(Ex)) { + const auto *PropRef = dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm()); if (PropRef && PropRef->isMessagingGetter()) { const Expr *GetterMessageSend = POE->getSemanticExpr(POE->getNumSemanticExprs() - 1); @@ -1338,7 +1360,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex, } // Peel off the ternary operator. - if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) { + if (const auto *CO = dyn_cast<ConditionalOperator>(Ex)) { // Find a node where the branching occurred and find out which branch // we took (true/false) by looking at the ExplodedGraph. const ExplodedNode *NI = N; @@ -1396,7 +1418,6 @@ static const ExplodedNode* findNodeForExpression(const ExplodedNode *N, } assert(N && "Unable to find the lvalue node."); return N; - } /// Performing operator `&' on an lvalue expression is essentially a no-op. @@ -1418,7 +1439,6 @@ static const Expr* peelOfOuterAddrOf(const Expr* Ex) { if (const Expr *DerefEx = bugreporter::getDerefExpr(Op->getSubExpr())) return DerefEx; return Ex; - } bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, @@ -1562,7 +1582,7 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Expr *NilReceiverBRVisitor::getNilReceiver(const Stmt *S, const ExplodedNode *N) { - const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S); + const auto *ME = dyn_cast<ObjCMessageExpr>(S); if (!ME) return nullptr; if (const Expr *Receiver = ME->getInstanceReceiver()) { @@ -1590,7 +1610,7 @@ NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, llvm::SmallString<256> Buf; llvm::raw_svector_ostream OS(Buf); - if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) { + if (const auto *ME = dyn_cast<ObjCMessageExpr>(S)) { OS << "'"; ME->getSelector().print(OS); OS << "' not called"; @@ -1625,8 +1645,8 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, ProgramStateManager &StateMgr = N->getState()->getStateManager(); - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Head)) { - if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { + if (const auto *DR = dyn_cast<DeclRefExpr>(Head)) { + if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) { const VarRegion *R = StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); @@ -1672,7 +1692,6 @@ std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitNodeImpl(const ExplodedNode *N, const ExplodedNode *Prev, BugReporterContext &BRC, BugReport &BR) { - ProgramPoint progPoint = N->getLocation(); ProgramStateRef CurrentState = N->getState(); ProgramStateRef PrevState = Prev->getState(); @@ -1794,7 +1813,7 @@ ConditionBRVisitor::VisitTrueTest(const Expr *Cond, bool tookTrue, return P; break; case Stmt::UnaryOperatorClass: { - const UnaryOperator *UO = cast<UnaryOperator>(CondTmp); + const auto *UO = cast<UnaryOperator>(CondTmp); if (UO->getOpcode() == UO_LNot) { tookTrueTmp = !tookTrueTmp; CondTmp = UO->getSubExpr(); @@ -1837,7 +1856,6 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, isa<CXXBoolLiteralExpr>(Ex) || isa<IntegerLiteral>(Ex) || isa<FloatingLiteral>(Ex))) { - StringRef StartName = Lexer::getImmediateMacroNameForDiagnostics(LocStart, BRC.getSourceManager(), BRC.getASTContext().getLangOpts()); StringRef EndName = Lexer::getImmediateMacroNameForDiagnostics(LocEnd, @@ -1868,7 +1886,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, } } - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Ex)) { + if (const auto *DR = dyn_cast<DeclRefExpr>(Ex)) { const bool quotes = isa<VarDecl>(DR->getDecl()); if (quotes) { Out << '\''; @@ -1892,7 +1910,7 @@ bool ConditionBRVisitor::patternMatch(const Expr *Ex, return quotes; } - if (const IntegerLiteral *IL = dyn_cast<IntegerLiteral>(Ex)) { + if (const auto *IL = dyn_cast<IntegerLiteral>(Ex)) { QualType OriginalTy = OriginalExpr->getType(); if (OriginalTy->isPointerType()) { if (IL->getValue() == 0) { @@ -1918,7 +1936,6 @@ std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const BinaryOperator *BExpr, const bool tookTrue, BugReporterContext &BRC, BugReport &R, const ExplodedNode *N) { - bool shouldInvert = false; Optional<bool> shouldPrune; @@ -2023,8 +2040,8 @@ std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitConditionVariable( PathDiagnosticLocation Loc(CondVarExpr, BRC.getSourceManager(), LCtx); auto event = std::make_shared<PathDiagnosticEventPiece>(Loc, Out.str()); - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { - if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { + if (const auto *DR = dyn_cast<DeclRefExpr>(CondVarExpr)) { + if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) { const ProgramState *state = N->getState().get(); if (const MemRegion *R = state->getLValue(VD, LCtx).getAsRegion()) { if (report.isInteresting(R)) @@ -2040,8 +2057,7 @@ std::shared_ptr<PathDiagnosticPiece> ConditionBRVisitor::VisitTrueTest(const Expr *Cond, const DeclRefExpr *DR, const bool tookTrue, BugReporterContext &BRC, BugReport &report, const ExplodedNode *N) { - - const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()); + const auto *VD = dyn_cast<VarDecl>(DR->getDecl()); if (!VD) return nullptr; @@ -2107,7 +2123,6 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, if (Options.shouldSuppressFromCXXStandardLibrary()) { BR.markInvalid(getTag(), nullptr); return nullptr; - } else { // If the complete 'std' suppression is not enabled, suppress reports // from the 'std' namespace that are known to produce false positives. @@ -2115,7 +2130,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // The analyzer issues a false use-after-free when std::list::pop_front // or std::list::pop_back are called multiple times because we cannot // reason about the internal invariants of the data structure. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { const CXXRecordDecl *CD = MD->getParent(); if (CD->getName() == "list") { BR.markInvalid(getTag(), nullptr); @@ -2125,7 +2140,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, // The analyzer issues a false positive when the constructor of // std::__independent_bits_engine from algorithms is used. - if (const CXXConstructorDecl *MD = dyn_cast<CXXConstructorDecl>(D)) { + if (const auto *MD = dyn_cast<CXXConstructorDecl>(D)) { const CXXRecordDecl *CD = MD->getParent(); if (CD->getName() == "__independent_bits_engine") { BR.markInvalid(getTag(), nullptr); @@ -2135,7 +2150,7 @@ LikelyFalsePositiveSuppressionBRVisitor::getEndPath(BugReporterContext &BRC, for (const LocationContext *LCtx = N->getLocationContext(); LCtx; LCtx = LCtx->getParent()) { - const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); + const auto *MD = dyn_cast<CXXMethodDecl>(LCtx->getDecl()); if (!MD) continue; @@ -2181,7 +2196,6 @@ std::shared_ptr<PathDiagnosticPiece> UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC, BugReport &BR) { - ProgramStateRef State = N->getState(); ProgramPoint ProgLoc = N->getLocation(); @@ -2194,18 +2208,17 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager(); CallEventRef<> Call = CEMgr.getCaller(CEnter->getCalleeContext(), State); unsigned Idx = 0; - ArrayRef<ParmVarDecl*> parms = Call->parameters(); + ArrayRef<ParmVarDecl *> parms = Call->parameters(); - for (ArrayRef<ParmVarDecl*>::iterator I = parms.begin(), E = parms.end(); - I != E; ++I, ++Idx) { + for (const auto ParamDecl : parms) { const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); + ++Idx; // Are we tracking the argument or its subregion? if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts())) continue; // Check the function parameter type. - const ParmVarDecl *ParamDecl = *I; assert(ParamDecl && "Formal parameter has no decl?"); QualType T = ParamDecl->getType(); @@ -2237,7 +2250,7 @@ CXXSelfAssignmentBRVisitor::VisitNode(const ExplodedNode *Succ, if (Satisfied) return nullptr; - auto Edge = Succ->getLocation().getAs<BlockEdge>(); + const auto Edge = Succ->getLocation().getAs<BlockEdge>(); if (!Edge.hasValue()) return nullptr; diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 8119e3a927a..18e06cb2c3a 100644 --- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -1,4 +1,4 @@ -//===--- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -*- C++ -*-===// +//===- PathDiagnostic.cpp - Path-Specific Diagnostic Handling -------------===// // // The LLVM Compiler Infrastructure // @@ -13,26 +13,50 @@ #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/OperationKinds.h" #include "clang/AST/ParentMap.h" -#include "clang/AST/StmtCXX.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstring> +#include <memory> +#include <utility> +#include <vector> using namespace clang; using namespace ento; bool PathDiagnosticMacroPiece::containsEvent() const { - for (auto &P : subPieces) { + for (const auto &P : subPieces) { if (isa<PathDiagnosticEventPiece>(*P)) return true; - if (auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get())) + if (const auto *MP = dyn_cast<PathDiagnosticMacroPiece>(P.get())) if (MP->containsEvent()) return true; } @@ -43,23 +67,27 @@ static StringRef StripTrailingDots(StringRef s) { for (StringRef::size_type i = s.size(); i != 0; --i) if (s[i - 1] != '.') return s.substr(0, i); - return ""; + return {}; } PathDiagnosticPiece::PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint) - : str(StripTrailingDots(s)), kind(k), Hint(hint), - LastInMainSourceFile(false) {} + : str(StripTrailingDots(s)), kind(k), Hint(hint) {} PathDiagnosticPiece::PathDiagnosticPiece(Kind k, DisplayHint hint) - : kind(k), Hint(hint), LastInMainSourceFile(false) {} + : kind(k), Hint(hint) {} -PathDiagnosticPiece::~PathDiagnosticPiece() {} -PathDiagnosticEventPiece::~PathDiagnosticEventPiece() {} -PathDiagnosticCallPiece::~PathDiagnosticCallPiece() {} -PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() {} -PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() {} -PathDiagnosticNotePiece::~PathDiagnosticNotePiece() {} +PathDiagnosticPiece::~PathDiagnosticPiece() = default; + +PathDiagnosticEventPiece::~PathDiagnosticEventPiece() = default; + +PathDiagnosticCallPiece::~PathDiagnosticCallPiece() = default; + +PathDiagnosticControlFlowPiece::~PathDiagnosticControlFlowPiece() = default; + +PathDiagnosticMacroPiece::~PathDiagnosticMacroPiece() = default; + +PathDiagnosticNotePiece::~PathDiagnosticNotePiece() = default; void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current, bool ShouldFlattenMacros) const { @@ -96,7 +124,7 @@ void PathPieces::flattenTo(PathPieces &Primary, PathPieces &Current, } } -PathDiagnostic::~PathDiagnostic() {} +PathDiagnostic::~PathDiagnostic() = default; PathDiagnostic::PathDiagnostic( StringRef CheckName, const Decl *declWithIssue, StringRef bugtype, @@ -133,10 +161,8 @@ getFirstStackedCallToHeaderFile(PathDiagnosticCallPiece *CP, // Check if the last piece in the callee path is a call to a function outside // of the main file. - if (PathDiagnosticCallPiece *CPInner = - dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) { + if (auto *CPInner = dyn_cast<PathDiagnosticCallPiece>(Path.back().get())) return getFirstStackedCallToHeaderFile(CPInner, SMgr); - } // Otherwise, the last piece is in the main file. return nullptr; @@ -152,14 +178,14 @@ void PathDiagnostic::resetDiagnosticLocationToMainFile() { // We only need to check if the report ends inside headers, if the last piece // is a call piece. - if (PathDiagnosticCallPiece *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) { + if (auto *CP = dyn_cast<PathDiagnosticCallPiece>(LastP)) { CP = getFirstStackedCallToHeaderFile(CP, SMgr); if (CP) { // Mark the piece. CP->setAsLastInMainSourceFile(); // Update the path diagnostic message. - const NamedDecl *ND = dyn_cast<NamedDecl>(CP->getCallee()); + const auto *ND = dyn_cast<NamedDecl>(CP->getCallee()); if (ND) { SmallString<200> buf; llvm::raw_svector_ostream os(buf); @@ -176,14 +202,12 @@ void PathDiagnostic::resetDiagnosticLocationToMainFile() { } } -void PathDiagnosticConsumer::anchor() { } +void PathDiagnosticConsumer::anchor() {} PathDiagnosticConsumer::~PathDiagnosticConsumer() { // Delete the contents of the FoldingSet if it isn't empty already. - for (llvm::FoldingSet<PathDiagnostic>::iterator it = - Diags.begin(), et = Diags.end() ; it != et ; ++it) { - delete &*it; - } + for (auto &Diag : Diags) + delete &Diag; } void PathDiagnosticConsumer::HandlePathDiagnostic( @@ -214,9 +238,8 @@ void PathDiagnosticConsumer::HandlePathDiagnostic( while (!WorkList.empty()) { const PathPieces &path = *WorkList.pop_back_val(); - for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; - ++I) { - const PathDiagnosticPiece *piece = I->get(); + for (const auto &I : path) { + const PathDiagnosticPiece *piece = I.get(); FullSourceLoc L = piece->getLocation().asLocation().getExpansionLoc(); if (FID.isInvalid()) { @@ -228,28 +251,23 @@ void PathDiagnosticConsumer::HandlePathDiagnostic( // Check the source ranges. ArrayRef<SourceRange> Ranges = piece->getRanges(); - for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), - E = Ranges.end(); I != E; ++I) { - SourceLocation L = SMgr.getExpansionLoc(I->getBegin()); + for (const auto &I : Ranges) { + SourceLocation L = SMgr.getExpansionLoc(I.getBegin()); if (!L.isFileID() || SMgr.getFileID(L) != FID) { llvm::errs() << warning.str(); return; } - L = SMgr.getExpansionLoc(I->getEnd()); + L = SMgr.getExpansionLoc(I.getEnd()); if (!L.isFileID() || SMgr.getFileID(L) != FID) { llvm::errs() << warning.str(); return; } } - if (const PathDiagnosticCallPiece *call = - dyn_cast<PathDiagnosticCallPiece>(piece)) { + if (const auto *call = dyn_cast<PathDiagnosticCallPiece>(piece)) WorkList.push_back(&call->path); - } - else if (const PathDiagnosticMacroPiece *macro = - dyn_cast<PathDiagnosticMacroPiece>(piece)) { + else if (const auto *macro = dyn_cast<PathDiagnosticMacroPiece>(piece)) WorkList.push_back(¯o->subPieces); - } } } @@ -442,11 +460,8 @@ void PathDiagnosticConsumer::FlushDiagnostics( flushed = true; std::vector<const PathDiagnostic *> BatchDiags; - for (llvm::FoldingSet<PathDiagnostic>::iterator it = Diags.begin(), - et = Diags.end(); it != et; ++it) { - const PathDiagnostic *D = &*it; - BatchDiags.push_back(D); - } + for (const auto &D : Diags) + BatchDiags.push_back(&D); // Sort the diagnostics so that they are always emitted in a deterministic // order. @@ -463,11 +478,8 @@ void PathDiagnosticConsumer::FlushDiagnostics( FlushDiagnosticsImpl(BatchDiags, Files); // Delete the flushed diagnostics. - for (std::vector<const PathDiagnostic *>::iterator it = BatchDiags.begin(), - et = BatchDiags.end(); it != et; ++it) { - const PathDiagnostic *D = *it; + for (const auto D : BatchDiags) delete D; - } // Clear out the FoldingSet. Diags.clear(); @@ -628,7 +640,7 @@ PathDiagnosticLocation PathDiagnosticLocation::createEnd(const Stmt *S, const SourceManager &SM, LocationOrAnalysisDeclContext LAC) { - if (const CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) + if (const auto *CS = dyn_cast<CompoundStmt>(S)) return createEndBrace(CS, SM); return PathDiagnosticLocation(getValidSourceLocation(S, LAC, /*End=*/true), SM, SingleLocK); @@ -647,7 +659,6 @@ PathDiagnosticLocation::createConditionalColonLoc( return PathDiagnosticLocation(CO->getColonLoc(), SM, SingleLocK); } - PathDiagnosticLocation PathDiagnosticLocation::createMemberLoc(const MemberExpr *ME, const SourceManager &SM) { @@ -672,8 +683,7 @@ PathDiagnosticLocation PathDiagnosticLocation::createDeclBegin(const LocationContext *LC, const SourceManager &SM) { // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. - if (const CompoundStmt *CS = - dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody())) + if (const auto *CS = dyn_cast_or_null<CompoundStmt>(LC->getDecl()->getBody())) if (!CS->body_empty()) { SourceLocation Loc = (*CS->body_begin())->getLocStart(); return PathDiagnosticLocation(Loc, SM, SingleLocK); @@ -815,11 +825,11 @@ PathDiagnosticLocation const LocationContext *LC = N->getLocationContext(); // For member expressions, return the location of the '.' or '->'. - if (const MemberExpr *ME = dyn_cast<MemberExpr>(S)) + if (const auto *ME = dyn_cast<MemberExpr>(S)) return PathDiagnosticLocation::createMemberLoc(ME, SM); // For binary operators, return the location of the operator. - if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) + if (const auto *B = dyn_cast<BinaryOperator>(S)) return PathDiagnosticLocation::createOperatorLoc(B, SM); if (P.getAs<PostStmtPurgeDeadSymbols>()) @@ -881,7 +891,7 @@ PathDiagnosticRange default: break; case Stmt::DeclStmtClass: { - const DeclStmt *DS = cast<DeclStmt>(S); + const auto *DS = cast<DeclStmt>(S); if (DS->isSingleDecl()) { // Should always be the case, but we'll be defensive. return SourceRange(DS->getLocStart(), @@ -911,9 +921,9 @@ PathDiagnosticRange break; } case DeclK: - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) return MD->getSourceRange(); - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (Stmt *Body = FD->getBody()) return Body->getSourceRange(); } @@ -923,7 +933,7 @@ PathDiagnosticRange } } - return SourceRange(Loc,Loc); + return SourceRange(Loc, Loc); } void PathDiagnosticLocation::flatten() { @@ -979,14 +989,14 @@ void PathDiagnosticCallPiece::setCallee(const CallEnter &CE, // non-autosynthesized callbacks. // Unless set here, the IsCalleeAnAutosynthesizedPropertyAccessor flag // defaults to false. - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee)) + if (const auto *MD = dyn_cast<ObjCMethodDecl>(Callee)) IsCalleeAnAutosynthesizedPropertyAccessor = ( MD->isPropertyAccessor() && CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized()); } -static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D, - StringRef Prefix = StringRef()) { +static void describeClass(raw_ostream &Out, const CXXRecordDecl *D, + StringRef Prefix = StringRef()) { if (!D->getIdentifier()) return; Out << Prefix << '\'' << *D << '\''; @@ -1004,7 +1014,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D, return ExtendedDescription; } - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) { Out << Prefix; if (ExtendedDescription && !MD->isUserProvided()) { if (MD->isExplicitlyDefaulted()) @@ -1013,7 +1023,7 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D, Out << "implicit "; } - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(MD)) { + if (const auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { if (CD->isDefaultConstructor()) Out << "default "; else if (CD->isCopyConstructor()) @@ -1023,7 +1033,6 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D, Out << "constructor"; describeClass(Out, MD->getParent(), " for "); - } else if (isa<CXXDestructorDecl>(MD)) { if (!MD->isUserProvided()) { Out << "destructor"; @@ -1032,15 +1041,12 @@ static bool describeCodeDecl(raw_ostream &Out, const Decl *D, // Use ~Foo for explicitly-written destructors. Out << "'" << *MD << "'"; } - } else if (MD->isCopyAssignmentOperator()) { Out << "copy assignment operator"; describeClass(Out, MD->getParent(), " for "); - } else if (MD->isMoveAssignmentOperator()) { Out << "move assignment operator"; describeClass(Out, MD->getParent(), " for "); - } else { if (MD->getParent()->getIdentifier()) Out << "'" << *MD->getParent() << "::" << *MD << "'"; @@ -1080,7 +1086,7 @@ PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { return nullptr; if (Callee->isImplicit() || !Callee->hasBody()) return nullptr; - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Callee)) + if (const auto *MD = dyn_cast<CXXMethodDecl>(Callee)) if (MD->isDefaulted()) return nullptr; @@ -1120,13 +1126,10 @@ PathDiagnosticCallPiece::getCallExitEvent() const { } static void compute_path_size(const PathPieces &pieces, unsigned &size) { - for (PathPieces::const_iterator it = pieces.begin(), - et = pieces.end(); it != et; ++it) { - const PathDiagnosticPiece *piece = it->get(); - if (const PathDiagnosticCallPiece *cp = - dyn_cast<PathDiagnosticCallPiece>(piece)) { + for (const auto &I : pieces) { + const PathDiagnosticPiece *piece = I.get(); + if (const auto *cp = dyn_cast<PathDiagnosticCallPiece>(piece)) compute_path_size(cp->path, size); - } else ++size; } @@ -1154,19 +1157,16 @@ void PathDiagnosticPiece::Profile(llvm::FoldingSetNodeID &ID) const { // FIXME: Add profiling support for code hints. ID.AddInteger((unsigned) getDisplayHint()); ArrayRef<SourceRange> Ranges = getRanges(); - for (ArrayRef<SourceRange>::iterator I = Ranges.begin(), E = Ranges.end(); - I != E; ++I) { - ID.AddInteger(I->getBegin().getRawEncoding()); - ID.AddInteger(I->getEnd().getRawEncoding()); + for (const auto &I : Ranges) { + ID.AddInteger(I.getBegin().getRawEncoding()); + ID.AddInteger(I.getEnd().getRawEncoding()); } } void PathDiagnosticCallPiece::Profile(llvm::FoldingSetNodeID &ID) const { PathDiagnosticPiece::Profile(ID); - for (PathPieces::const_iterator it = path.begin(), - et = path.end(); it != et; ++it) { - ID.Add(**it); - } + for (const auto &I : path) + ID.Add(*I); } void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { @@ -1176,15 +1176,14 @@ void PathDiagnosticSpotPiece::Profile(llvm::FoldingSetNodeID &ID) const { void PathDiagnosticControlFlowPiece::Profile(llvm::FoldingSetNodeID &ID) const { PathDiagnosticPiece::Profile(ID); - for (const_iterator I = begin(), E = end(); I != E; ++I) - ID.Add(*I); + for (const auto &I : *this) + ID.Add(I); } void PathDiagnosticMacroPiece::Profile(llvm::FoldingSetNodeID &ID) const { PathDiagnosticSpotPiece::Profile(ID); - for (PathPieces::const_iterator I = subPieces.begin(), E = subPieces.end(); - I != E; ++I) - ID.Add(**I); + for (const auto &I : subPieces) + ID.Add(*I); } void PathDiagnosticNotePiece::Profile(llvm::FoldingSetNodeID &ID) const { @@ -1200,13 +1199,13 @@ void PathDiagnostic::Profile(llvm::FoldingSetNodeID &ID) const { void PathDiagnostic::FullProfile(llvm::FoldingSetNodeID &ID) const { Profile(ID); - for (PathPieces::const_iterator I = path.begin(), E = path.end(); I != E; ++I) - ID.Add(**I); + for (const auto &I : path) + ID.Add(*I); for (meta_iterator I = meta_begin(), E = meta_end(); I != E; ++I) ID.AddString(*I); } -StackHintGenerator::~StackHintGenerator() {} +StackHintGenerator::~StackHintGenerator() = default; std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ if (!N) @@ -1217,9 +1216,9 @@ std::string StackHintGeneratorForSymbol::getMessage(const ExplodedNode *N){ // FIXME: Use CallEvent to abstract this over all calls. const Stmt *CallSite = CExit.getCalleeContext()->getCallSite(); - const CallExpr *CE = dyn_cast_or_null<CallExpr>(CallSite); + const auto *CE = dyn_cast_or_null<CallExpr>(CallSite); if (!CE) - return ""; + return {}; // Check if one of the parameters are set to the interesting symbol. unsigned ArgIndex = 0; |