LoopConvertUtils.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. //===--- LoopConvertUtils.h - clang-tidy ------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H
  9. #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H
  10. #include "clang/AST/ASTContext.h"
  11. #include "clang/AST/RecursiveASTVisitor.h"
  12. #include "clang/ASTMatchers/ASTMatchFinder.h"
  13. #include "clang/Basic/SourceLocation.h"
  14. #include "llvm/ADT/DenseMap.h"
  15. #include "llvm/ADT/SmallSet.h"
  16. #include "llvm/ADT/SmallVector.h"
  17. #include "llvm/ADT/StringRef.h"
  18. #include <algorithm>
  19. #include <memory>
  20. #include <string>
  21. #include <utility>
  22. namespace clang::tidy::modernize {
  23. enum LoopFixerKind {
  24. LFK_Array,
  25. LFK_Iterator,
  26. LFK_ReverseIterator,
  27. LFK_PseudoArray
  28. };
  29. /// A map used to walk the AST in reverse: maps child Stmt to parent Stmt.
  30. typedef llvm::DenseMap<const clang::Stmt *, const clang::Stmt *> StmtParentMap;
  31. /// A map used to walk the AST in reverse:
  32. /// maps VarDecl to the to parent DeclStmt.
  33. typedef llvm::DenseMap<const clang::VarDecl *, const clang::DeclStmt *>
  34. DeclParentMap;
  35. /// A map used to track which variables have been removed by a refactoring pass.
  36. /// It maps the parent ForStmt to the removed index variable's VarDecl.
  37. typedef llvm::DenseMap<const clang::ForStmt *, const clang::VarDecl *>
  38. ReplacedVarsMap;
  39. /// A map used to remember the variable names generated in a Stmt
  40. typedef llvm::DenseMap<const clang::Stmt *, std::string>
  41. StmtGeneratedVarNameMap;
  42. /// A vector used to store the AST subtrees of an Expr.
  43. typedef llvm::SmallVector<const clang::Expr *, 16> ComponentVector;
  44. /// Class used build the reverse AST properties needed to detect
  45. /// name conflicts and free variables.
  46. class StmtAncestorASTVisitor
  47. : public clang::RecursiveASTVisitor<StmtAncestorASTVisitor> {
  48. public:
  49. StmtAncestorASTVisitor() { StmtStack.push_back(nullptr); }
  50. /// Run the analysis on the AST.
  51. ///
  52. /// In case we're running this analysis multiple times, don't repeat the work.
  53. void gatherAncestors(ASTContext &Ctx) {
  54. if (StmtAncestors.empty())
  55. TraverseAST(Ctx);
  56. }
  57. /// Accessor for StmtAncestors.
  58. const StmtParentMap &getStmtToParentStmtMap() { return StmtAncestors; }
  59. /// Accessor for DeclParents.
  60. const DeclParentMap &getDeclToParentStmtMap() { return DeclParents; }
  61. friend class clang::RecursiveASTVisitor<StmtAncestorASTVisitor>;
  62. private:
  63. StmtParentMap StmtAncestors;
  64. DeclParentMap DeclParents;
  65. llvm::SmallVector<const clang::Stmt *, 16> StmtStack;
  66. bool TraverseStmt(clang::Stmt *Statement);
  67. bool VisitDeclStmt(clang::DeclStmt *Statement);
  68. };
  69. /// Class used to find the variables and member expressions on which an
  70. /// arbitrary expression depends.
  71. class ComponentFinderASTVisitor
  72. : public clang::RecursiveASTVisitor<ComponentFinderASTVisitor> {
  73. public:
  74. ComponentFinderASTVisitor() = default;
  75. /// Find the components of an expression and place them in a ComponentVector.
  76. void findExprComponents(const clang::Expr *SourceExpr) {
  77. TraverseStmt(const_cast<clang::Expr *>(SourceExpr));
  78. }
  79. /// Accessor for Components.
  80. const ComponentVector &getComponents() { return Components; }
  81. friend class clang::RecursiveASTVisitor<ComponentFinderASTVisitor>;
  82. private:
  83. ComponentVector Components;
  84. bool VisitDeclRefExpr(clang::DeclRefExpr *E);
  85. bool VisitMemberExpr(clang::MemberExpr *Member);
  86. };
  87. /// Class used to determine if an expression is dependent on a variable declared
  88. /// inside of the loop where it would be used.
  89. class DependencyFinderASTVisitor
  90. : public clang::RecursiveASTVisitor<DependencyFinderASTVisitor> {
  91. public:
  92. DependencyFinderASTVisitor(const StmtParentMap *StmtParents,
  93. const DeclParentMap *DeclParents,
  94. const ReplacedVarsMap *ReplacedVars,
  95. const clang::Stmt *ContainingStmt)
  96. : StmtParents(StmtParents), DeclParents(DeclParents),
  97. ContainingStmt(ContainingStmt), ReplacedVars(ReplacedVars) {}
  98. /// Run the analysis on Body, and return true iff the expression
  99. /// depends on some variable declared within ContainingStmt.
  100. ///
  101. /// This is intended to protect against hoisting the container expression
  102. /// outside of an inner context if part of that expression is declared in that
  103. /// inner context.
  104. ///
  105. /// For example,
  106. /// \code
  107. /// const int N = 10, M = 20;
  108. /// int arr[N][M];
  109. /// int getRow();
  110. ///
  111. /// for (int i = 0; i < M; ++i) {
  112. /// int k = getRow();
  113. /// printf("%d:", arr[k][i]);
  114. /// }
  115. /// \endcode
  116. /// At first glance, this loop looks like it could be changed to
  117. /// \code
  118. /// for (int elem : arr[k]) {
  119. /// int k = getIndex();
  120. /// printf("%d:", elem);
  121. /// }
  122. /// \endcode
  123. /// But this is malformed, since `k` is used before it is defined!
  124. ///
  125. /// In order to avoid this, this class looks at the container expression
  126. /// `arr[k]` and decides whether or not it contains a sub-expression declared
  127. /// within the loop body.
  128. bool dependsOnInsideVariable(const clang::Stmt *Body) {
  129. DependsOnInsideVariable = false;
  130. TraverseStmt(const_cast<clang::Stmt *>(Body));
  131. return DependsOnInsideVariable;
  132. }
  133. friend class clang::RecursiveASTVisitor<DependencyFinderASTVisitor>;
  134. private:
  135. const StmtParentMap *StmtParents;
  136. const DeclParentMap *DeclParents;
  137. const clang::Stmt *ContainingStmt;
  138. const ReplacedVarsMap *ReplacedVars;
  139. bool DependsOnInsideVariable;
  140. bool VisitVarDecl(clang::VarDecl *V);
  141. bool VisitDeclRefExpr(clang::DeclRefExpr *D);
  142. };
  143. /// Class used to determine if any declarations used in a Stmt would conflict
  144. /// with a particular identifier. This search includes the names that don't
  145. /// actually appear in the AST (i.e. created by a refactoring tool) by including
  146. /// a map from Stmts to generated names associated with those stmts.
  147. class DeclFinderASTVisitor
  148. : public clang::RecursiveASTVisitor<DeclFinderASTVisitor> {
  149. public:
  150. DeclFinderASTVisitor(const StringRef &Name,
  151. const StmtGeneratedVarNameMap *GeneratedDecls)
  152. : Name(Name), GeneratedDecls(GeneratedDecls), Found(false) {}
  153. /// Attempts to find any usages of variables name Name in Body, returning
  154. /// true when it is used in Body. This includes the generated loop variables
  155. /// of ForStmts which have already been transformed.
  156. bool findUsages(const clang::Stmt *Body) {
  157. Found = false;
  158. TraverseStmt(const_cast<clang::Stmt *>(Body));
  159. return Found;
  160. }
  161. friend class clang::RecursiveASTVisitor<DeclFinderASTVisitor>;
  162. private:
  163. std::string Name;
  164. /// GeneratedDecls keeps track of ForStmts which have been transformed,
  165. /// mapping each modified ForStmt to the variable generated in the loop.
  166. const StmtGeneratedVarNameMap *GeneratedDecls;
  167. bool Found;
  168. bool VisitForStmt(clang::ForStmt *F);
  169. bool VisitNamedDecl(clang::NamedDecl *D);
  170. bool VisitDeclRefExpr(clang::DeclRefExpr *D);
  171. bool VisitTypeLoc(clang::TypeLoc TL);
  172. };
  173. /// The information needed to describe a valid convertible usage
  174. /// of an array index or iterator.
  175. struct Usage {
  176. enum UsageKind {
  177. // Regular usages of the loop index (the ones not specified below). Some
  178. // examples:
  179. // \code
  180. // int X = 8 * Arr[i];
  181. // ^~~~~~
  182. // f(param1, param2, *It);
  183. // ^~~
  184. // if (Vec[i].SomeBool) {}
  185. // ^~~~~~
  186. // \endcode
  187. UK_Default,
  188. // Indicates whether this is an access to a member through the arrow
  189. // operator on pointers or iterators.
  190. UK_MemberThroughArrow,
  191. // If the variable is being captured by a lambda, indicates whether the
  192. // capture was done by value or by reference.
  193. UK_CaptureByCopy,
  194. UK_CaptureByRef
  195. };
  196. // The expression that is going to be converted. Null in case of lambda
  197. // captures.
  198. const Expr *Expression;
  199. UsageKind Kind;
  200. // Range that covers this usage.
  201. SourceRange Range;
  202. explicit Usage(const Expr *E)
  203. : Expression(E), Kind(UK_Default), Range(Expression->getSourceRange()) {}
  204. Usage(const Expr *E, UsageKind Kind, SourceRange Range)
  205. : Expression(E), Kind(Kind), Range(std::move(Range)) {}
  206. };
  207. /// A class to encapsulate lowering of the tool's confidence level.
  208. class Confidence {
  209. public:
  210. enum Level {
  211. // Transformations that are likely to change semantics.
  212. CL_Risky,
  213. // Transformations that might change semantics.
  214. CL_Reasonable,
  215. // Transformations that will not change semantics.
  216. CL_Safe
  217. };
  218. /// Initialize confidence level.
  219. explicit Confidence(Confidence::Level Level) : CurrentLevel(Level) {}
  220. /// Lower the internal confidence level to Level, but do not raise it.
  221. void lowerTo(Confidence::Level Level) {
  222. CurrentLevel = std::min(Level, CurrentLevel);
  223. }
  224. /// Return the internal confidence level.
  225. Level getLevel() const { return CurrentLevel; }
  226. private:
  227. Level CurrentLevel;
  228. };
  229. // The main computational result of ForLoopIndexVisitor.
  230. typedef llvm::SmallVector<Usage, 8> UsageResult;
  231. // General functions used by ForLoopIndexUseVisitor and LoopConvertCheck.
  232. const Expr *digThroughConstructorsConversions(const Expr *E);
  233. bool areSameExpr(ASTContext *Context, const Expr *First, const Expr *Second);
  234. const DeclRefExpr *getDeclRef(const Expr *E);
  235. bool areSameVariable(const ValueDecl *First, const ValueDecl *Second);
  236. /// Discover usages of expressions consisting of index or iterator
  237. /// access.
  238. ///
  239. /// Given an index variable, recursively crawls a for loop to discover if the
  240. /// index variable is used in a way consistent with range-based for loop access.
  241. class ForLoopIndexUseVisitor
  242. : public RecursiveASTVisitor<ForLoopIndexUseVisitor> {
  243. public:
  244. ForLoopIndexUseVisitor(ASTContext *Context, const VarDecl *IndexVar,
  245. const VarDecl *EndVar, const Expr *ContainerExpr,
  246. const Expr *ArrayBoundExpr,
  247. bool ContainerNeedsDereference);
  248. /// Finds all uses of IndexVar in Body, placing all usages in Usages,
  249. /// and returns true if IndexVar was only used in a way consistent with a
  250. /// range-based for loop.
  251. ///
  252. /// The general strategy is to reject any DeclRefExprs referencing IndexVar,
  253. /// with the exception of certain acceptable patterns.
  254. /// For arrays, the DeclRefExpr for IndexVar must appear as the index of an
  255. /// ArraySubscriptExpression. Iterator-based loops may dereference
  256. /// IndexVar or call methods through operator-> (builtin or overloaded).
  257. /// Array-like containers may use IndexVar as a parameter to the at() member
  258. /// function and in overloaded operator[].
  259. bool findAndVerifyUsages(const Stmt *Body);
  260. /// Add a set of components that we should consider relevant to the
  261. /// container.
  262. void addComponents(const ComponentVector &Components);
  263. /// Accessor for Usages.
  264. const UsageResult &getUsages() const { return Usages; }
  265. /// Adds the Usage if it was not added before.
  266. void addUsage(const Usage &U);
  267. /// Get the container indexed by IndexVar, if any.
  268. const Expr *getContainerIndexed() const { return ContainerExpr; }
  269. /// Returns the statement declaring the variable created as an alias
  270. /// for the loop element, if any.
  271. const DeclStmt *getAliasDecl() const { return AliasDecl; }
  272. /// Accessor for ConfidenceLevel.
  273. Confidence::Level getConfidenceLevel() const {
  274. return ConfidenceLevel.getLevel();
  275. }
  276. /// Indicates if the alias declaration was in a place where it cannot
  277. /// simply be removed but rather replaced with a use of the alias variable.
  278. /// For example, variables declared in the condition of an if, switch, or for
  279. /// stmt.
  280. bool aliasUseRequired() const { return ReplaceWithAliasUse; }
  281. /// Indicates if the alias declaration came from the init clause of a
  282. /// nested for loop. SourceRanges provided by Clang for DeclStmts in this
  283. /// case need to be adjusted.
  284. bool aliasFromForInit() const { return AliasFromForInit; }
  285. private:
  286. /// Typedef used in CRTP functions.
  287. typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase;
  288. friend class RecursiveASTVisitor<ForLoopIndexUseVisitor>;
  289. /// Overriden methods for RecursiveASTVisitor's traversal.
  290. bool TraverseArraySubscriptExpr(ArraySubscriptExpr *E);
  291. bool TraverseCXXMemberCallExpr(CXXMemberCallExpr *MemberCall);
  292. bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *OpCall);
  293. bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
  294. Expr *Init);
  295. bool TraverseMemberExpr(MemberExpr *Member);
  296. bool TraverseUnaryOperator(UnaryOperator *Uop);
  297. bool VisitDeclRefExpr(DeclRefExpr *E);
  298. bool VisitDeclStmt(DeclStmt *S);
  299. bool TraverseStmt(Stmt *S);
  300. /// Add an expression to the list of expressions on which the container
  301. /// expression depends.
  302. void addComponent(const Expr *E);
  303. // Input member variables:
  304. ASTContext *Context;
  305. /// The index variable's VarDecl.
  306. const VarDecl *IndexVar;
  307. /// The loop's 'end' variable, which cannot be mentioned at all.
  308. const VarDecl *EndVar;
  309. /// The Expr which refers to the container.
  310. const Expr *ContainerExpr;
  311. /// The Expr which refers to the terminating condition for array-based loops.
  312. const Expr *ArrayBoundExpr;
  313. bool ContainerNeedsDereference;
  314. // Output member variables:
  315. /// A container which holds all usages of IndexVar as the index of
  316. /// ArraySubscriptExpressions.
  317. UsageResult Usages;
  318. llvm::SmallSet<SourceLocation, 8> UsageLocations;
  319. bool OnlyUsedAsIndex;
  320. /// The DeclStmt for an alias to the container element.
  321. const DeclStmt *AliasDecl;
  322. Confidence ConfidenceLevel;
  323. /// A list of expressions on which ContainerExpr depends.
  324. ///
  325. /// If any of these expressions are encountered outside of an acceptable usage
  326. /// of the loop element, lower our confidence level.
  327. llvm::SmallVector<std::pair<const Expr *, llvm::FoldingSetNodeID>, 16>
  328. DependentExprs;
  329. /// The parent-in-waiting. Will become the real parent once we traverse down
  330. /// one level in the AST.
  331. const Stmt *NextStmtParent;
  332. /// The actual parent of a node when Visit*() calls are made. Only the
  333. /// parentage of DeclStmt's to possible iteration/selection statements is of
  334. /// importance.
  335. const Stmt *CurrStmtParent;
  336. /// \see aliasUseRequired().
  337. bool ReplaceWithAliasUse;
  338. /// \see aliasFromForInit().
  339. bool AliasFromForInit;
  340. };
  341. struct TUTrackingInfo {
  342. /// Reset and initialize per-TU tracking information.
  343. ///
  344. /// Must be called before using container accessors.
  345. TUTrackingInfo() : ParentFinder(new StmtAncestorASTVisitor) {}
  346. StmtAncestorASTVisitor &getParentFinder() { return *ParentFinder; }
  347. StmtGeneratedVarNameMap &getGeneratedDecls() { return GeneratedDecls; }
  348. ReplacedVarsMap &getReplacedVars() { return ReplacedVars; }
  349. private:
  350. std::unique_ptr<StmtAncestorASTVisitor> ParentFinder;
  351. StmtGeneratedVarNameMap GeneratedDecls;
  352. ReplacedVarsMap ReplacedVars;
  353. };
  354. /// Create names for generated variables within a particular statement.
  355. ///
  356. /// VariableNamer uses a DeclContext as a reference point, checking for any
  357. /// conflicting declarations higher up in the context or within SourceStmt.
  358. /// It creates a variable name using hints from a source container and the old
  359. /// index, if they exist.
  360. class VariableNamer {
  361. public:
  362. // Supported naming styles.
  363. enum NamingStyle {
  364. NS_CamelBack,
  365. NS_CamelCase,
  366. NS_LowerCase,
  367. NS_UpperCase,
  368. };
  369. VariableNamer(StmtGeneratedVarNameMap *GeneratedDecls,
  370. const StmtParentMap *ReverseAST, const clang::Stmt *SourceStmt,
  371. const clang::VarDecl *OldIndex,
  372. const clang::ValueDecl *TheContainer,
  373. const clang::ASTContext *Context, NamingStyle Style)
  374. : GeneratedDecls(GeneratedDecls), ReverseAST(ReverseAST),
  375. SourceStmt(SourceStmt), OldIndex(OldIndex), TheContainer(TheContainer),
  376. Context(Context), Style(Style) {}
  377. /// Generate a new index name.
  378. ///
  379. /// Generates the name to be used for an inserted iterator. It relies on
  380. /// declarationExists() to determine that there are no naming conflicts, and
  381. /// tries to use some hints from the container name and the old index name.
  382. std::string createIndexName();
  383. private:
  384. StmtGeneratedVarNameMap *GeneratedDecls;
  385. const StmtParentMap *ReverseAST;
  386. const clang::Stmt *SourceStmt;
  387. const clang::VarDecl *OldIndex;
  388. const clang::ValueDecl *TheContainer;
  389. const clang::ASTContext *Context;
  390. const NamingStyle Style;
  391. // Determine whether or not a declaration that would conflict with Symbol
  392. // exists in an outer context or in any statement contained in SourceStmt.
  393. bool declarationExists(llvm::StringRef Symbol);
  394. };
  395. } // namespace clang::tidy::modernize
  396. #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_LOOP_CONVERT_UTILS_H