diff options
Diffstat (limited to 'include/clang/Analysis')
-rw-r--r-- | include/clang/Analysis/Analyses/Consumed.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/Dominators.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/LiveVariables.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/PostOrderCFGView.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/ThreadSafety.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/ThreadSafetyCommon.h | 2 | ||||
-rw-r--r-- | include/clang/Analysis/Analyses/ThreadSafetyTIL.h | 24 | ||||
-rw-r--r-- | include/clang/Analysis/AnalysisDeclContext.h (renamed from include/clang/Analysis/AnalysisContext.h) | 24 | ||||
-rw-r--r-- | include/clang/Analysis/BodyFarm.h | 54 | ||||
-rw-r--r-- | include/clang/Analysis/CFG.h | 358 | ||||
-rw-r--r-- | include/clang/Analysis/CallGraph.h | 93 | ||||
-rw-r--r-- | include/clang/Analysis/CloneDetection.h | 245 | ||||
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 26 | ||||
-rw-r--r-- | include/clang/Analysis/Support/BumpVector.h | 53 |
14 files changed, 427 insertions, 462 deletions
diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index c0fc02724f09..5ba42b475c83 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -19,7 +19,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/StmtCXX.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceLocation.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index 38010e1ee1d8..6cb161ab37c8 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -14,7 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H #define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/GenericDomTree.h" diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 8db4b0a58f86..6a1222386bae 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -15,7 +15,7 @@ #define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H #include "clang/AST/Decl.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "llvm/ADT/ImmutableSet.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h index a1c650427588..c0a93528373e 100644 --- a/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -21,7 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/BitVector.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 22694a7a225a..7e403b1f4090 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -19,7 +19,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 8c1d1da554bd..414645b7231b 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -25,7 +25,7 @@ #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/OperatorKinds.h" #include <memory> #include <ostream> diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index be8a7105d783..0a58d2a80250 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -92,6 +92,7 @@ enum TIL_BinaryOpcode : unsigned char { BOP_Neq, // != BOP_Lt, // < BOP_Leq, // <= + BOP_Cmp, // <=> BOP_LogicAnd, // && (no short-circuit) BOP_LogicOr // || (no short-circuit) }; @@ -909,15 +910,10 @@ class Project : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } - Project(SExpr *R, StringRef SName) - : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) - { } Project(SExpr *R, const clang::ValueDecl *Cvd) - : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) - { } - Project(const Project &P, SExpr *R) - : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) - { } + : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) { + assert(Cvd && "ValueDecl must not be null"); + } SExpr *record() { return Rec; } const SExpr *record() const { return Rec; } @@ -931,10 +927,14 @@ public: } StringRef slotName() const { - if (Cvdecl) + if (Cvdecl->getDeclName().isIdentifier()) return Cvdecl->getName(); - else - return SlotName; + if (!SlotName) { + SlotName = ""; + llvm::raw_string_ostream OS(*SlotName); + Cvdecl->printName(OS); + } + return *SlotName; } template <class V> @@ -953,7 +953,7 @@ public: private: SExpr* Rec; - StringRef SlotName; + mutable llvm::Optional<std::string> SlotName; const clang::ValueDecl *Cvdecl; }; diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisDeclContext.h index ec7549d4535c..03ff4a9516da 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisDeclContext.h @@ -1,4 +1,4 @@ -//=== AnalysisContext.h - Analysis context for Path Sens analysis --*- C++ -*-// +//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H -#define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H +#define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H #include "clang/AST/Decl.h" +#include "clang/Analysis/BodyFarm.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CodeInjector.h" #include "llvm/ADT/DenseMap.h" @@ -416,23 +417,25 @@ class AnalysisDeclContextManager { /// Pointer to an interface that can provide function bodies for /// declarations from external source. std::unique_ptr<CodeInjector> Injector; - + + /// A factory for creating and caching implementations for common + /// methods during the analysis. + BodyFarm FunctionBodyFarm; + /// Flag to indicate whether or not bodies should be synthesized /// for well-known functions. bool SynthesizeBodies; public: - AnalysisDeclContextManager(bool useUnoptimizedCFG = false, + AnalysisDeclContextManager(ASTContext &ASTCtx, bool useUnoptimizedCFG = false, bool addImplicitDtors = false, bool addInitializers = false, bool addTemporaryDtors = false, - bool addLifetime = false, + bool addLifetime = false, bool addLoopExit = false, bool synthesizeBodies = false, bool addStaticInitBranches = false, bool addCXXNewAllocator = true, - CodeInjector* injector = nullptr); - - ~AnalysisDeclContextManager(); + CodeInjector *injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); @@ -471,6 +474,9 @@ public: return LocContexts.getStackFrame(getContext(D), Parent, S, Blk, Idx); } + /// Get a reference to {@code BodyFarm} instance. + BodyFarm &getBodyFarm(); + /// Discard all previously created AnalysisDeclContexts. void clear(); diff --git a/include/clang/Analysis/BodyFarm.h b/include/clang/Analysis/BodyFarm.h new file mode 100644 index 000000000000..ff0859bc662d --- /dev/null +++ b/include/clang/Analysis/BodyFarm.h @@ -0,0 +1,54 @@ +//== BodyFarm.h - Factory for conjuring up fake bodies -------------*- C++ -*-// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// BodyFarm is a factory for creating faux implementations for functions/methods +// for analysis purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_ANALYSIS_BODYFARM_H +#define LLVM_CLANG_LIB_ANALYSIS_BODYFARM_H + +#include "clang/AST/DeclBase.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" + +namespace clang { + +class ASTContext; +class FunctionDecl; +class ObjCMethodDecl; +class ObjCPropertyDecl; +class Stmt; +class CodeInjector; + +class BodyFarm { +public: + BodyFarm(ASTContext &C, CodeInjector *injector) : C(C), Injector(injector) {} + + /// Factory method for creating bodies for ordinary functions. + Stmt *getBody(const FunctionDecl *D); + + /// Factory method for creating bodies for Objective-C properties. + Stmt *getBody(const ObjCMethodDecl *D); + + /// Remove copy constructor to avoid accidental copying. + BodyFarm(const BodyFarm &other) = delete; + +private: + typedef llvm::DenseMap<const Decl *, Optional<Stmt *>> BodyMap; + + ASTContext &C; + BodyMap Bodies; + CodeInjector *Injector; +}; +} // namespace clang + +#endif diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 97639bbfade2..cfedb2aa8ed5 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -1,4 +1,4 @@ -//===--- CFG.h - Classes for representing and building CFGs------*- C++ -*-===// +//===- CFG.h - Classes for representing and building CFGs -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,38 +17,38 @@ #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" #include <bitset> #include <cassert> +#include <cstddef> #include <iterator> #include <memory> +#include <vector> namespace clang { - class CXXDestructorDecl; - class Decl; - class Stmt; - class Expr; - class FieldDecl; - class VarDecl; - class CXXCtorInitializer; - class CXXBaseSpecifier; - class CXXBindTemporaryExpr; - class CFG; - class PrinterHelper; - class LangOptions; - class ASTContext; - class CXXRecordDecl; - class CXXDeleteExpr; - class CXXNewExpr; - class BinaryOperator; + +class ASTContext; +class BinaryOperator; +class CFG; +class CXXBaseSpecifier; +class CXXBindTemporaryExpr; +class CXXCtorInitializer; +class CXXDeleteExpr; +class CXXDestructorDecl; +class CXXNewExpr; +class CXXRecordDecl; +class Decl; +class FieldDecl; +class LangOptions; +class VarDecl; /// CFGElement - Represents a top-level expression in a basic block. class CFGElement { @@ -59,6 +59,7 @@ public: Initializer, NewAllocator, LifetimeEnds, + LoopExit, // dtor kind AutomaticObjectDtor, DeleteDtor, @@ -75,14 +76,14 @@ protected: llvm::PointerIntPair<void *, 2> Data2; CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = nullptr) - : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), - Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { + : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) { assert(getKind() == kind); } - CFGElement() {} -public: + CFGElement() = default; +public: /// \brief Convert to the specified CFGElement type, asserting that this /// CFGElement is of the desired type. template<typename T> @@ -124,7 +125,9 @@ public: private: friend class CFGElement; - CFGStmt() {} + + CFGStmt() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Statement; } @@ -143,7 +146,9 @@ public: private: friend class CFGElement; - CFGInitializer() {} + + CFGInitializer() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == Initializer; } @@ -162,12 +167,38 @@ public: private: friend class CFGElement; - CFGNewAllocator() {} + + CFGNewAllocator() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == NewAllocator; } }; +/// Represents the point where a loop ends. +/// This element is is only produced when building the CFG for the static +/// analyzer and hidden behind the 'cfg-loopexit' analyzer config flag. +/// +/// Note: a loop exit element can be reached even when the loop body was never +/// entered. +class CFGLoopExit : public CFGElement { +public: + explicit CFGLoopExit(const Stmt *stmt) : CFGElement(LoopExit, stmt) {} + + const Stmt *getLoopStmt() const { + return static_cast<Stmt *>(Data1.getPointer()); + } + +private: + friend class CFGElement; + + CFGLoopExit() = default; + + static bool isKind(const CFGElement &elem) { + return elem.getKind() == LoopExit; + } +}; + /// Represents the point where the lifetime of an automatic object ends class CFGLifetimeEnds : public CFGElement { public: @@ -184,7 +215,9 @@ public: private: friend class CFGElement; - CFGLifetimeEnds() {} + + CFGLifetimeEnds() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == LifetimeEnds; } @@ -194,7 +227,8 @@ private: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor() {} + CFGImplicitDtor() = default; + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = nullptr) : CFGElement(kind, data1, data2) { assert(kind >= DTOR_BEGIN && kind <= DTOR_END); @@ -206,6 +240,7 @@ public: private: friend class CFGElement; + static bool isKind(const CFGElement &E) { Kind kind = E.getKind(); return kind >= DTOR_BEGIN && kind <= DTOR_END; @@ -231,7 +266,9 @@ public: private: friend class CFGElement; - CFGAutomaticObjDtor() {} + + CFGAutomaticObjDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == AutomaticObjectDtor; } @@ -255,7 +292,9 @@ public: private: friend class CFGElement; - CFGDeleteDtor() {} + + CFGDeleteDtor() = default; + static bool isKind(const CFGElement &elem) { return elem.getKind() == DeleteDtor; } @@ -274,7 +313,9 @@ public: private: friend class CFGElement; - CFGBaseDtor() {} + + CFGBaseDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == BaseDtor; } @@ -293,7 +334,9 @@ public: private: friend class CFGElement; - CFGMemberDtor() {} + + CFGMemberDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == MemberDtor; } @@ -312,7 +355,9 @@ public: private: friend class CFGElement; - CFGTemporaryDtor() {} + + CFGTemporaryDtor() = default; + static bool isKind(const CFGElement &E) { return E.getKind() == TemporaryDtor; } @@ -326,8 +371,9 @@ private: /// of matching full expression. class CFGTerminator { llvm::PointerIntPair<Stmt *, 1> Data; + public: - CFGTerminator() {} + CFGTerminator() = default; CFGTerminator(Stmt *S, bool TemporaryDtorsBranch = false) : Data(S, TemporaryDtorsBranch) {} @@ -373,21 +419,23 @@ public: /// &&, || expression that uses result of && or ||, RHS /// /// But note that any of that may be NULL in case of optimized-out edges. -/// class CFGBlock { class ElementList { - typedef BumpVector<CFGElement> ImplTy; + using ImplTy = BumpVector<CFGElement>; + ImplTy Impl; + public: ElementList(BumpVectorContext &C) : Impl(C, 4) {} - typedef std::reverse_iterator<ImplTy::iterator> iterator; - typedef std::reverse_iterator<ImplTy::const_iterator> const_iterator; - typedef ImplTy::iterator reverse_iterator; - typedef ImplTy::const_iterator const_reverse_iterator; - typedef ImplTy::const_reference const_reference; + using iterator = std::reverse_iterator<ImplTy::iterator>; + using const_iterator = std::reverse_iterator<ImplTy::const_iterator>; + using reverse_iterator = ImplTy::iterator; + using const_reverse_iterator = ImplTy::const_iterator; + using const_reference = ImplTy::const_reference; void push_back(CFGElement e, BumpVectorContext &C) { Impl.push_back(e, C); } + reverse_iterator insert(reverse_iterator I, size_t Cnt, CFGElement E, BumpVectorContext &C) { return Impl.insert(I, Cnt, E, C); @@ -405,10 +453,10 @@ class CFGBlock { const_reverse_iterator rbegin() const { return Impl.begin(); } const_reverse_iterator rend() const { return Impl.end(); } - CFGElement operator[](size_t i) const { - assert(i < Impl.size()); - return Impl[Impl.size() - 1 - i]; - } + CFGElement operator[](size_t i) const { + assert(i < Impl.size()); + return Impl[Impl.size() - 1 - i]; + } size_t size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } @@ -420,7 +468,7 @@ class CFGBlock { /// Label - An (optional) label that prefixes the executable /// statements in the block. When this variable is non-NULL, it is /// either an instance of LabelStmt, SwitchCase or CXXCatchStmt. - Stmt *Label; + Stmt *Label = nullptr; /// Terminator - The terminator for a basic block that /// indicates the type of control-flow that occurs between a block @@ -430,7 +478,7 @@ class CFGBlock { /// LoopTarget - Some blocks are used to represent the "loop edge" to /// the start of a loop from within the loop body. This Stmt* will be /// refer to the loop statement for such blocks (and be null otherwise). - const Stmt *LoopTarget; + const Stmt *LoopTarget = nullptr; /// BlockID - A numerical ID assigned to a CFGBlock during construction /// of the CFG. @@ -450,7 +498,7 @@ public: }; CFGBlock *ReachableBlock; - llvm::PointerIntPair<CFGBlock*, 2> UnreachableBlock; + llvm::PointerIntPair<CFGBlock *, 2> UnreachableBlock; public: /// Construct an AdjacentBlock with a possibly unreachable block. @@ -493,7 +541,7 @@ public: private: /// Predecessors/Successors - Keep track of the predecessor / successor /// CFG blocks. - typedef BumpVector<AdjacentBlock> AdjacentBlocks; + using AdjacentBlocks = BumpVector<AdjacentBlock>; AdjacentBlocks Preds; AdjacentBlocks Succs; @@ -513,15 +561,14 @@ private: public: explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent) - : Elements(C), Label(nullptr), Terminator(nullptr), LoopTarget(nullptr), - BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false), - Parent(parent) {} + : Elements(C), Terminator(nullptr), BlockID(blockid), Preds(C, 1), + Succs(C, 1), HasNoReturnElement(false), Parent(parent) {} // Statement iterators - typedef ElementList::iterator iterator; - typedef ElementList::const_iterator const_iterator; - typedef ElementList::reverse_iterator reverse_iterator; - typedef ElementList::const_reverse_iterator const_reverse_iterator; + using iterator = ElementList::iterator; + using const_iterator = ElementList::const_iterator; + using reverse_iterator = ElementList::reverse_iterator; + using const_reverse_iterator = ElementList::const_reverse_iterator; CFGElement front() const { return Elements.front(); } CFGElement back() const { return Elements.back(); } @@ -542,19 +589,19 @@ public: CFGElement operator[](size_t i) const { return Elements[i]; } // CFG iterators - typedef AdjacentBlocks::iterator pred_iterator; - typedef AdjacentBlocks::const_iterator const_pred_iterator; - typedef AdjacentBlocks::reverse_iterator pred_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_pred_reverse_iterator; - typedef llvm::iterator_range<pred_iterator> pred_range; - typedef llvm::iterator_range<const_pred_iterator> pred_const_range; - - typedef AdjacentBlocks::iterator succ_iterator; - typedef AdjacentBlocks::const_iterator const_succ_iterator; - typedef AdjacentBlocks::reverse_iterator succ_reverse_iterator; - typedef AdjacentBlocks::const_reverse_iterator const_succ_reverse_iterator; - typedef llvm::iterator_range<succ_iterator> succ_range; - typedef llvm::iterator_range<const_succ_iterator> succ_const_range; + using pred_iterator = AdjacentBlocks::iterator; + using const_pred_iterator = AdjacentBlocks::const_iterator; + using pred_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_pred_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using pred_range = llvm::iterator_range<pred_iterator>; + using pred_const_range = llvm::iterator_range<const_pred_iterator>; + + using succ_iterator = AdjacentBlocks::iterator; + using const_succ_iterator = AdjacentBlocks::const_iterator; + using succ_reverse_iterator = AdjacentBlocks::reverse_iterator; + using const_succ_reverse_iterator = AdjacentBlocks::const_reverse_iterator; + using succ_range = llvm::iterator_range<succ_iterator>; + using succ_const_range = llvm::iterator_range<const_succ_iterator>; pred_iterator pred_begin() { return Preds.begin(); } pred_iterator pred_end() { return Preds.end(); } @@ -566,10 +613,11 @@ public: const_pred_reverse_iterator pred_rbegin() const { return Preds.rbegin(); } const_pred_reverse_iterator pred_rend() const { return Preds.rend(); } - pred_range preds() { + pred_range preds() { return pred_range(pred_begin(), pred_end()); } - pred_const_range preds() const { + + pred_const_range preds() const { return pred_const_range(pred_begin(), pred_end()); } @@ -583,10 +631,11 @@ public: const_succ_reverse_iterator succ_rbegin() const { return Succs.rbegin(); } const_succ_reverse_iterator succ_rend() const { return Succs.rend(); } - succ_range succs() { + succ_range succs() { return succ_range(succ_begin(), succ_end()); } - succ_const_range succs() const { + + succ_const_range succs() const { return succ_const_range(succ_begin(), succ_end()); } @@ -599,13 +648,11 @@ public: class FilterOptions { public: - FilterOptions() { - IgnoreNullPredecessors = 1; - IgnoreDefaultsWithCoveredEnums = 0; - } - unsigned IgnoreNullPredecessors : 1; unsigned IgnoreDefaultsWithCoveredEnums : 1; + + FilterOptions() + : IgnoreNullPredecessors(1), IgnoreDefaultsWithCoveredEnums(0) {} }; static bool FilterEdge(const FilterOptions &F, const CFGBlock *Src, @@ -617,6 +664,7 @@ public: IMPL I, E; const FilterOptions F; const CFGBlock *From; + public: explicit FilteredCFGBlockIterator(const IMPL &i, const IMPL &e, const CFGBlock *from, @@ -634,17 +682,18 @@ public: } const CFGBlock *operator*() const { return *I; } + private: bool Filter(const CFGBlock *To) { return IsPred ? FilterEdge(F, To, From) : FilterEdge(F, From, To); } }; - typedef FilteredCFGBlockIterator<const_pred_iterator, true> - filtered_pred_iterator; + using filtered_pred_iterator = + FilteredCFGBlockIterator<const_pred_iterator, true>; - typedef FilteredCFGBlockIterator<const_succ_iterator, false> - filtered_succ_iterator; + using filtered_succ_iterator = + FilteredCFGBlockIterator<const_succ_iterator, false>; filtered_pred_iterator filtered_pred_start_end(const FilterOptions &f) const { return filtered_pred_iterator(pred_begin(), pred_end(), this, f); @@ -728,6 +777,10 @@ public: Elements.push_back(CFGLifetimeEnds(VD, S), C); } + void appendLoopExit(const Stmt *LoopStmt, BumpVectorContext &C) { + Elements.push_back(CFGLoopExit(LoopStmt), C); + } + void appendDeleteDtor(CXXRecordDecl *RD, CXXDeleteExpr *DE, BumpVectorContext &C) { Elements.push_back(CFGDeleteDtor(RD, DE), C); } @@ -763,11 +816,12 @@ public: /// operator error is found when building the CFG. class CFGCallback { public: - CFGCallback() {} + CFGCallback() = default; + virtual ~CFGCallback() = default; + virtual void compareAlwaysTrue(const BinaryOperator *B, bool isAlwaysTrue) {} virtual void compareBitwiseEquality(const BinaryOperator *B, bool isAlwaysTrue) {} - virtual ~CFGCallback() {} }; /// CFG - Represents a source-level, intra-procedural CFG that represents the @@ -785,19 +839,24 @@ public: class BuildOptions { std::bitset<Stmt::lastStmtConstant> alwaysAddMask; + public: - typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; - ForcedBlkExprs **forcedBlkExprs; - CFGCallback *Observer; - bool PruneTriviallyFalseEdges; - bool AddEHEdges; - bool AddInitializers; - bool AddImplicitDtors; - bool AddLifetime; - bool AddTemporaryDtors; - bool AddStaticInitBranches; - bool AddCXXNewAllocator; - bool AddCXXDefaultInitExprInCtors; + using ForcedBlkExprs = llvm::DenseMap<const Stmt *, const CFGBlock *>; + + ForcedBlkExprs **forcedBlkExprs = nullptr; + CFGCallback *Observer = nullptr; + bool PruneTriviallyFalseEdges = true; + bool AddEHEdges = false; + bool AddInitializers = false; + bool AddImplicitDtors = false; + bool AddLifetime = false; + bool AddLoopExit = false; + bool AddTemporaryDtors = false; + bool AddStaticInitBranches = false; + bool AddCXXNewAllocator = false; + bool AddCXXDefaultInitExprInCtors = false; + + BuildOptions() = default; bool alwaysAdd(const Stmt *stmt) const { return alwaysAddMask[stmt->getStmtClass()]; @@ -812,15 +871,6 @@ public: alwaysAddMask.set(); return *this; } - - BuildOptions() - : forcedBlkExprs(nullptr), Observer(nullptr), - PruneTriviallyFalseEdges(true), - AddEHEdges(false), - AddInitializers(false), AddImplicitDtors(false), - AddLifetime(false), - AddTemporaryDtors(false), AddStaticInitBranches(false), - AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {} }; /// buildCFG - Builds a CFG from an AST. @@ -844,11 +894,11 @@ public: // Block Iterators //===--------------------------------------------------------------------===// - typedef BumpVector<CFGBlock*> CFGBlockListTy; - typedef CFGBlockListTy::iterator iterator; - typedef CFGBlockListTy::const_iterator const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + using CFGBlockListTy = BumpVector<CFGBlock *>; + using iterator = CFGBlockListTy::iterator; + using const_iterator = CFGBlockListTy::const_iterator; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; CFGBlock & front() { return *Blocks.front(); } CFGBlock & back() { return *Blocks.back(); } @@ -876,10 +926,12 @@ public: CFGBlock * getIndirectGotoBlock() { return IndirectGotoBlock; } const CFGBlock * getIndirectGotoBlock() const { return IndirectGotoBlock; } - typedef std::vector<const CFGBlock*>::const_iterator try_block_iterator; + using try_block_iterator = std::vector<const CFGBlock *>::const_iterator; + try_block_iterator try_blocks_begin() const { return TryDispatchBlocks.begin(); } + try_block_iterator try_blocks_end() const { return TryDispatchBlocks.end(); } @@ -900,9 +952,9 @@ public: SyntheticDeclStmts[Synthetic] = Source; } - typedef llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator - synthetic_stmt_iterator; - typedef llvm::iterator_range<synthetic_stmt_iterator> synthetic_stmt_range; + using synthetic_stmt_iterator = + llvm::DenseMap<const DeclStmt *, const DeclStmt *>::const_iterator; + using synthetic_stmt_range = llvm::iterator_range<synthetic_stmt_iterator>; /// Iterates over synthetic DeclStmts in the CFG. /// @@ -962,9 +1014,7 @@ public: // Internal: constructors and data. //===--------------------------------------------------------------------===// - CFG() - : Entry(nullptr), Exit(nullptr), IndirectGotoBlock(nullptr), NumBlockIDs(0), - Blocks(BlkBVC, 10) {} + CFG() : Blocks(BlkBVC, 10) {} llvm::BumpPtrAllocator& getAllocator() { return BlkBVC.getAllocator(); @@ -975,11 +1025,13 @@ public: } private: - CFGBlock *Entry; - CFGBlock *Exit; - CFGBlock* IndirectGotoBlock; // Special block to contain collective dispatch - // for indirect gotos - unsigned NumBlockIDs; + CFGBlock *Entry = nullptr; + CFGBlock *Exit = nullptr; + + // Special block to contain collective dispatch for indirect gotos + CFGBlock* IndirectGotoBlock = nullptr; + + unsigned NumBlockIDs = 0; BumpVectorContext BlkBVC; @@ -993,7 +1045,8 @@ private: /// source DeclStmt. llvm::DenseMap<const DeclStmt *, const DeclStmt *> SyntheticDeclStmts; }; -} // end namespace clang + +} // namespace clang //===----------------------------------------------------------------------===// // GraphTraits specializations for CFG basic block graphs (source-level CFGs) @@ -1004,7 +1057,8 @@ namespace llvm { /// Implement simplify_type for CFGTerminator, so that we can dyn_cast from /// CFGTerminator to a specific Stmt class. template <> struct simplify_type< ::clang::CFGTerminator> { - typedef ::clang::Stmt *SimpleType; + using SimpleType = ::clang::Stmt *; + static SimpleType getSimplifiedValue(::clang::CFGTerminator Val) { return Val.getStmt(); } @@ -1013,50 +1067,44 @@ template <> struct simplify_type< ::clang::CFGTerminator> { // Traits for: CFGBlock template <> struct GraphTraits< ::clang::CFGBlock *> { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::succ_iterator ChildIteratorType; + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::succ_iterator; static NodeRef getEntryNode(::clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; template <> struct GraphTraits< const ::clang::CFGBlock *> { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_succ_iterator ChildIteratorType; + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_succ_iterator; static NodeRef getEntryNode(const clang::CFGBlock *BB) { return BB; } - static ChildIteratorType child_begin(NodeRef N) { return N->succ_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->succ_end(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > { - typedef ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse< ::clang::CFGBlock *>> { + using NodeRef = ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { - typedef const ::clang::CFGBlock *NodeRef; - typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType; +template <> struct GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using NodeRef = const ::clang::CFGBlock *; + using ChildIteratorType = ::clang::CFGBlock::const_pred_iterator; static NodeRef getEntryNode(Inverse<const ::clang::CFGBlock *> G) { return G.Graph; } static ChildIteratorType child_begin(NodeRef N) { return N->pred_begin(); } - static ChildIteratorType child_end(NodeRef N) { return N->pred_end(); } }; @@ -1064,8 +1112,7 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > { template <> struct GraphTraits< ::clang::CFG* > : public GraphTraits< ::clang::CFGBlock *> { - - typedef ::clang::CFG::iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getEntry(); } static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();} @@ -1075,44 +1122,47 @@ template <> struct GraphTraits< ::clang::CFG* > template <> struct GraphTraits<const ::clang::CFG* > : public GraphTraits<const ::clang::CFGBlock *> { - - typedef ::clang::CFG::const_iterator nodes_iterator; + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getEntry(); } + static nodes_iterator nodes_begin( const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end( const ::clang::CFG* F) { return F->nodes_end(); } + static unsigned size(const ::clang::CFG* F) { return F->size(); } }; -template <> struct GraphTraits<Inverse< ::clang::CFG*> > - : public GraphTraits<Inverse< ::clang::CFGBlock*> > { - - typedef ::clang::CFG::iterator nodes_iterator; +template <> struct GraphTraits<Inverse< ::clang::CFG *>> + : public GraphTraits<Inverse< ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::iterator; static NodeRef getEntryNode(::clang::CFG *F) { return &F->getExit(); } static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();} static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); } }; -template <> struct GraphTraits<Inverse<const ::clang::CFG*> > - : public GraphTraits<Inverse<const ::clang::CFGBlock*> > { - - typedef ::clang::CFG::const_iterator nodes_iterator; +template <> struct GraphTraits<Inverse<const ::clang::CFG *>> + : public GraphTraits<Inverse<const ::clang::CFGBlock *>> { + using nodes_iterator = ::clang::CFG::const_iterator; static NodeRef getEntryNode(const ::clang::CFG *F) { return &F->getExit(); } + static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->nodes_begin(); } + static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->nodes_end(); } }; -} // end llvm namespace + +} // namespace llvm #endif // LLVM_CLANG_ANALYSIS_CFG_H diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index a2a27a8e47c7..bdcdfecddc3e 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -1,4 +1,4 @@ -//== CallGraph.h - AST-based Call graph ------------------------*- C++ -*--==// +//===- CallGraph.h - AST-based Call graph -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,19 +12,27 @@ // A call graph for functions whose definitions/bodies are available in the // current translation unit. The graph has a "virtual" root node that contains // edges to all externally available functions. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H #define LLVM_CLANG_ANALYSIS_CALLGRAPH_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/RecursiveASTVisitor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include <memory> namespace clang { + class CallGraphNode; +class Decl; +class DeclContext; +class Stmt; /// \brief The AST-based call graph. /// @@ -34,8 +42,8 @@ class CallGraphNode; class CallGraph : public RecursiveASTVisitor<CallGraph> { friend class CallGraphNode; - typedef llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>> - FunctionMapTy; + using FunctionMapTy = + llvm::DenseMap<const Decl *, std::unique_ptr<CallGraphNode>>; /// FunctionMap owns all CallGraphNodes. FunctionMapTy FunctionMap; @@ -65,10 +73,11 @@ public: /// one into the graph. CallGraphNode *getOrInsertNode(Decl *); + using iterator = FunctionMapTy::iterator; + using const_iterator = FunctionMapTy::const_iterator; + /// Iterators through all the elements in the graph. Note, this gives /// non-deterministic order. - typedef FunctionMapTy::iterator iterator; - typedef FunctionMapTy::const_iterator const_iterator; iterator begin() { return FunctionMap.begin(); } iterator end() { return FunctionMap.end(); } const_iterator begin() const { return FunctionMap.begin(); } @@ -84,8 +93,8 @@ public: /// Iterators through all the nodes of the graph that have no parent. These /// are the unreachable nodes, which are either unused or are due to us /// failing to add a call edge due to the analysis imprecision. - typedef llvm::SetVector<CallGraphNode *>::iterator nodes_iterator; - typedef llvm::SetVector<CallGraphNode *>::const_iterator const_nodes_iterator; + using nodes_iterator = llvm::SetVector<CallGraphNode *>::iterator; + using const_nodes_iterator = llvm::SetVector<CallGraphNode *>::const_iterator; void print(raw_ostream &os) const; void dump() const; @@ -133,7 +142,7 @@ private: class CallGraphNode { public: - typedef CallGraphNode* CallRecord; + using CallRecord = CallGraphNode *; private: /// \brief The function/method declaration. @@ -145,17 +154,17 @@ private: public: CallGraphNode(Decl *D) : FD(D) {} - typedef SmallVectorImpl<CallRecord>::iterator iterator; - typedef SmallVectorImpl<CallRecord>::const_iterator const_iterator; + using iterator = SmallVectorImpl<CallRecord>::iterator; + using const_iterator = SmallVectorImpl<CallRecord>::const_iterator; /// Iterators through all the callees/children of the node. - inline iterator begin() { return CalledFunctions.begin(); } - inline iterator end() { return CalledFunctions.end(); } - inline const_iterator begin() const { return CalledFunctions.begin(); } - inline const_iterator end() const { return CalledFunctions.end(); } + iterator begin() { return CalledFunctions.begin(); } + iterator end() { return CalledFunctions.end(); } + const_iterator begin() const { return CalledFunctions.begin(); } + const_iterator end() const { return CalledFunctions.end(); } - inline bool empty() const {return CalledFunctions.empty(); } - inline unsigned size() const {return CalledFunctions.size(); } + bool empty() const { return CalledFunctions.empty(); } + unsigned size() const { return CalledFunctions.size(); } void addCallee(CallGraphNode *N) { CalledFunctions.push_back(N); @@ -167,35 +176,33 @@ public: void dump() const; }; -} // end clang namespace +} // namespace clang // Graph traits for iteration, viewing. namespace llvm { + template <> struct GraphTraits<clang::CallGraphNode*> { - typedef clang::CallGraphNode NodeType; - typedef clang::CallGraphNode *NodeRef; - typedef NodeType::iterator ChildIteratorType; + using NodeType = clang::CallGraphNode; + using NodeRef = clang::CallGraphNode *; + using ChildIteratorType = NodeType::iterator; static NodeType *getEntryNode(clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { - return N->begin(); - } - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin(); } + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits<const clang::CallGraphNode*> { - typedef const clang::CallGraphNode NodeType; - typedef const clang::CallGraphNode *NodeRef; - typedef NodeType::const_iterator ChildIteratorType; + using NodeType = const clang::CallGraphNode; + using NodeRef = const clang::CallGraphNode *; + using ChildIteratorType = NodeType::const_iterator; static NodeType *getEntryNode(const clang::CallGraphNode *CGN) { return CGN; } - static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} - static inline ChildIteratorType child_end(NodeType *N) { return N->end(); } + static ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static ChildIteratorType child_end(NodeType *N) { return N->end(); } }; template <> struct GraphTraits<clang::CallGraph*> : public GraphTraits<clang::CallGraphNode*> { - static NodeType *getEntryNode(clang::CallGraph *CGN) { return CGN->getRoot(); // Start at the external node! } @@ -206,19 +213,18 @@ template <> struct GraphTraits<clang::CallGraph*> } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)> - nodes_iterator; + using nodes_iterator = + mapped_iterator<clang::CallGraph::iterator, decltype(&CGGetValue)>; static nodes_iterator nodes_begin(clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end (clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(clang::CallGraph *CG) { - return CG->size(); - } + static unsigned size(clang::CallGraph *CG) { return CG->size(); } }; template <> struct GraphTraits<const clang::CallGraph*> : @@ -233,21 +239,20 @@ template <> struct GraphTraits<const clang::CallGraph*> : } // nodes_iterator/begin/end - Allow iteration over all nodes in the graph - typedef mapped_iterator<clang::CallGraph::const_iterator, - decltype(&CGGetValue)> - nodes_iterator; + using nodes_iterator = + mapped_iterator<clang::CallGraph::const_iterator, decltype(&CGGetValue)>; static nodes_iterator nodes_begin(const clang::CallGraph *CG) { return nodes_iterator(CG->begin(), &CGGetValue); } + static nodes_iterator nodes_end(const clang::CallGraph *CG) { return nodes_iterator(CG->end(), &CGGetValue); } - static unsigned size(const clang::CallGraph *CG) { - return CG->size(); - } + + static unsigned size(const clang::CallGraph *CG) { return CG->size(); } }; -} // end llvm namespace +} // namespace llvm -#endif +#endif // LLVM_CLANG_ANALYSIS_CALLGRAPH_H diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h index 6339deef41bd..051b9236658c 100644 --- a/include/clang/Analysis/CloneDetection.h +++ b/include/clang/Analysis/CloneDetection.h @@ -7,19 +7,15 @@ // //===----------------------------------------------------------------------===// /// -/// /file -/// This file defines classes for searching and anlyzing source code clones. +/// \file +/// This file defines classes for searching and analyzing source code clones. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_CLONEDETECTION_H #define LLVM_CLANG_AST_CLONEDETECTION_H -#include "clang/AST/DeclTemplate.h" #include "clang/AST/StmtVisitor.h" -#include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" #include "llvm/Support/Regex.h" #include <vector> @@ -31,192 +27,6 @@ class VarDecl; class ASTContext; class CompoundStmt; -namespace clone_detection { - -/// Returns a string that represents all macro expansions that expanded into the -/// given SourceLocation. -/// -/// If 'getMacroStack(A) == getMacroStack(B)' is true, then the SourceLocations -/// A and B are expanded from the same macros in the same order. -std::string getMacroStack(SourceLocation Loc, ASTContext &Context); - -/// Collects the data of a single Stmt. -/// -/// This class defines what a code clone is: If it collects for two statements -/// the same data, then those two statements are considered to be clones of each -/// other. -/// -/// All collected data is forwarded to the given data consumer of the type T. -/// The data consumer class needs to provide a member method with the signature: -/// update(StringRef Str) -template <typename T> -class StmtDataCollector : public ConstStmtVisitor<StmtDataCollector<T>> { - - ASTContext &Context; - /// The data sink to which all data is forwarded. - T &DataConsumer; - -public: - /// Collects data of the given Stmt. - /// \param S The given statement. - /// \param Context The ASTContext of S. - /// \param DataConsumer The data sink to which all data is forwarded. - StmtDataCollector(const Stmt *S, ASTContext &Context, T &DataConsumer) - : Context(Context), DataConsumer(DataConsumer) { - this->Visit(S); - } - - typedef unsigned DataPiece; - - // Below are utility methods for appending different data to the vector. - - void addData(DataPiece Integer) { - DataConsumer.update( - StringRef(reinterpret_cast<char *>(&Integer), sizeof(Integer))); - } - - void addData(llvm::StringRef Str) { DataConsumer.update(Str); } - - void addData(const QualType &QT) { addData(QT.getAsString()); } - -// The functions below collect the class specific data of each Stmt subclass. - -// Utility macro for defining a visit method for a given class. This method -// calls back to the ConstStmtVisitor to visit all parent classes. -#define DEF_ADD_DATA(CLASS, CODE) \ - void Visit##CLASS(const CLASS *S) { \ - CODE; \ - ConstStmtVisitor<StmtDataCollector>::Visit##CLASS(S); \ - } - - DEF_ADD_DATA(Stmt, { - addData(S->getStmtClass()); - // This ensures that macro generated code isn't identical to macro-generated - // code. - addData(getMacroStack(S->getLocStart(), Context)); - addData(getMacroStack(S->getLocEnd(), Context)); - }) - DEF_ADD_DATA(Expr, { addData(S->getType()); }) - - //--- Builtin functionality ----------------------------------------------// - DEF_ADD_DATA(ArrayTypeTraitExpr, { addData(S->getTrait()); }) - DEF_ADD_DATA(ExpressionTraitExpr, { addData(S->getTrait()); }) - DEF_ADD_DATA(PredefinedExpr, { addData(S->getIdentType()); }) - DEF_ADD_DATA(TypeTraitExpr, { - addData(S->getTrait()); - for (unsigned i = 0; i < S->getNumArgs(); ++i) - addData(S->getArg(i)->getType()); - }) - - //--- Calls --------------------------------------------------------------// - DEF_ADD_DATA(CallExpr, { - // Function pointers don't have a callee and we just skip hashing it. - if (const FunctionDecl *D = S->getDirectCallee()) { - // If the function is a template specialization, we also need to handle - // the template arguments as they are not included in the qualified name. - if (auto Args = D->getTemplateSpecializationArgs()) { - std::string ArgString; - - // Print all template arguments into ArgString - llvm::raw_string_ostream OS(ArgString); - for (unsigned i = 0; i < Args->size(); ++i) { - Args->get(i).print(Context.getLangOpts(), OS); - // Add a padding character so that 'foo<X, XX>()' != 'foo<XX, X>()'. - OS << '\n'; - } - OS.flush(); - - addData(ArgString); - } - addData(D->getQualifiedNameAsString()); - } - }) - - //--- Exceptions ---------------------------------------------------------// - DEF_ADD_DATA(CXXCatchStmt, { addData(S->getCaughtType()); }) - - //--- C++ OOP Stmts ------------------------------------------------------// - DEF_ADD_DATA(CXXDeleteExpr, { - addData(S->isArrayFormAsWritten()); - addData(S->isGlobalDelete()); - }) - - //--- Casts --------------------------------------------------------------// - DEF_ADD_DATA(ObjCBridgedCastExpr, { addData(S->getBridgeKind()); }) - - //--- Miscellaneous Exprs ------------------------------------------------// - DEF_ADD_DATA(BinaryOperator, { addData(S->getOpcode()); }) - DEF_ADD_DATA(UnaryOperator, { addData(S->getOpcode()); }) - - //--- Control flow -------------------------------------------------------// - DEF_ADD_DATA(GotoStmt, { addData(S->getLabel()->getName()); }) - DEF_ADD_DATA(IndirectGotoStmt, { - if (S->getConstantTarget()) - addData(S->getConstantTarget()->getName()); - }) - DEF_ADD_DATA(LabelStmt, { addData(S->getDecl()->getName()); }) - DEF_ADD_DATA(MSDependentExistsStmt, { addData(S->isIfExists()); }) - DEF_ADD_DATA(AddrLabelExpr, { addData(S->getLabel()->getName()); }) - - //--- Objective-C --------------------------------------------------------// - DEF_ADD_DATA(ObjCIndirectCopyRestoreExpr, { addData(S->shouldCopy()); }) - DEF_ADD_DATA(ObjCPropertyRefExpr, { - addData(S->isSuperReceiver()); - addData(S->isImplicitProperty()); - }) - DEF_ADD_DATA(ObjCAtCatchStmt, { addData(S->hasEllipsis()); }) - - //--- Miscellaneous Stmts ------------------------------------------------// - DEF_ADD_DATA(CXXFoldExpr, { - addData(S->isRightFold()); - addData(S->getOperator()); - }) - DEF_ADD_DATA(GenericSelectionExpr, { - for (unsigned i = 0; i < S->getNumAssocs(); ++i) { - addData(S->getAssocType(i)); - } - }) - DEF_ADD_DATA(LambdaExpr, { - for (const LambdaCapture &C : S->captures()) { - addData(C.isPackExpansion()); - addData(C.getCaptureKind()); - if (C.capturesVariable()) - addData(C.getCapturedVar()->getType()); - } - addData(S->isGenericLambda()); - addData(S->isMutable()); - }) - DEF_ADD_DATA(DeclStmt, { - auto numDecls = std::distance(S->decl_begin(), S->decl_end()); - addData(static_cast<DataPiece>(numDecls)); - for (const Decl *D : S->decls()) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - addData(VD->getType()); - } - } - }) - DEF_ADD_DATA(AsmStmt, { - addData(S->isSimple()); - addData(S->isVolatile()); - addData(S->generateAsmString(Context)); - for (unsigned i = 0; i < S->getNumInputs(); ++i) { - addData(S->getInputConstraint(i)); - } - for (unsigned i = 0; i < S->getNumOutputs(); ++i) { - addData(S->getOutputConstraint(i)); - } - for (unsigned i = 0; i < S->getNumClobbers(); ++i) { - addData(S->getClobber(i)); - } - }) - DEF_ADD_DATA(AttributedStmt, { - for (const Attr *A : S->getAttrs()) { - addData(std::string(A->getSpelling())); - } - }) -}; -} // namespace clone_detection - /// Identifies a list of statements. /// /// Can either identify a single arbitrary Stmt object, a continuous sequence of @@ -423,9 +233,9 @@ public: /// filtered. /// \param Filter The filter function that should return true for all groups /// that should be removed from the list. - static void - filterGroups(std::vector<CloneDetector::CloneGroup> &CloneGroups, - std::function<bool(const CloneDetector::CloneGroup &)> Filter) { + static void filterGroups( + std::vector<CloneDetector::CloneGroup> &CloneGroups, + llvm::function_ref<bool(const CloneDetector::CloneGroup &)> Filter) { CloneGroups.erase( std::remove_if(CloneGroups.begin(), CloneGroups.end(), Filter), CloneGroups.end()); @@ -439,25 +249,29 @@ public: /// to the same CloneGroup. static void splitCloneGroups( std::vector<CloneDetector::CloneGroup> &CloneGroups, - std::function<bool(const StmtSequence &, const StmtSequence &)> Compare); + llvm::function_ref<bool(const StmtSequence &, const StmtSequence &)> + Compare); }; -/// Searches all children of the given clones for type II clones (i.e. they are -/// identical in every aspect beside the used variable names). -class RecursiveCloneTypeIIConstraint { - - /// Generates and saves a hash code for the given Stmt. - /// \param S The given Stmt. - /// \param D The Decl containing S. - /// \param StmtsByHash Output parameter that will contain the hash codes for - /// each StmtSequence in the given Stmt. - /// \return The hash code of the given Stmt. - /// - /// If the given Stmt is a CompoundStmt, this method will also generate - /// hashes for all possible StmtSequences in the children of this Stmt. - size_t saveHash(const Stmt *S, const Decl *D, - std::vector<std::pair<size_t, StmtSequence>> &StmtsByHash); +/// This constraint moves clones into clone groups of type II via hashing. +/// +/// Clones with different hash values are moved into separate clone groups. +/// Collisions are possible, and this constraint does nothing to address this +/// them. Add the slower RecursiveCloneTypeIIVerifyConstraint later in the +/// constraint chain, not necessarily immediately, to eliminate hash collisions +/// through a more detailed analysis. +class RecursiveCloneTypeIIHashConstraint { +public: + void constrain(std::vector<CloneDetector::CloneGroup> &Sequences); +}; +/// This constraint moves clones into clone groups of type II by comparing them. +/// +/// Clones that aren't type II clones are moved into separate clone groups. +/// In contrast to the RecursiveCloneTypeIIHashConstraint, all clones in a clone +/// group are guaranteed to be be type II clones of each other, but it is too +/// slow to efficiently handle large amounts of clones. +class RecursiveCloneTypeIIVerifyConstraint { public: void constrain(std::vector<CloneDetector::CloneGroup> &Sequences); }; @@ -474,14 +288,19 @@ public: MinComplexityConstraint(unsigned MinComplexity) : MinComplexity(MinComplexity) {} - size_t calculateStmtComplexity(const StmtSequence &Seq, + /// Calculates the complexity of the given StmtSequence. + /// \param Limit The limit of complexity we probe for. After reaching + /// this limit during calculation, this method is exiting + /// early to improve performance and returns this limit. + size_t calculateStmtComplexity(const StmtSequence &Seq, std::size_t Limit, const std::string &ParentMacroStack = ""); void constrain(std::vector<CloneDetector::CloneGroup> &CloneGroups) { CloneConstraint::filterGroups( CloneGroups, [this](const CloneDetector::CloneGroup &A) { if (!A.empty()) - return calculateStmtComplexity(A.front()) < MinComplexity; + return calculateStmtComplexity(A.front(), MinComplexity) < + MinComplexity; else return false; }); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index be5adfb29423..2d59dec48a88 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H #define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H -#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -83,6 +83,7 @@ public: PostImplicitCallKind, MinImplicitCallKind = PreImplicitCallKind, MaxImplicitCallKind = PostImplicitCallKind, + LoopExitKind, EpsilonKind}; private: @@ -654,6 +655,29 @@ private: } }; +/// Represents a point when we exit a loop. +/// When this ProgramPoint is encountered we can be sure that the symbolic +/// execution of the corresponding LoopStmt is finished on the given path. +/// Note: It is possible to encounter a LoopExit element when we haven't even +/// encountered the loop itself. At the current state not all loop exits will +/// result in a LoopExit program point. +class LoopExit : public ProgramPoint { +public: + LoopExit(const Stmt *LoopStmt, const LocationContext *LC) + : ProgramPoint(LoopStmt, nullptr, LoopExitKind, LC) {} + + const Stmt *getLoopStmt() const { + return static_cast<const Stmt *>(getData1()); + } + +private: + friend class ProgramPoint; + LoopExit() {} + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == LoopExitKind; + } +}; + /// This is a meta program point, which should be skipped by all the diagnostic /// reasoning etc. class EpsilonPoint : public ProgramPoint { diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 591d17b9bc03..5940520855ef 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -1,4 +1,4 @@ -//===-- BumpVector.h - Vector-like ADT that uses bump allocation --*- C++ -*-=// +//===- BumpVector.h - Vector-like ADT that uses bump allocation -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -21,16 +21,18 @@ #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/type_traits.h" -#include <algorithm> +#include <cassert> +#include <cstddef> #include <cstring> #include <iterator> #include <memory> +#include <type_traits> namespace clang { class BumpVectorContext { llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc; + public: /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator /// and destroys it when the BumpVectorContext object is destroyed. @@ -56,11 +58,13 @@ public: template<typename T> class BumpVector { - T *Begin, *End, *Capacity; + T *Begin = nullptr; + T *End = nullptr; + T *Capacity = nullptr; + public: // Default ctor - Initialize to empty. - explicit BumpVector(BumpVectorContext &C, unsigned N) - : Begin(nullptr), End(nullptr), Capacity(nullptr) { + explicit BumpVector(BumpVectorContext &C, unsigned N) { reserve(C, N); } @@ -71,19 +75,19 @@ public: } } - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef T value_type; - typedef T* iterator; - typedef const T* const_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + using value_type = T; + using iterator = T *; + using const_iterator = const T *; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; + using reverse_iterator = std::reverse_iterator<iterator>; - typedef T& reference; - typedef const T& const_reference; - typedef T* pointer; - typedef const T* const_pointer; + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; // forward iterator creation methods. iterator begin() { return Begin; } @@ -92,10 +96,12 @@ public: const_iterator end() const { return End; } // reverse iterator creation methods. - reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin());} + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } bool empty() const { return Begin == End; } size_type size() const { return End-Begin; } @@ -166,7 +172,7 @@ public: /// iterator to position after last inserted copy. iterator insert(iterator I, size_t Cnt, const_reference E, BumpVectorContext &C) { - assert (I >= Begin && I <= End && "Iterator out of bounds."); + assert(I >= Begin && I <= End && "Iterator out of bounds."); if (End + Cnt <= Capacity) { Retry: move_range_right(I, End, Cnt); @@ -246,5 +252,6 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { Capacity = Begin+NewCapacity; } -} // end: clang namespace -#endif +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H |