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