From 79bbdd4289dd55cb66d4dcaed2f0fce2e79c6a34 Mon Sep 17 00:00:00 2001 From: Eugene Zelenko Date: Tue, 13 Mar 2018 21:32:01 +0000 Subject: [PATCH] [Analysis] Fix some Clang-tidy modernize and Include What You Use warnings; other minor fixes (NFC). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@327453 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Analysis/Analyses/Consumed.h | 69 ++++--- include/clang/Analysis/Analyses/Dominators.h | 65 +++---- .../Analysis/Analyses/PostOrderCFGView.h | 48 ++--- .../Analysis/Analyses/ThreadSafetyCommon.h | 183 ++++++++++-------- lib/Analysis/Consumed.cpp | 171 +++++++--------- lib/Analysis/Dominators.cpp | 4 +- lib/Analysis/PostOrderCFGView.cpp | 7 +- lib/Analysis/ThreadSafetyCommon.cpp | 99 +++++----- 8 files changed, 326 insertions(+), 320 deletions(-) diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index 5ba42b475c..295d122d48 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -1,4 +1,4 @@ -//===- Consumed.h ----------------------------------------------*- C++ --*-===// +//===- Consumed.h -----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,32 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H #define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H -#include "clang/AST/DeclCXX.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtCXX.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" -#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include +#include +#include +#include namespace clang { + +class AnalysisDeclContext; +class CXXBindTemporaryExpr; +class FunctionDecl; +class PostOrderCFGView; +class Stmt; +class VarDecl; + namespace consumed { + class ConsumedStmtVisitor; + enum ConsumedState { // No state information for the given variable. CS_None, @@ -34,16 +50,12 @@ namespace consumed { CS_Consumed }; - class ConsumedStmtVisitor; - - typedef SmallVector OptionalNotes; - typedef std::pair DelayedDiag; - typedef std::list DiagList; + using OptionalNotes = SmallVector; + using DelayedDiag = std::pair; + using DiagList = std::list; class ConsumedWarningsHandlerBase { - public: - virtual ~ConsumedWarningsHandlerBase(); /// \brief Emit the warnings and notes left by the analysis. @@ -129,23 +141,21 @@ namespace consumed { }; class ConsumedStateMap { - - typedef llvm::DenseMap VarMapType; - typedef llvm::DenseMap - TmpMapType; + using VarMapType = llvm::DenseMap; + using TmpMapType = + llvm::DenseMap; protected: - - bool Reachable; - const Stmt *From; + bool Reachable = true; + const Stmt *From = nullptr; VarMapType VarMap; TmpMapType TmpMap; public: - ConsumedStateMap() : Reachable(true), From(nullptr) {} + ConsumedStateMap() = default; ConsumedStateMap(const ConsumedStateMap &Other) - : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), - TmpMap() {} + : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), + TmpMap() {} /// \brief Warn if any of the parameters being tracked are not in the state /// they were declared to be in upon return from a function. @@ -205,10 +215,8 @@ namespace consumed { ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) : StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) { unsigned int VisitOrderCounter = 0; - for (PostOrderCFGView::iterator BI = SortedGraph->begin(), - BE = SortedGraph->end(); BI != BE; ++BI) { - VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++; - } + for (const auto BI : *SortedGraph) + VisitOrder[BI->getBlockID()] = VisitOrderCounter++; } bool allBackEdgesVisited(const CFGBlock *CurrBlock, @@ -231,7 +239,6 @@ namespace consumed { /// A class that handles the analysis of uniqueness violations. class ConsumedAnalyzer { - ConsumedBlockInfo BlockInfo; std::unique_ptr CurrStates; @@ -243,7 +250,6 @@ namespace consumed { const ConsumedStmtVisitor &Visitor); public: - ConsumedWarningsHandlerBase &WarningsHandler; ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler) @@ -259,6 +265,9 @@ namespace consumed { /// exactly once. void run(AnalysisDeclContext &AC); }; -}} // end namespace clang::consumed -#endif +} // namespace consumed + +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index 6cb161ab37..963bbd3d79 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -1,4 +1,4 @@ -//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==// +//- Dominators.h - Implementation of dominators tree for Clang CFG -*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -16,29 +16,35 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/GenericDomTree.h" -#include "llvm/Support/GenericDomTreeConstruction.h" +#include "llvm/Support/GenericDomTreeConstruction.h" +#include "llvm/Support/raw_ostream.h" // FIXME: There is no good reason for the domtree to require a print method // which accepts an LLVM Module, so remove this (and the method's argument that // needs it) when that is fixed. + namespace llvm { + class Module; -} + +} // namespace llvm namespace clang { -class CFGBlock; -typedef llvm::DomTreeNodeBase DomTreeNode; +using DomTreeNode = llvm::DomTreeNodeBase; /// \brief Concrete subclass of DominatorTreeBase for Clang /// This class implements the dominators tree functionality given a Clang CFG. /// class DominatorTree : public ManagedAnalysis { virtual void anchor(); + public: - llvm::DomTreeBase* DT; + llvm::DomTreeBase *DT; DominatorTree() { DT = new llvm::DomTreeBase(); @@ -49,22 +55,20 @@ public: llvm::DomTreeBase& getBase() { return *DT; } /// \brief This method returns the root CFGBlock of the dominators tree. - /// - inline CFGBlock *getRoot() const { + CFGBlock *getRoot() const { return DT->getRoot(); } /// \brief This method returns the root DomTreeNode, which is the wrapper /// for CFGBlock. - inline DomTreeNode *getRootNode() const { + DomTreeNode *getRootNode() const { return DT->getRootNode(); } /// \brief This method compares two dominator trees. /// The method returns false if the other dominator tree matches this /// dominator tree, otherwise returns true. - /// - inline bool compare(DominatorTree &Other) const { + bool compare(DominatorTree &Other) const { DomTreeNode *R = getRootNode(); DomTreeNode *OtherR = Other.getRootNode(); @@ -79,7 +83,6 @@ public: /// \brief This method builds the dominator tree for a given CFG /// The CFG information is passed via AnalysisDeclContext - /// void buildDominatorTree(AnalysisDeclContext &AC) { cfg = AC.getCFG(); DT->recalculate(*cfg); @@ -87,7 +90,6 @@ public: /// \brief This method dumps immediate dominators for each block, /// mainly used for debug purposes. - /// void dump() { llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; for (CFG::const_iterator I = cfg->begin(), @@ -105,52 +107,45 @@ public: /// \brief This method tests if one CFGBlock dominates the other. /// The method return true if A dominates B, false otherwise. /// Note a block always dominates itself. - /// - inline bool dominates(const CFGBlock* A, const CFGBlock* B) const { + bool dominates(const CFGBlock *A, const CFGBlock *B) const { return DT->dominates(A, B); } /// \brief This method tests if one CFGBlock properly dominates the other. /// The method return true if A properly dominates B, false otherwise. - /// - bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const { + bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const { return DT->properlyDominates(A, B); } /// \brief This method finds the nearest common dominator CFG block /// for CFG block A and B. If there is no such block then return NULL. - /// - inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { + CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { return DT->findNearestCommonDominator(A, B); } - inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A, - const CFGBlock *B) { + const CFGBlock *findNearestCommonDominator(const CFGBlock *A, + const CFGBlock *B) { return DT->findNearestCommonDominator(A, B); } /// \brief This method is used to update the dominator /// tree information when a node's immediate dominator changes. - /// - inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { + void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { DT->changeImmediateDominator(N, NewIDom); } /// \brief This method tests if the given CFGBlock can be reachable from root. /// Returns true if reachable, false otherwise. - /// bool isReachableFromEntry(const CFGBlock *A) { return DT->isReachableFromEntry(A); } /// \brief This method releases the memory held by the dominator tree. - /// virtual void releaseMemory() { DT->releaseMemory(); } /// \brief This method converts the dominator tree to human readable form. - /// virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const { DT->print(OS); } @@ -159,23 +154,24 @@ private: CFG *cfg; }; -} // end namespace clang +} // namespace clang //===------------------------------------- /// DominatorTree GraphTraits specialization so the DominatorTree can be /// iterable by generic graph iterators. /// namespace llvm { + template <> struct GraphTraits< ::clang::DomTreeNode* > { - typedef ::clang::DomTreeNode *NodeRef; - typedef ::clang::DomTreeNode::iterator ChildIteratorType; + using NodeRef = ::clang::DomTreeNode *; + using ChildIteratorType = ::clang::DomTreeNode::iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } static ChildIteratorType child_end(NodeRef N) { return N->end(); } - typedef llvm::pointer_iterator> - nodes_iterator; + using nodes_iterator = + llvm::pointer_iterator>; static nodes_iterator nodes_begin(::clang::DomTreeNode *N) { return nodes_iterator(df_begin(getEntryNode(N))); @@ -187,7 +183,7 @@ template <> struct GraphTraits< ::clang::DomTreeNode* > { }; template <> struct GraphTraits< ::clang::DominatorTree* > - : public GraphTraits< ::clang::DomTreeNode* > { + : public GraphTraits< ::clang::DomTreeNode* > { static NodeRef getEntryNode(::clang::DominatorTree *DT) { return DT->getRootNode(); } @@ -200,6 +196,7 @@ template <> struct GraphTraits< ::clang::DominatorTree* > return nodes_iterator(df_end(getEntryNode(N))); } }; -} // end namespace llvm -#endif +} // namespace llvm + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h index c0a9352837..e76f3d4f3d 100644 --- a/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -1,4 +1,4 @@ -//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-// +//===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,20 +14,21 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H #define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H -#include -//#include - -#include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/BitVector.h" - #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PostOrderIterator.h" +#include +#include namespace clang { class PostOrderCFGView : public ManagedAnalysis { virtual void anchor(); + public: /// \brief Implements a set of CFGBlocks using a BitVector. /// @@ -37,12 +38,13 @@ public: /// visit during the analysis. class CFGBlockSet { llvm::BitVector VisitedBlockIDs; + public: // po_iterator requires this iterator, but the only interface needed is the - // value_type typedef. - struct iterator { typedef const CFGBlock *value_type; }; + // value_type type. + struct iterator { using value_type = const CFGBlock *; }; - CFGBlockSet() {} + CFGBlockSet() = default; CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {} /// \brief Set the bit associated with a particular CFGBlock. @@ -69,33 +71,34 @@ public: }; private: - typedef llvm::po_iterator po_iterator; - std::vector Blocks; + using po_iterator = llvm::po_iterator; + std::vector Blocks; - typedef llvm::DenseMap BlockOrderTy; + using BlockOrderTy = llvm::DenseMap; BlockOrderTy BlockOrder; public: - typedef std::vector::reverse_iterator iterator; - typedef std::vector::const_reverse_iterator const_iterator; + friend struct BlockOrderCompare; + + using iterator = std::vector::reverse_iterator; + using const_iterator = std::vector::const_reverse_iterator; PostOrderCFGView(const CFG *cfg); iterator begin() { return Blocks.rbegin(); } - iterator end() { return Blocks.rend(); } + iterator end() { return Blocks.rend(); } const_iterator begin() const { return Blocks.rbegin(); } const_iterator end() const { return Blocks.rend(); } bool empty() const { return begin() == end(); } - struct BlockOrderCompare; - friend struct BlockOrderCompare; - struct BlockOrderCompare { const PostOrderCFGView &POV; + public: BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {} + bool operator()(const CFGBlock *b1, const CFGBlock *b2) const; }; @@ -109,7 +112,6 @@ public: static PostOrderCFGView *create(AnalysisDeclContext &analysisContext); }; -} // end clang namespace - -#endif +} // namespace clang +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 414645b723..76a467a9b9 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -1,4 +1,4 @@ -//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===// +//===- ThreadSafetyCommon.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,20 +22,41 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H +#include "clang/AST/Decl.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" +#include "clang/Analysis/Analyses/ThreadSafetyUtil.h" #include "clang/Analysis/AnalysisDeclContext.h" -#include "clang/Basic/OperatorKinds.h" -#include -#include +#include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" #include +#include +#include #include - namespace clang { -namespace threadSafety { +class AbstractConditionalOperator; +class ArraySubscriptExpr; +class BinaryOperator; +class CallExpr; +class CastExpr; +class CXXDestructorDecl; +class CXXMemberCallExpr; +class CXXOperatorCallExpr; +class CXXThisExpr; +class DeclRefExpr; +class DeclStmt; +class Expr; +class MemberExpr; +class Stmt; +class UnaryOperator; + +namespace threadSafety { // Various helper functions on til::SExpr namespace sx { @@ -72,9 +93,7 @@ inline std::string toString(const til::SExpr *E) { return ss.str(); } -} // end namespace sx - - +} // namespace sx // This class defines the interface of a clang CFG Visitor. // CFGWalker will invoke the following methods. @@ -123,11 +142,10 @@ class CFGVisitor { void exitCFG(const CFGBlock *Last) {} }; - // Walks the clang CFG, and invokes methods on a given CFGVisitor. class CFGWalker { public: - CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {} + CFGWalker() = default; // Initialize the CFGWalker. This setup only needs to be done once, even // if there are multiple passes over the CFG. @@ -186,15 +204,15 @@ public: // Process statements for (const auto &BI : *CurrBlock) { switch (BI.getKind()) { - case CFGElement::Statement: { + case CFGElement::Statement: V.handleStatement(BI.castAs().getStmt()); break; - } + case CFGElement::AutomaticObjectDtor: { CFGAutomaticObjDtor AD = BI.castAs(); - CXXDestructorDecl *DD = const_cast( + auto *DD = const_cast( AD.getDestructorDecl(ACtx->getASTContext())); - VarDecl *VD = const_cast(AD.getVarDecl()); + auto *VD = const_cast(AD.getVarDecl()); V.handleDestructorCall(VD, DD); break; } @@ -242,28 +260,27 @@ public: const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } private: - CFG *CFGraph; - AnalysisDeclContext *ACtx; - PostOrderCFGView *SortedGraph; + CFG *CFGraph = nullptr; + AnalysisDeclContext *ACtx = nullptr; + PostOrderCFGView *SortedGraph = nullptr; }; - - - +// TODO: move this back into ThreadSafety.cpp +// This is specific to thread safety. It is here because +// translateAttrExpr needs it, but that should be moved too. class CapabilityExpr { - // TODO: move this back into ThreadSafety.cpp - // This is specific to thread safety. It is here because - // translateAttrExpr needs it, but that should be moved too. - private: - const til::SExpr* CapExpr; ///< The capability expression. - bool Negated; ///< True if this is a negative capability + /// The capability expression. + const til::SExpr* CapExpr; + + /// True if this is a negative capability. + bool Negated; public: CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {} - const til::SExpr* sexpr() const { return CapExpr; } - bool negative() const { return Negated; } + const til::SExpr* sexpr() const { return CapExpr; } + bool negative() const { return Negated; } CapabilityExpr operator!() const { return CapabilityExpr(CapExpr, !Negated); @@ -289,9 +306,9 @@ public: const ValueDecl* valueDecl() const { if (Negated || CapExpr == nullptr) return nullptr; - if (auto *P = dyn_cast(CapExpr)) + if (const auto *P = dyn_cast(CapExpr)) return P->clangDecl(); - if (auto *P = dyn_cast(CapExpr)) + if (const auto *P = dyn_cast(CapExpr)) return P->clangDecl(); return nullptr; } @@ -309,8 +326,6 @@ public: bool isUniversal() const { return sexpr() && isa(sexpr()); } }; - - // Translate clang::Expr to til::SExpr. class SExprBuilder { public: @@ -324,22 +339,29 @@ public: /// should be evaluated; multiple calling contexts can be chained together /// by the lock_returned attribute. struct CallingContext { - CallingContext *Prev; // The previous context; or 0 if none. - const NamedDecl *AttrDecl; // The decl to which the attr is attached. - const Expr *SelfArg; // Implicit object argument -- e.g. 'this' - unsigned NumArgs; // Number of funArgs - const Expr *const *FunArgs; // Function arguments - bool SelfArrow; // is Self referred to with -> or .? + // The previous context; or 0 if none. + CallingContext *Prev; + + // The decl to which the attr is attached. + const NamedDecl *AttrDecl; + + // Implicit object argument -- e.g. 'this' + const Expr *SelfArg = nullptr; + + // Number of funArgs + unsigned NumArgs = 0; + + // Function arguments + const Expr *const *FunArgs = nullptr; + + // is Self referred to with -> or .? + bool SelfArrow = false; CallingContext(CallingContext *P, const NamedDecl *D = nullptr) - : Prev(P), AttrDecl(D), SelfArg(nullptr), - NumArgs(0), FunArgs(nullptr), SelfArrow(false) - {} + : Prev(P), AttrDecl(D) {} }; - SExprBuilder(til::MemRegionRef A) - : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr), - CurrentBlockInfo(nullptr) { + SExprBuilder(til::MemRegionRef A) : Arena(A), CurrentBB() { // FIXME: we don't always have a self-variable. SelfVar = new (Arena) til::Variable(nullptr); SelfVar->setKind(til::Variable::VK_SFun); @@ -368,6 +390,9 @@ public: til::SCFG *getCFG() { return Scfg; } private: + // We implement the CFGVisitor API + friend class CFGWalker; + til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE, CallingContext *Ctx) ; til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); @@ -397,31 +422,30 @@ private: til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); // Map from statements in the clang CFG to SExprs in the til::SCFG. - typedef llvm::DenseMap StatementMap; + using StatementMap = llvm::DenseMap; // Map from clang local variables to indices in a LVarDefinitionMap. - typedef llvm::DenseMap LVarIndexMap; + using LVarIndexMap = llvm::DenseMap; // Map from local variable indices to SSA variables (or constants). - typedef std::pair NameVarPair; - typedef CopyOnWriteVector LVarDefinitionMap; + using NameVarPair = std::pair; + using LVarDefinitionMap = CopyOnWriteVector; struct BlockInfo { LVarDefinitionMap ExitMap; - bool HasBackEdges; - unsigned UnprocessedSuccessors; // Successors yet to be processed - unsigned ProcessedPredecessors; // Predecessors already processed + bool HasBackEdges = false; - BlockInfo() - : HasBackEdges(false), UnprocessedSuccessors(0), - ProcessedPredecessors(0) {} + // Successors yet to be processed + unsigned UnprocessedSuccessors = 0; + + // Predecessors already processed + unsigned ProcessedPredecessors = 0; + + BlockInfo() = default; BlockInfo(BlockInfo &&) = default; BlockInfo &operator=(BlockInfo &&) = default; }; - // We implement the CFGVisitor API - friend class CFGWalker; - void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First); void enterCFGBlock(const CFGBlock *B); bool visitPredecessors() { return true; } @@ -440,6 +464,7 @@ private: void insertStmt(const Stmt *S, til::SExpr *E) { SMap.insert(std::make_pair(S, E)); } + til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); til::SExpr *addStatement(til::SExpr *E, const Stmt *S, @@ -459,30 +484,36 @@ private: static const bool CapabilityExprMode = true; til::MemRegionRef Arena; - til::Variable *SelfVar; // Variable to use for 'this'. May be null. - til::SCFG *Scfg; - StatementMap SMap; // Map from Stmt to TIL Variables - LVarIndexMap LVarIdxMap; // Indices of clang local vars. - std::vector BlockMap; // Map from clang to til BBs. - std::vector BBInfo; // Extra information per BB. - // Indexed by clang BlockID. + // Variable to use for 'this'. May be null. + til::Variable *SelfVar = nullptr; + + til::SCFG *Scfg = nullptr; + + // Map from Stmt to TIL Variables + StatementMap SMap; + + // Indices of clang local vars. + LVarIndexMap LVarIdxMap; + + // Map from clang to til BBs. + std::vector BlockMap; + + // Extra information per BB. Indexed by clang BlockID. + std::vector BBInfo; LVarDefinitionMap CurrentLVarMap; - std::vector CurrentArguments; - std::vector CurrentInstructions; - std::vector IncompleteArgs; - til::BasicBlock *CurrentBB; - BlockInfo *CurrentBlockInfo; + std::vector CurrentArguments; + std::vector CurrentInstructions; + std::vector IncompleteArgs; + til::BasicBlock *CurrentBB = nullptr; + BlockInfo *CurrentBlockInfo = nullptr; }; - // Dump an SCFG to llvm::errs(). void printSCFG(CFGWalker &Walker); +} // namespace threadSafety +} // namespace clang -} // end namespace threadSafety - -} // end namespace clang - -#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H +#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H diff --git a/lib/Analysis/Consumed.cpp b/lib/Analysis/Consumed.cpp index 96edad0c30..a46386e2d1 100644 --- a/lib/Analysis/Consumed.cpp +++ b/lib/Analysis/Consumed.cpp @@ -1,4 +1,4 @@ -//===- Consumed.cpp --------------------------------------------*- C++ --*-===// +//===- Consumed.cpp -------------------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,21 +13,29 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/Consumed.h" -#include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/AST/StmtCXX.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/Type.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include #include +#include // TODO: Adjust states of args to constructors in the same way that arguments to // function calls are handled. @@ -49,7 +57,7 @@ using namespace clang; using namespace consumed; // Key method definition -ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() {} +ConsumedWarningsHandlerBase::~ConsumedWarningsHandlerBase() = default; static SourceLocation getFirstStmtLoc(const CFGBlock *Block) { // Find the source location of the first statement in the block, if the block @@ -63,7 +71,7 @@ static SourceLocation getFirstStmtLoc(const CFGBlock *Block) { if (Block->succ_size() == 1 && *Block->succ_begin()) return getFirstStmtLoc(*Block->succ_begin()); - return SourceLocation(); + return {}; } static SourceLocation getLastStmtLoc(const CFGBlock *Block) { @@ -109,7 +117,6 @@ static ConsumedState invertConsumedUnconsumed(ConsumedState State) { static bool isCallableInState(const CallableWhenAttr *CWAttr, ConsumedState State) { - for (const auto &S : CWAttr->callableStates()) { ConsumedState MappedAttrState = CS_None; @@ -134,7 +141,6 @@ static bool isCallableInState(const CallableWhenAttr *CWAttr, return false; } - static bool isConsumableType(const QualType &QT) { if (QT->isPointerType() || QT->isReferenceType()) return false; @@ -161,7 +167,6 @@ static bool isSetOnReadPtrType(const QualType &QT) { return false; } - static bool isKnownState(ConsumedState State) { switch (State) { case CS_Unconsumed: @@ -270,11 +275,13 @@ static ConsumedState testsFor(const FunctionDecl *FunDecl) { } namespace { + struct VarTestResult { const VarDecl *Var; ConsumedState TestsFor; }; -} // end anonymous::VarTestResult + +} // namespace namespace clang { namespace consumed { @@ -292,7 +299,7 @@ class PropagationInfo { IT_BinTest, IT_Var, IT_Tmp - } InfoType; + } InfoType = IT_None; struct BinTestTy { const BinaryOperator *Source; @@ -310,22 +317,19 @@ class PropagationInfo { }; public: - PropagationInfo() : InfoType(IT_None) {} - + PropagationInfo() = default; PropagationInfo(const VarTestResult &VarTest) - : InfoType(IT_VarTest), VarTest(VarTest) {} - + : InfoType(IT_VarTest), VarTest(VarTest) {} + PropagationInfo(const VarDecl *Var, ConsumedState TestsFor) - : InfoType(IT_VarTest) { - + : InfoType(IT_VarTest) { VarTest.Var = Var; VarTest.TestsFor = TestsFor; } PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarTestResult <est, const VarTestResult &RTest) - : InfoType(IT_BinTest) { - + : InfoType(IT_BinTest) { BinTest.Source = Source; BinTest.EOp = EOp; BinTest.LTest = LTest; @@ -335,8 +339,7 @@ public: PropagationInfo(const BinaryOperator *Source, EffectiveOp EOp, const VarDecl *LVar, ConsumedState LTestsFor, const VarDecl *RVar, ConsumedState RTestsFor) - : InfoType(IT_BinTest) { - + : InfoType(IT_BinTest) { BinTest.Source = Source; BinTest.EOp = EOp; BinTest.LTest.Var = LVar; @@ -346,38 +349,37 @@ public: } PropagationInfo(ConsumedState State) - : InfoType(IT_State), State(State) {} - + : InfoType(IT_State), State(State) {} PropagationInfo(const VarDecl *Var) : InfoType(IT_Var), Var(Var) {} PropagationInfo(const CXXBindTemporaryExpr *Tmp) - : InfoType(IT_Tmp), Tmp(Tmp) {} + : InfoType(IT_Tmp), Tmp(Tmp) {} - const ConsumedState & getState() const { + const ConsumedState &getState() const { assert(InfoType == IT_State); return State; } - const VarTestResult & getVarTest() const { + const VarTestResult &getVarTest() const { assert(InfoType == IT_VarTest); return VarTest; } - const VarTestResult & getLTest() const { + const VarTestResult &getLTest() const { assert(InfoType == IT_BinTest); return BinTest.LTest; } - const VarTestResult & getRTest() const { + const VarTestResult &getRTest() const { assert(InfoType == IT_BinTest); return BinTest.RTest; } - const VarDecl * getVar() const { + const VarDecl *getVar() const { assert(InfoType == IT_Var); return Var; } - const CXXBindTemporaryExpr * getTmp() const { + const CXXBindTemporaryExpr *getTmp() const { assert(InfoType == IT_Tmp); return Tmp; } @@ -405,12 +407,12 @@ public: return BinTest.Source; } - inline bool isValid() const { return InfoType != IT_None; } - inline bool isState() const { return InfoType == IT_State; } - inline bool isVarTest() const { return InfoType == IT_VarTest; } - inline bool isBinTest() const { return InfoType == IT_BinTest; } - inline bool isVar() const { return InfoType == IT_Var; } - inline bool isTmp() const { return InfoType == IT_Tmp; } + bool isValid() const { return InfoType != IT_None; } + bool isState() const { return InfoType == IT_State; } + bool isVarTest() const { return InfoType == IT_VarTest; } + bool isBinTest() const { return InfoType == IT_BinTest; } + bool isVar() const { return InfoType == IT_Var; } + bool isTmp() const { return InfoType == IT_Tmp; } bool isTest() const { return InfoType == IT_VarTest || InfoType == IT_BinTest; @@ -433,15 +435,17 @@ public: BinTest.LTest.Var, invertConsumedUnconsumed(BinTest.LTest.TestsFor), BinTest.RTest.Var, invertConsumedUnconsumed(BinTest.RTest.TestsFor)); } else { - return PropagationInfo(); + return {}; } } }; -static inline void +} // namespace consumed +} // namespace clang + +static void setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo, ConsumedState State) { - assert(PInfo.isVar() || PInfo.isTmp()); if (PInfo.isVar()) @@ -450,12 +454,14 @@ setStateForVarOrTmp(ConsumedStateMap *StateMap, const PropagationInfo &PInfo, StateMap->setState(PInfo.getTmp(), State); } +namespace clang { +namespace consumed { + class ConsumedStmtVisitor : public ConstStmtVisitor { - - typedef llvm::DenseMap MapType; - typedef std::pair PairType; - typedef MapType::iterator InfoEntry; - typedef MapType::const_iterator ConstInfoEntry; + using MapType = llvm::DenseMap; + using PairType= std::pair; + using InfoEntry = MapType::iterator; + using ConstInfoEntry = MapType::const_iterator; AnalysisDeclContext &AC; ConsumedAnalyzer &Analyzer; @@ -463,17 +469,19 @@ class ConsumedStmtVisitor : public ConstStmtVisitor { MapType PropagationMap; InfoEntry findInfo(const Expr *E) { - if (auto Cleanups = dyn_cast(E)) + if (const auto Cleanups = dyn_cast(E)) if (!Cleanups->cleanupsHaveSideEffects()) E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } + ConstInfoEntry findInfo(const Expr *E) const { - if (auto Cleanups = dyn_cast(E)) + if (const auto Cleanups = dyn_cast(E)) if (!Cleanups->cleanupsHaveSideEffects()) E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } + void insertInfo(const Expr *E, const PropagationInfo &PI) { PropagationMap.insert(PairType(E->IgnoreParens(), PI)); } @@ -517,7 +525,7 @@ public: if (Entry != PropagationMap.end()) return Entry->second; else - return PropagationInfo(); + return {}; } void reset(ConsumedStateMap *NewStateMap) { @@ -525,6 +533,8 @@ public: } }; +} // namespace consumed +} // namespace clang void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) { InfoEntry Entry = findInfo(From); @@ -532,7 +542,6 @@ void ConsumedStmtVisitor::forwardInfo(const Expr *From, const Expr *To) { insertInfo(To, Entry->second); } - // Create a new state for To, which is initialized to the state of From. // If NS is not CS_None, sets the state of From to NS. void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To, @@ -548,7 +557,6 @@ void ConsumedStmtVisitor::copyInfo(const Expr *From, const Expr *To, } } - // Get the ConsumedState for From ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) { InfoEntry Entry = findInfo(From); @@ -559,7 +567,6 @@ ConsumedState ConsumedStmtVisitor::getInfo(const Expr *From) { return CS_None; } - // If we already have info for To then update it, otherwise create a new entry. void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) { InfoEntry Entry = findInfo(To); @@ -572,8 +579,6 @@ void ConsumedStmtVisitor::setInfo(const Expr *To, ConsumedState NS) { } } - - void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo, const FunctionDecl *FunDecl, SourceLocation BlameLoc) { @@ -592,7 +597,6 @@ void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo, Analyzer.WarningsHandler.warnUseInInvalidState( FunDecl->getNameAsString(), PInfo.getVar()->getNameAsString(), stateToString(VarState), BlameLoc); - } else { ConsumedState TmpState = PInfo.getAsState(StateMap); @@ -604,7 +608,6 @@ void ConsumedStmtVisitor::checkCallability(const PropagationInfo &PInfo, } } - // Factors out common behavior for function, method, and operator calls. // Check parameters and set parameter state if necessary. // Returns true if the state of ObjArg is set, or false otherwise. @@ -681,7 +684,6 @@ bool ConsumedStmtVisitor::handleCall(const CallExpr *Call, const Expr *ObjArg, return false; } - void ConsumedStmtVisitor::propagateReturnType(const Expr *Call, const FunctionDecl *Fun) { QualType RetType = Fun->getCallResultType(); @@ -699,7 +701,6 @@ void ConsumedStmtVisitor::propagateReturnType(const Expr *Call, } } - void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) { switch (BinOp->getOpcode()) { case BO_LAnd: @@ -711,7 +712,6 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) { if (LEntry != PropagationMap.end() && LEntry->second.isVarTest()) { LTest = LEntry->second.getVarTest(); - } else { LTest.Var = nullptr; LTest.TestsFor = CS_None; @@ -719,7 +719,6 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) { if (REntry != PropagationMap.end() && REntry->second.isVarTest()) { RTest = REntry->second.getVarTest(); - } else { RTest.Var = nullptr; RTest.TestsFor = CS_None; @@ -728,7 +727,6 @@ void ConsumedStmtVisitor::VisitBinaryOperator(const BinaryOperator *BinOp) { if (!(LTest.Var == nullptr && RTest.Var == nullptr)) PropagationMap.insert(PairType(BinOp, PropagationInfo(BinOp, static_cast(BinOp->getOpcode() == BO_LOr), LTest, RTest))); - break; } @@ -805,7 +803,6 @@ void ConsumedStmtVisitor::VisitCXXConstructExpr(const CXXConstructExpr *Call) { } } - void ConsumedStmtVisitor::VisitCXXMemberCallExpr( const CXXMemberCallExpr *Call) { CXXMethodDecl* MD = Call->getMethodDecl(); @@ -816,12 +813,9 @@ void ConsumedStmtVisitor::VisitCXXMemberCallExpr( propagateReturnType(Call, MD); } - void ConsumedStmtVisitor::VisitCXXOperatorCallExpr( const CXXOperatorCallExpr *Call) { - - const FunctionDecl *FunDecl = - dyn_cast_or_null(Call->getDirectCallee()); + const auto *FunDecl = dyn_cast_or_null(Call->getDirectCallee()); if (!FunDecl) return; if (Call->getOperator() == OO_Equal) { @@ -831,7 +825,7 @@ void ConsumedStmtVisitor::VisitCXXOperatorCallExpr( return; } - if (const CXXMemberCallExpr *MCall = dyn_cast(Call)) + if (const auto *MCall = dyn_cast(Call)) handleCall(MCall, MCall->getImplicitObjectArgument(), FunDecl); else handleCall(Call, Call->getArg(0), FunDecl); @@ -840,7 +834,7 @@ void ConsumedStmtVisitor::VisitCXXOperatorCallExpr( } void ConsumedStmtVisitor::VisitDeclRefExpr(const DeclRefExpr *DeclRef) { - if (const VarDecl *Var = dyn_cast_or_null(DeclRef->getDecl())) + if (const auto *Var = dyn_cast_or_null(DeclRef->getDecl())) if (StateMap->getState(Var) != consumed::CS_None) PropagationMap.insert(PairType(DeclRef, PropagationInfo(Var))); } @@ -851,13 +845,12 @@ void ConsumedStmtVisitor::VisitDeclStmt(const DeclStmt *DeclS) { VisitVarDecl(cast(DI)); if (DeclS->isSingleDecl()) - if (const VarDecl *Var = dyn_cast_or_null(DeclS->getSingleDecl())) + if (const auto *Var = dyn_cast_or_null(DeclS->getSingleDecl())) PropagationMap.insert(PairType(DeclS, PropagationInfo(Var))); } void ConsumedStmtVisitor::VisitMaterializeTemporaryExpr( const MaterializeTemporaryExpr *Temp) { - forwardInfo(Temp->GetTemporaryExpr(), Temp); } @@ -865,7 +858,6 @@ void ConsumedStmtVisitor::VisitMemberExpr(const MemberExpr *MExpr) { forwardInfo(MExpr->getBase(), MExpr); } - void ConsumedStmtVisitor::VisitParmVarDecl(const ParmVarDecl *Param) { QualType ParamType = Param->getType(); ConsumedState ParamState = consumed::CS_None; @@ -943,10 +935,6 @@ void ConsumedStmtVisitor::VisitVarDecl(const VarDecl *Var) { StateMap->setState(Var, consumed::CS_Unknown); } } -}} // end clang::consumed::ConsumedStmtVisitor - -namespace clang { -namespace consumed { static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test, ConsumedStateMap *ThenStates, @@ -956,10 +944,8 @@ static void splitVarStateForIf(const IfStmt *IfNode, const VarTestResult &Test, if (VarState == CS_Unknown) { ThenStates->setState(Test.Var, Test.TestsFor); ElseStates->setState(Test.Var, invertConsumedUnconsumed(Test.TestsFor)); - } else if (VarState == invertConsumedUnconsumed(Test.TestsFor)) { ThenStates->markUnreachable(); - } else if (VarState == Test.TestsFor) { ElseStates->markUnreachable(); } @@ -978,28 +964,22 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo, if (PInfo.testEffectiveOp() == EO_And) { if (LState == CS_Unknown) { ThenStates->setState(LTest.Var, LTest.TestsFor); - } else if (LState == invertConsumedUnconsumed(LTest.TestsFor)) { ThenStates->markUnreachable(); - } else if (LState == LTest.TestsFor && isKnownState(RState)) { if (RState == RTest.TestsFor) ElseStates->markUnreachable(); else ThenStates->markUnreachable(); } - } else { if (LState == CS_Unknown) { ElseStates->setState(LTest.Var, invertConsumedUnconsumed(LTest.TestsFor)); - } else if (LState == LTest.TestsFor) { ElseStates->markUnreachable(); - } else if (LState == invertConsumedUnconsumed(LTest.TestsFor) && isKnownState(RState)) { - if (RState == RTest.TestsFor) ElseStates->markUnreachable(); else @@ -1014,7 +994,6 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo, ThenStates->setState(RTest.Var, RTest.TestsFor); else if (RState == invertConsumedUnconsumed(RTest.TestsFor)) ThenStates->markUnreachable(); - } else { if (RState == CS_Unknown) ElseStates->setState(RTest.Var, @@ -1027,7 +1006,6 @@ static void splitVarStateForIfBinOp(const PropagationInfo &PInfo, bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock, const CFGBlock *TargetBlock) { - assert(CurrBlock && "Block pointer must not be NULL"); assert(TargetBlock && "TargetBlock pointer must not be NULL"); @@ -1043,7 +1021,6 @@ bool ConsumedBlockInfo::allBackEdgesVisited(const CFGBlock *CurrBlock, void ConsumedBlockInfo::addInfo( const CFGBlock *Block, ConsumedStateMap *StateMap, std::unique_ptr &OwnedStateMap) { - assert(Block && "Block pointer must not be NULL"); auto &Entry = StateMapsArray[Block->getBlockID()]; @@ -1058,7 +1035,6 @@ void ConsumedBlockInfo::addInfo( void ConsumedBlockInfo::addInfo(const CFGBlock *Block, std::unique_ptr StateMap) { - assert(Block && "Block pointer must not be NULL"); auto &Entry = StateMapsArray[Block->getBlockID()]; @@ -1119,7 +1095,7 @@ void ConsumedStateMap::checkParamsForReturnTypestate(SourceLocation BlameLoc, for (const auto &DM : VarMap) { if (isa(DM.first)) { - const ParmVarDecl *Param = cast(DM.first); + const auto *Param = cast(DM.first); const ReturnTypestateAttr *RTA = Param->getAttr(); if (!RTA) @@ -1226,7 +1202,7 @@ bool ConsumedStateMap::operator!=(const ConsumedStateMap *Other) const { void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC, const FunctionDecl *D) { QualType ReturnType; - if (const CXXConstructorDecl *Constructor = dyn_cast(D)) { + if (const auto *Constructor = dyn_cast(D)) { ASTContext &CurrContext = AC.getASTContext(); ReturnType = Constructor->getThisType(CurrContext)->getPointeeType(); } else @@ -1256,14 +1232,12 @@ void ConsumedAnalyzer::determineExpectedReturnState(AnalysisDeclContext &AC, bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock, const ConsumedStmtVisitor &Visitor) { - std::unique_ptr FalseStates( new ConsumedStateMap(*CurrStates)); PropagationInfo PInfo; - if (const IfStmt *IfNode = - dyn_cast_or_null(CurrBlock->getTerminator().getStmt())) { - + if (const auto *IfNode = + dyn_cast_or_null(CurrBlock->getTerminator().getStmt())) { const Expr *Cond = IfNode->getCond(); PInfo = Visitor.getInfo(Cond); @@ -1275,19 +1249,15 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock, FalseStates->setSource(Cond); splitVarStateForIf(IfNode, PInfo.getVarTest(), CurrStates.get(), FalseStates.get()); - } else if (PInfo.isBinTest()) { CurrStates->setSource(PInfo.testSourceNode()); FalseStates->setSource(PInfo.testSourceNode()); splitVarStateForIfBinOp(PInfo, CurrStates.get(), FalseStates.get()); - } else { return false; } - - } else if (const BinaryOperator *BinOp = - dyn_cast_or_null(CurrBlock->getTerminator().getStmt())) { - + } else if (const auto *BinOp = + dyn_cast_or_null(CurrBlock->getTerminator().getStmt())) { PInfo = Visitor.getInfo(BinOp->getLHS()); if (!PInfo.isVarTest()) { if ((BinOp = dyn_cast_or_null(BinOp->getLHS()))) { @@ -1295,7 +1265,6 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock, if (!PInfo.isVarTest()) return false; - } else { return false; } @@ -1320,7 +1289,6 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock, else if (VarState == Test.TestsFor) FalseStates->markUnreachable(); } - } else { return false; } @@ -1339,7 +1307,7 @@ bool ConsumedAnalyzer::splitState(const CFGBlock *CurrBlock, } void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { - const FunctionDecl *D = dyn_cast_or_null(AC.getDecl()); + const auto *D = dyn_cast_or_null(AC.getDecl()); if (!D) return; @@ -1368,7 +1336,6 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { if (!CurrStates) { continue; - } else if (!CurrStates->isReachable()) { CurrStates = nullptr; continue; @@ -1423,7 +1390,6 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { for (CFGBlock::const_succ_iterator SI = CurrBlock->succ_begin(), SE = CurrBlock->succ_end(); SI != SE; ++SI) { - if (*SI == nullptr) continue; if (BlockInfo.isBackEdge(CurrBlock, *SI)) { @@ -1452,4 +1418,3 @@ void ConsumedAnalyzer::run(AnalysisDeclContext &AC) { WarningsHandler.emitDiagnostics(); } -}} // end namespace clang::consumed diff --git a/lib/Analysis/Dominators.cpp b/lib/Analysis/Dominators.cpp index 0e02c6d717..1b7dd8c804 100644 --- a/lib/Analysis/Dominators.cpp +++ b/lib/Analysis/Dominators.cpp @@ -1,4 +1,4 @@ -//=- Dominators.cpp - Implementation of dominators tree for Clang CFG C++ -*-=// +//===- Dominators.cpp - Implementation of dominators tree for Clang CFG ---===// // // The LLVM Compiler Infrastructure // @@ -11,4 +11,4 @@ using namespace clang; -void DominatorTree::anchor() { } +void DominatorTree::anchor() {} diff --git a/lib/Analysis/PostOrderCFGView.cpp b/lib/Analysis/PostOrderCFGView.cpp index 5a3c8182a1..124424bf25 100644 --- a/lib/Analysis/PostOrderCFGView.cpp +++ b/lib/Analysis/PostOrderCFGView.cpp @@ -1,4 +1,4 @@ -//===- PostOrderCFGView.cpp - Post order view of CFG blocks -------*- C++ --*-// +//===- PostOrderCFGView.cpp - Post order view of CFG blocks ---------------===// // // The LLVM Compiler Infrastructure // @@ -12,10 +12,12 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/PostOrderCFGView.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" using namespace clang; -void PostOrderCFGView::anchor() { } +void PostOrderCFGView::anchor() {} PostOrderCFGView::PostOrderCFGView(const CFG *cfg) { Blocks.reserve(cfg->getNumBlockIDs()); @@ -46,4 +48,3 @@ bool PostOrderCFGView::BlockOrderCompare::operator()(const CFGBlock *b1, unsigned b2V = (b2It == POV.BlockOrder.end()) ? 0 : b2It->second; return b1V > b2V; } - diff --git a/lib/Analysis/ThreadSafetyCommon.cpp b/lib/Analysis/ThreadSafetyCommon.cpp index 99284f07b4..1376a89d15 100644 --- a/lib/Analysis/ThreadSafetyCommon.cpp +++ b/lib/Analysis/ThreadSafetyCommon.cpp @@ -1,4 +1,4 @@ -//===- ThreadSafetyCommon.cpp -----------------------------------*- C++ -*-===// +//===- ThreadSafetyCommon.cpp ---------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,24 +13,32 @@ #include "clang/Analysis/Analyses/ThreadSafetyCommon.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclGroup.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtCXX.h" +#include "clang/AST/OperationKinds.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" -#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" -#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/OperatorKinds.h" -#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include +#include +#include +#include using namespace clang; using namespace threadSafety; // From ThreadSafetyUtil.h -std::string threadSafety::getSourceLiteralString(const clang::Expr *CE) { +std::string threadSafety::getSourceLiteralString(const Expr *CE) { switch (CE->getStmtClass()) { case Stmt::IntegerLiteralClass: return cast(CE)->getValue().toString(10, true); @@ -59,7 +67,7 @@ static bool isIncompletePhi(const til::SExpr *E) { return false; } -typedef SExprBuilder::CallingContext CallingContext; +using CallingContext = SExprBuilder::CallingContext; til::SExpr *SExprBuilder::lookupStmt(const Stmt *S) { auto It = SMap.find(S); @@ -74,7 +82,7 @@ til::SCFG *SExprBuilder::buildCFG(CFGWalker &Walker) { } static bool isCalleeArrow(const Expr *E) { - const MemberExpr *ME = dyn_cast(E->IgnoreParenCasts()); + const auto *ME = dyn_cast(E->IgnoreParenCasts()); return ME ? ME->isArrow() : false; } @@ -97,20 +105,18 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, // Examine DeclExp to find SelfArg and FunArgs, which are used to substitute // for formal parameters when we call buildMutexID later. - if (const MemberExpr *ME = dyn_cast(DeclExp)) { + if (const auto *ME = dyn_cast(DeclExp)) { Ctx.SelfArg = ME->getBase(); Ctx.SelfArrow = ME->isArrow(); - } else if (const CXXMemberCallExpr *CE = - dyn_cast(DeclExp)) { + } else if (const auto *CE = dyn_cast(DeclExp)) { Ctx.SelfArg = CE->getImplicitObjectArgument(); Ctx.SelfArrow = isCalleeArrow(CE->getCallee()); Ctx.NumArgs = CE->getNumArgs(); Ctx.FunArgs = CE->getArgs(); - } else if (const CallExpr *CE = dyn_cast(DeclExp)) { + } else if (const auto *CE = dyn_cast(DeclExp)) { Ctx.NumArgs = CE->getNumArgs(); Ctx.FunArgs = CE->getArgs(); - } else if (const CXXConstructExpr *CE = - dyn_cast(DeclExp)) { + } else if (const auto *CE = dyn_cast(DeclExp)) { Ctx.SelfArg = nullptr; // Will be set below Ctx.NumArgs = CE->getNumArgs(); Ctx.FunArgs = CE->getArgs(); @@ -147,7 +153,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, if (!AttrExp) return CapabilityExpr(nullptr, false); - if (auto* SLit = dyn_cast(AttrExp)) { + if (const auto* SLit = dyn_cast(AttrExp)) { if (SLit->getString() == StringRef("*")) // The "*" expr is a universal lock, which essentially turns off // checks until it is removed from the lockset. @@ -158,13 +164,13 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, } bool Neg = false; - if (auto *OE = dyn_cast(AttrExp)) { + if (const auto *OE = dyn_cast(AttrExp)) { if (OE->getOperator() == OO_Exclaim) { Neg = true; AttrExp = OE->getArg(0); } } - else if (auto *UO = dyn_cast(AttrExp)) { + else if (const auto *UO = dyn_cast(AttrExp)) { if (UO->getOpcode() == UO_LNot) { Neg = true; AttrExp = UO->getSubExpr(); @@ -179,7 +185,7 @@ CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp, return CapabilityExpr(nullptr, false); // Hack to deal with smart pointers -- strip off top-level pointer casts. - if (auto *CE = dyn_cast_or_null(E)) { + if (const auto *CE = dyn_cast_or_null(E)) { if (CE->castOpcode() == til::CAST_objToPtr) return CapabilityExpr(CE->expr(), Neg); } @@ -254,7 +260,7 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { default: break; } - if (const CastExpr *CE = dyn_cast(S)) + if (const auto *CE = dyn_cast(S)) return translateCastExpr(CE, Ctx); return new (Arena) til::Undefined(S); @@ -262,11 +268,11 @@ til::SExpr *SExprBuilder::translate(const Stmt *S, CallingContext *Ctx) { til::SExpr *SExprBuilder::translateDeclRefExpr(const DeclRefExpr *DRE, CallingContext *Ctx) { - const ValueDecl *VD = cast(DRE->getDecl()->getCanonicalDecl()); + const auto *VD = cast(DRE->getDecl()->getCanonicalDecl()); // Function parameters require substitution and/or renaming. - if (const ParmVarDecl *PV = dyn_cast_or_null(VD)) { - const FunctionDecl *FD = + if (const auto *PV = dyn_cast_or_null(VD)) { + const auto *FD = cast(PV->getDeclContext())->getCanonicalDecl(); unsigned I = PV->getFunctionScopeIndex(); @@ -294,13 +300,13 @@ til::SExpr *SExprBuilder::translateCXXThisExpr(const CXXThisExpr *TE, } static const ValueDecl *getValueDeclFromSExpr(const til::SExpr *E) { - if (auto *V = dyn_cast(E)) + if (const auto *V = dyn_cast(E)) return V->clangDecl(); - if (auto *Ph = dyn_cast(E)) + if (const auto *Ph = dyn_cast(E)) return Ph->clangDecl(); - if (auto *P = dyn_cast(E)) + if (const auto *P = dyn_cast(E)) return P->clangDecl(); - if (auto *L = dyn_cast(E)) + if (const auto *L = dyn_cast(E)) return L->clangDecl(); return nullptr; } @@ -309,7 +315,7 @@ static bool hasCppPointerType(const til::SExpr *E) { auto *VD = getValueDeclFromSExpr(E); if (VD && VD->getType()->isPointerType()) return true; - if (auto *C = dyn_cast(E)) + if (const auto *C = dyn_cast(E)) return C->castOpcode() == til::CAST_objToPtr; return false; @@ -333,9 +339,8 @@ til::SExpr *SExprBuilder::translateMemberExpr(const MemberExpr *ME, til::SExpr *BE = translate(ME->getBase(), Ctx); til::SExpr *E = new (Arena) til::SApply(BE); - const ValueDecl *D = - cast(ME->getMemberDecl()->getCanonicalDecl()); - if (auto *VD = dyn_cast(D)) + const auto *D = cast(ME->getMemberDecl()->getCanonicalDecl()); + if (const auto *VD = dyn_cast(D)) D = getFirstVirtualDecl(VD); til::Project *P = new (Arena) til::Project(E, D); @@ -356,7 +361,7 @@ til::SExpr *SExprBuilder::translateCallExpr(const CallExpr *CE, LRCallCtx.SelfArg = SelfE; LRCallCtx.NumArgs = CE->getNumArgs(); LRCallCtx.FunArgs = CE->getArgs(); - return const_cast( + return const_cast( translateAttrExpr(At->getArg(), &LRCallCtx).sexpr()); } } @@ -407,10 +412,10 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO, case UO_PreDec: return new (Arena) til::Undefined(UO); - case UO_AddrOf: { + case UO_AddrOf: if (CapabilityExprMode) { // interpret &Graph::mu_ as an existential. - if (DeclRefExpr* DRE = dyn_cast(UO->getSubExpr())) { + if (const auto *DRE = dyn_cast(UO->getSubExpr())) { if (DRE->getDecl()->isCXXInstanceMember()) { // This is a pointer-to-member expression, e.g. &MyClass::mu_. // We interpret this syntax specially, as a wildcard. @@ -421,7 +426,6 @@ til::SExpr *SExprBuilder::translateUnaryOperator(const UnaryOperator *UO, } // otherwise, & is a no-op return translate(UO->getSubExpr(), Ctx); - } // We treat these as no-ops case UO_Deref: @@ -470,7 +474,7 @@ til::SExpr *SExprBuilder::translateBinAssign(til::TIL_BinaryOpcode Op, const ValueDecl *VD = nullptr; til::SExpr *CV = nullptr; - if (const DeclRefExpr *DRE = dyn_cast(LHS)) { + if (const auto *DRE = dyn_cast(LHS)) { VD = DRE->getDecl(); CV = lookupVarDecl(VD); } @@ -533,10 +537,10 @@ til::SExpr *SExprBuilder::translateBinaryOperator(const BinaryOperator *BO, til::SExpr *SExprBuilder::translateCastExpr(const CastExpr *CE, CallingContext *Ctx) { - clang::CastKind K = CE->getCastKind(); + CastKind K = CE->getCastKind(); switch (K) { case CK_LValueToRValue: { - if (const DeclRefExpr *DRE = dyn_cast(CE->getSubExpr())) { + if (const auto *DRE = dyn_cast(CE->getSubExpr())) { til::SExpr *E0 = lookupVarDecl(DRE->getDecl()); if (E0) return E0; @@ -584,16 +588,15 @@ SExprBuilder::translateAbstractConditionalOperator( til::SExpr * SExprBuilder::translateDeclStmt(const DeclStmt *S, CallingContext *Ctx) { DeclGroupRef DGrp = S->getDeclGroup(); - for (DeclGroupRef::iterator I = DGrp.begin(), E = DGrp.end(); I != E; ++I) { - if (VarDecl *VD = dyn_cast_or_null(*I)) { + for (auto I : DGrp) { + if (auto *VD = dyn_cast_or_null(I)) { Expr *E = VD->getInit(); til::SExpr* SE = translate(E, Ctx); // Add local variables with trivial type to the variable map QualType T = VD->getType(); - if (T.isTrivialType(VD->getASTContext())) { + if (T.isTrivialType(VD->getASTContext())) return addVarDecl(VD, SE); - } else { // TODO: add alloca } @@ -632,7 +635,7 @@ til::SExpr *SExprBuilder::lookupVarDecl(const ValueDecl *VD) { static void maybeUpdateVD(til::SExpr *E, const ValueDecl *VD) { if (!E) return; - if (til::Variable *V = dyn_cast(E)) { + if (auto *V = dyn_cast(E)) { if (!V->clangDecl()) V->setClangDecl(VD); } @@ -672,7 +675,7 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) { if (CurrE->block() == CurrentBB) { // We already have a Phi node in the current block, // so just add the new variable to the Phi node. - til::Phi *Ph = dyn_cast(CurrE); + auto *Ph = dyn_cast(CurrE); assert(Ph && "Expecting Phi node."); if (E) Ph->values()[ArgIndex] = E; @@ -690,9 +693,8 @@ void SExprBuilder::makePhiNodeVar(unsigned i, unsigned NPreds, til::SExpr *E) { Ph->setClangDecl(CurrentLVarMap[i].first); // If E is from a back-edge, or either E or CurrE are incomplete, then // mark this node as incomplete; we may need to remove it later. - if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) { + if (!E || isIncompletePhi(E) || isIncompletePhi(CurrE)) Ph->setStatus(til::Phi::PH_Incomplete); - } // Add Phi node to current block, and update CurrentLVarMap[i] CurrentArguments.push_back(Ph); @@ -721,7 +723,7 @@ void SExprBuilder::mergeEntryMap(LVarDefinitionMap Map) { unsigned MSz = Map.size(); unsigned Sz = std::min(ESz, MSz); - for (unsigned i=0; inumPredecessors(); - for (unsigned i=0; i < Sz; ++i) { + for (unsigned i = 0; i < Sz; ++i) makePhiNodeVar(i, NPreds, nullptr); - } } // Update the phi nodes that were initially created for a back edge @@ -772,7 +773,7 @@ void SExprBuilder::mergePhiNodesBackEdge(const CFGBlock *Blk) { assert(ArgIndex > 0 && ArgIndex < BB->numPredecessors()); for (til::SExpr *PE : BB->arguments()) { - til::Phi *Ph = dyn_cast_or_null(PE); + auto *Ph = dyn_cast_or_null(PE); assert(Ph && "Expecting Phi Node."); assert(Ph->values()[ArgIndex] == nullptr && "Wrong index for back edge."); -- 2.40.0