| //===--- LoopConvertUtils.h - clang-tidy ------------------------*- C++ -*-===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H | 
 | #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H | 
 |  | 
 | #include "clang/AST/ASTContext.h" | 
 | #include "clang/AST/RecursiveASTVisitor.h" | 
 | #include "clang/ASTMatchers/ASTMatchFinder.h" | 
 | #include "clang/Basic/SourceLocation.h" | 
 | #include "llvm/ADT/DenseMap.h" | 
 | #include "llvm/ADT/SmallSet.h" | 
 | #include "llvm/ADT/SmallVector.h" | 
 | #include "llvm/ADT/StringRef.h" | 
 | #include <algorithm> | 
 | #include <memory> | 
 | #include <string> | 
 | #include <utility> | 
 |  | 
 | namespace clang { | 
 | namespace tidy { | 
 | namespace modernize { | 
 |  | 
 | enum LoopFixerKind { LFK_Array, LFK_Iterator, LFK_PseudoArray }; | 
 |  | 
 | /// A map used to walk the AST in reverse: maps child Stmt to parent Stmt. | 
 | typedef llvm::DenseMap<const clang::Stmt *, const clang::Stmt *> StmtParentMap; | 
 |  | 
 | /// A map used to walk the AST in reverse: | 
 | ///  maps VarDecl to the to parent DeclStmt. | 
 | typedef llvm::DenseMap<const clang::VarDecl *, const clang::DeclStmt *> | 
 |     DeclParentMap; | 
 |  | 
 | /// A map used to track which variables have been removed by a refactoring pass. | 
 | /// It maps the parent ForStmt to the removed index variable's VarDecl. | 
 | typedef llvm::DenseMap<const clang::ForStmt *, const clang::VarDecl *> | 
 |     ReplacedVarsMap; | 
 |  | 
 | /// A map used to remember the variable names generated in a Stmt | 
 | typedef llvm::DenseMap<const clang::Stmt *, std::string> | 
 |     StmtGeneratedVarNameMap; | 
 |  | 
 | /// A vector used to store the AST subtrees of an Expr. | 
 | typedef llvm::SmallVector<const clang::Expr *, 16> ComponentVector; | 
 |  | 
 | /// \brief Class used build the reverse AST properties needed to detect | 
 | /// name conflicts and free variables. | 
 | class StmtAncestorASTVisitor | 
 |     : public clang::RecursiveASTVisitor<StmtAncestorASTVisitor> { | 
 | public: | 
 |   StmtAncestorASTVisitor() { StmtStack.push_back(nullptr); } | 
 |  | 
 |   /// \brief Run the analysis on the TranslationUnitDecl. | 
 |   /// | 
 |   /// In case we're running this analysis multiple times, don't repeat the work. | 
 |   void gatherAncestors(const clang::TranslationUnitDecl *T) { | 
 |     if (StmtAncestors.empty()) | 
 |       TraverseDecl(const_cast<clang::TranslationUnitDecl *>(T)); | 
 |   } | 
 |  | 
 |   /// Accessor for StmtAncestors. | 
 |   const StmtParentMap &getStmtToParentStmtMap() { return StmtAncestors; } | 
 |  | 
 |   /// Accessor for DeclParents. | 
 |   const DeclParentMap &getDeclToParentStmtMap() { return DeclParents; } | 
 |  | 
 |   friend class clang::RecursiveASTVisitor<StmtAncestorASTVisitor>; | 
 |  | 
 | private: | 
 |   StmtParentMap StmtAncestors; | 
 |   DeclParentMap DeclParents; | 
 |   llvm::SmallVector<const clang::Stmt *, 16> StmtStack; | 
 |  | 
 |   bool TraverseStmt(clang::Stmt *Statement); | 
 |   bool VisitDeclStmt(clang::DeclStmt *Statement); | 
 | }; | 
 |  | 
 | /// Class used to find the variables and member expressions on which an | 
 | /// arbitrary expression depends. | 
 | class ComponentFinderASTVisitor | 
 |     : public clang::RecursiveASTVisitor<ComponentFinderASTVisitor> { | 
 | public: | 
 |   ComponentFinderASTVisitor() = default; | 
 |  | 
 |   /// Find the components of an expression and place them in a ComponentVector. | 
 |   void findExprComponents(const clang::Expr *SourceExpr) { | 
 |     TraverseStmt(const_cast<clang::Expr *>(SourceExpr)); | 
 |   } | 
 |  | 
 |   /// Accessor for Components. | 
 |   const ComponentVector &getComponents() { return Components; } | 
 |  | 
 |   friend class clang::RecursiveASTVisitor<ComponentFinderASTVisitor>; | 
 |  | 
 | private: | 
 |   ComponentVector Components; | 
 |  | 
 |   bool VisitDeclRefExpr(clang::DeclRefExpr *E); | 
 |   bool VisitMemberExpr(clang::MemberExpr *Member); | 
 | }; | 
 |  | 
 | /// Class used to determine if an expression is dependent on a variable declared | 
 | /// inside of the loop where it would be used. | 
 | class DependencyFinderASTVisitor | 
 |     : public clang::RecursiveASTVisitor<DependencyFinderASTVisitor> { | 
 | public: | 
 |   DependencyFinderASTVisitor(const StmtParentMap *StmtParents, | 
 |                              const DeclParentMap *DeclParents, | 
 |                              const ReplacedVarsMap *ReplacedVars, | 
 |                              const clang::Stmt *ContainingStmt) | 
 |       : StmtParents(StmtParents), DeclParents(DeclParents), | 
 |         ContainingStmt(ContainingStmt), ReplacedVars(ReplacedVars) {} | 
 |  | 
 |   /// \brief Run the analysis on Body, and return true iff the expression | 
 |   /// depends on some variable declared within ContainingStmt. | 
 |   /// | 
 |   /// This is intended to protect against hoisting the container expression | 
 |   /// outside of an inner context if part of that expression is declared in that | 
 |   /// inner context. | 
 |   /// | 
 |   /// For example, | 
 |   /// \code | 
 |   ///   const int N = 10, M = 20; | 
 |   ///   int arr[N][M]; | 
 |   ///   int getRow(); | 
 |   /// | 
 |   ///   for (int i = 0; i < M; ++i) { | 
 |   ///     int k = getRow(); | 
 |   ///     printf("%d:", arr[k][i]); | 
 |   ///   } | 
 |   /// \endcode | 
 |   /// At first glance, this loop looks like it could be changed to | 
 |   /// \code | 
 |   ///   for (int elem : arr[k]) { | 
 |   ///     int k = getIndex(); | 
 |   ///     printf("%d:", elem); | 
 |   ///   } | 
 |   /// \endcode | 
 |   /// But this is malformed, since `k` is used before it is defined! | 
 |   /// | 
 |   /// In order to avoid this, this class looks at the container expression | 
 |   /// `arr[k]` and decides whether or not it contains a sub-expression declared | 
 |   /// within the the loop body. | 
 |   bool dependsOnInsideVariable(const clang::Stmt *Body) { | 
 |     DependsOnInsideVariable = false; | 
 |     TraverseStmt(const_cast<clang::Stmt *>(Body)); | 
 |     return DependsOnInsideVariable; | 
 |   } | 
 |  | 
 |   friend class clang::RecursiveASTVisitor<DependencyFinderASTVisitor>; | 
 |  | 
 | private: | 
 |   const StmtParentMap *StmtParents; | 
 |   const DeclParentMap *DeclParents; | 
 |   const clang::Stmt *ContainingStmt; | 
 |   const ReplacedVarsMap *ReplacedVars; | 
 |   bool DependsOnInsideVariable; | 
 |  | 
 |   bool VisitVarDecl(clang::VarDecl *V); | 
 |   bool VisitDeclRefExpr(clang::DeclRefExpr *D); | 
 | }; | 
 |  | 
 | /// Class used to determine if any declarations used in a Stmt would conflict | 
 | /// with a particular identifier. This search includes the names that don't | 
 | /// actually appear in the AST (i.e. created by a refactoring tool) by including | 
 | /// a map from Stmts to generated names associated with those stmts. | 
 | class DeclFinderASTVisitor | 
 |     : public clang::RecursiveASTVisitor<DeclFinderASTVisitor> { | 
 | public: | 
 |   DeclFinderASTVisitor(const std::string &Name, | 
 |                        const StmtGeneratedVarNameMap *GeneratedDecls) | 
 |       : Name(Name), GeneratedDecls(GeneratedDecls), Found(false) {} | 
 |  | 
 |   /// Attempts to find any usages of variables name Name in Body, returning | 
 |   /// true when it is used in Body. This includes the generated loop variables | 
 |   /// of ForStmts which have already been transformed. | 
 |   bool findUsages(const clang::Stmt *Body) { | 
 |     Found = false; | 
 |     TraverseStmt(const_cast<clang::Stmt *>(Body)); | 
 |     return Found; | 
 |   } | 
 |  | 
 |   friend class clang::RecursiveASTVisitor<DeclFinderASTVisitor>; | 
 |  | 
 | private: | 
 |   std::string Name; | 
 |   /// GeneratedDecls keeps track of ForStmts which have been transformed, | 
 |   /// mapping each modified ForStmt to the variable generated in the loop. | 
 |   const StmtGeneratedVarNameMap *GeneratedDecls; | 
 |   bool Found; | 
 |  | 
 |   bool VisitForStmt(clang::ForStmt *F); | 
 |   bool VisitNamedDecl(clang::NamedDecl *D); | 
 |   bool VisitDeclRefExpr(clang::DeclRefExpr *D); | 
 |   bool VisitTypeLoc(clang::TypeLoc TL); | 
 | }; | 
 |  | 
 | /// \brief The information needed to describe a valid convertible usage | 
 | /// of an array index or iterator. | 
 | struct Usage { | 
 |   enum UsageKind { | 
 |     // Regular usages of the loop index (the ones not specified below). Some | 
 |     // examples: | 
 |     // \code | 
 |     //   int X = 8 * Arr[i]; | 
 |     //               ^~~~~~ | 
 |     //   f(param1, param2, *It); | 
 |     //                     ^~~ | 
 |     //   if (Vec[i].SomeBool) {} | 
 |     //       ^~~~~~ | 
 |     // \endcode | 
 |     UK_Default, | 
 |     // Indicates whether this is an access to a member through the arrow | 
 |     // operator on pointers or iterators. | 
 |     UK_MemberThroughArrow, | 
 |     // If the variable is being captured by a lambda, indicates whether the | 
 |     // capture was done by value or by reference. | 
 |     UK_CaptureByCopy, | 
 |     UK_CaptureByRef | 
 |   }; | 
 |   // The expression that is going to be converted. Null in case of lambda | 
 |   // captures. | 
 |   const Expr *Expression; | 
 |  | 
 |   UsageKind Kind; | 
 |  | 
 |   // Range that covers this usage. | 
 |   SourceRange Range; | 
 |  | 
 |   explicit Usage(const Expr *E) | 
 |       : Expression(E), Kind(UK_Default), Range(Expression->getSourceRange()) {} | 
 |   Usage(const Expr *E, UsageKind Kind, SourceRange Range) | 
 |       : Expression(E), Kind(Kind), Range(std::move(Range)) {} | 
 | }; | 
 |  | 
 | /// \brief A class to encapsulate lowering of the tool's confidence level. | 
 | class Confidence { | 
 | public: | 
 |   enum Level { | 
 |     // Transformations that are likely to change semantics. | 
 |     CL_Risky, | 
 |  | 
 |     // Transformations that might change semantics. | 
 |     CL_Reasonable, | 
 |  | 
 |     // Transformations that will not change semantics. | 
 |     CL_Safe | 
 |   }; | 
 |   /// \brief Initialize confidence level. | 
 |   explicit Confidence(Confidence::Level Level) : CurrentLevel(Level) {} | 
 |  | 
 |   /// \brief Lower the internal confidence level to Level, but do not raise it. | 
 |   void lowerTo(Confidence::Level Level) { | 
 |     CurrentLevel = std::min(Level, CurrentLevel); | 
 |   } | 
 |  | 
 |   /// \brief Return the internal confidence level. | 
 |   Level getLevel() const { return CurrentLevel; } | 
 |  | 
 | private: | 
 |   Level CurrentLevel; | 
 | }; | 
 |  | 
 | // The main computational result of ForLoopIndexVisitor. | 
 | typedef llvm::SmallVector<Usage, 8> UsageResult; | 
 |  | 
 | // General functions used by ForLoopIndexUseVisitor and LoopConvertCheck. | 
 | const Expr *digThroughConstructors(const Expr *E); | 
 | bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second); | 
 | const DeclRefExpr *getDeclRef(const Expr *E); | 
 | bool areSameVariable(const ValueDecl *First, const ValueDecl *Second); | 
 |  | 
 | /// \brief Discover usages of expressions consisting of index or iterator | 
 | /// access. | 
 | /// | 
 | /// Given an index variable, recursively crawls a for loop to discover if the | 
 | /// index variable is used in a way consistent with range-based for loop access. | 
 | class ForLoopIndexUseVisitor | 
 |     : public RecursiveASTVisitor<ForLoopIndexUseVisitor> { | 
 | public: | 
 |   ForLoopIndexUseVisitor(ASTContext *Context, const VarDecl *IndexVar, | 
 |                          const VarDecl *EndVar, const Expr *ContainerExpr, | 
 |                          const Expr *ArrayBoundExpr, | 
 |                          bool ContainerNeedsDereference); | 
 |  | 
 |   /// \brief Finds all uses of IndexVar in Body, placing all usages in Usages, | 
 |   /// and returns true if IndexVar was only used in a way consistent with a | 
 |   /// range-based for loop. | 
 |   /// | 
 |   /// The general strategy is to reject any DeclRefExprs referencing IndexVar, | 
 |   /// with the exception of certain acceptable patterns. | 
 |   /// For arrays, the DeclRefExpr for IndexVar must appear as the index of an | 
 |   /// ArraySubscriptExpression. Iterator-based loops may dereference | 
 |   /// IndexVar or call methods through operator-> (builtin or overloaded). | 
 |   /// Array-like containers may use IndexVar as a parameter to the at() member | 
 |   /// function and in overloaded operator[]. | 
 |   bool findAndVerifyUsages(const Stmt *Body); | 
 |  | 
 |   /// \brief Add a set of components that we should consider relevant to the | 
 |   /// container. | 
 |   void addComponents(const ComponentVector &Components); | 
 |  | 
 |   /// \brief Accessor for Usages. | 
 |   const UsageResult &getUsages() const { return Usages; } | 
 |  | 
 |   /// \brief Adds the Usage if it was not added before. | 
 |   void addUsage(const Usage &U); | 
 |  | 
 |   /// \brief Get the container indexed by IndexVar, if any. | 
 |   const Expr *getContainerIndexed() const { return ContainerExpr; } | 
 |  | 
 |   /// \brief Returns the statement declaring the variable created as an alias | 
 |   /// for the loop element, if any. | 
 |   const DeclStmt *getAliasDecl() const { return AliasDecl; } | 
 |  | 
 |   /// \brief Accessor for ConfidenceLevel. | 
 |   Confidence::Level getConfidenceLevel() const { | 
 |     return ConfidenceLevel.getLevel(); | 
 |   } | 
 |  | 
 |   /// \brief Indicates if the alias declaration was in a place where it cannot | 
 |   /// simply be removed but rather replaced with a use of the alias variable. | 
 |   /// For example, variables declared in the condition of an if, switch, or for | 
 |   /// stmt. | 
 |   bool aliasUseRequired() const { return ReplaceWithAliasUse; } | 
 |  | 
 |   /// \brief Indicates if the alias declaration came from the init clause of a | 
 |   /// nested for loop. SourceRanges provided by Clang for DeclStmts in this | 
 |   /// case need to be adjusted. | 
 |   bool aliasFromForInit() const { return AliasFromForInit; } | 
 |  | 
 | private: | 
 |   /// Typedef used in CRTP functions. | 
 |   typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase; | 
 |   friend class RecursiveASTVisitor<ForLoopIndexUseVisitor>; | 
 |  | 
 |   /// Overriden methods for RecursiveASTVisitor's traversal. | 
 |   bool TraverseArraySubscriptExpr(ArraySubscriptExpr *E); | 
 |   bool TraverseCXXMemberCallExpr(CXXMemberCallExpr *MemberCall); | 
 |   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *OpCall); | 
 |   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, | 
 |                              Expr *Init); | 
 |   bool TraverseMemberExpr(MemberExpr *Member); | 
 |   bool TraverseUnaryDeref(UnaryOperator *Uop); | 
 |   bool VisitDeclRefExpr(DeclRefExpr *E); | 
 |   bool VisitDeclStmt(DeclStmt *S); | 
 |   bool TraverseStmt(Stmt *S); | 
 |  | 
 |   /// \brief Add an expression to the list of expressions on which the container | 
 |   /// expression depends. | 
 |   void addComponent(const Expr *E); | 
 |  | 
 |   // Input member variables: | 
 |   ASTContext *Context; | 
 |   /// The index variable's VarDecl. | 
 |   const VarDecl *IndexVar; | 
 |   /// The loop's 'end' variable, which cannot be mentioned at all. | 
 |   const VarDecl *EndVar; | 
 |   /// The Expr which refers to the container. | 
 |   const Expr *ContainerExpr; | 
 |   /// The Expr which refers to the terminating condition for array-based loops. | 
 |   const Expr *ArrayBoundExpr; | 
 |   bool ContainerNeedsDereference; | 
 |  | 
 |   // Output member variables: | 
 |   /// A container which holds all usages of IndexVar as the index of | 
 |   /// ArraySubscriptExpressions. | 
 |   UsageResult Usages; | 
 |   llvm::SmallSet<SourceLocation, 8> UsageLocations; | 
 |   bool OnlyUsedAsIndex; | 
 |   /// The DeclStmt for an alias to the container element. | 
 |   const DeclStmt *AliasDecl; | 
 |   Confidence ConfidenceLevel; | 
 |   /// \brief A list of expressions on which ContainerExpr depends. | 
 |   /// | 
 |   /// If any of these expressions are encountered outside of an acceptable usage | 
 |   /// of the loop element, lower our confidence level. | 
 |   llvm::SmallVector<std::pair<const Expr *, llvm::FoldingSetNodeID>, 16> | 
 |       DependentExprs; | 
 |  | 
 |   /// The parent-in-waiting. Will become the real parent once we traverse down | 
 |   /// one level in the AST. | 
 |   const Stmt *NextStmtParent; | 
 |   /// The actual parent of a node when Visit*() calls are made. Only the | 
 |   /// parentage of DeclStmt's to possible iteration/selection statements is of | 
 |   /// importance. | 
 |   const Stmt *CurrStmtParent; | 
 |  | 
 |   /// \see aliasUseRequired(). | 
 |   bool ReplaceWithAliasUse; | 
 |   /// \see aliasFromForInit(). | 
 |   bool AliasFromForInit; | 
 | }; | 
 |  | 
 | struct TUTrackingInfo { | 
 |   /// \brief Reset and initialize per-TU tracking information. | 
 |   /// | 
 |   /// Must be called before using container accessors. | 
 |   TUTrackingInfo() : ParentFinder(new StmtAncestorASTVisitor) {} | 
 |  | 
 |   StmtAncestorASTVisitor &getParentFinder() { return *ParentFinder; } | 
 |   StmtGeneratedVarNameMap &getGeneratedDecls() { return GeneratedDecls; } | 
 |   ReplacedVarsMap &getReplacedVars() { return ReplacedVars; } | 
 |  | 
 | private: | 
 |   std::unique_ptr<StmtAncestorASTVisitor> ParentFinder; | 
 |   StmtGeneratedVarNameMap GeneratedDecls; | 
 |   ReplacedVarsMap ReplacedVars; | 
 | }; | 
 |  | 
 | /// \brief Create names for generated variables within a particular statement. | 
 | /// | 
 | /// VariableNamer uses a DeclContext as a reference point, checking for any | 
 | /// conflicting declarations higher up in the context or within SourceStmt. | 
 | /// It creates a variable name using hints from a source container and the old | 
 | /// index, if they exist. | 
 | class VariableNamer { | 
 | public: | 
 |   // Supported naming styles. | 
 |   enum NamingStyle { | 
 |     NS_CamelBack, | 
 |     NS_CamelCase, | 
 |     NS_LowerCase, | 
 |     NS_UpperCase, | 
 |   }; | 
 |  | 
 |   VariableNamer(StmtGeneratedVarNameMap *GeneratedDecls, | 
 |                 const StmtParentMap *ReverseAST, const clang::Stmt *SourceStmt, | 
 |                 const clang::VarDecl *OldIndex, | 
 |                 const clang::ValueDecl *TheContainer, | 
 |                 const clang::ASTContext *Context, NamingStyle Style) | 
 |       : GeneratedDecls(GeneratedDecls), ReverseAST(ReverseAST), | 
 |         SourceStmt(SourceStmt), OldIndex(OldIndex), TheContainer(TheContainer), | 
 |         Context(Context), Style(Style) {} | 
 |  | 
 |   /// \brief Generate a new index name. | 
 |   /// | 
 |   /// Generates the name to be used for an inserted iterator. It relies on | 
 |   /// declarationExists() to determine that there are no naming conflicts, and | 
 |   /// tries to use some hints from the container name and the old index name. | 
 |   std::string createIndexName(); | 
 |  | 
 | private: | 
 |   StmtGeneratedVarNameMap *GeneratedDecls; | 
 |   const StmtParentMap *ReverseAST; | 
 |   const clang::Stmt *SourceStmt; | 
 |   const clang::VarDecl *OldIndex; | 
 |   const clang::ValueDecl *TheContainer; | 
 |   const clang::ASTContext *Context; | 
 |   const NamingStyle Style; | 
 |  | 
 |   // Determine whether or not a declaration that would conflict with Symbol | 
 |   // exists in an outer context or in any statement contained in SourceStmt. | 
 |   bool declarationExists(llvm::StringRef Symbol); | 
 | }; | 
 |  | 
 | } // namespace modernize | 
 | } // namespace tidy | 
 | } // namespace clang | 
 |  | 
 | #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H |