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