clang-tools  7.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:
113  DependencyFinderASTVisitor(const StmtParentMap *StmtParents,
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.
225  UK_CaptureByRef
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.
253  CL_Safe
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.
340  typedef RecursiveASTVisitor<ForLoopIndexUseVisitor> VisitorBase;
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
llvm::StringRef Name
StmtAncestorASTVisitor & getParentFinder()
Confidence::Level getConfidenceLevel() const
Accessor for ConfidenceLevel.
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.
static void addUsage(IdentifierNamingCheck::NamingCheckFailureMap &Failures, const IdentifierNamingCheck::NamingCheckId &Decl, SourceRange Range, SourceManager *SourceMgr=nullptr)
llvm::SmallVector< Usage, 8 > UsageResult
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.
DependencyFinderASTVisitor(const StmtParentMap *StmtParents, const DeclParentMap *DeclParents, const ReplacedVarsMap *ReplacedVars, const clang::Stmt *ContainingStmt)
A class to encapsulate lowering of the tool&#39;s confidence level.
const Expr * getContainerIndexed() const
Get the container indexed by IndexVar, if any.
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.
bool aliasUseRequired() const
Indicates if the alias declaration was in a place where it cannot simply be removed but rather replac...
const Expr * digThroughConstructors(const Expr *E)
Look through conversion/copy constructors to find the explicit initialization expression, returning it is found.
StmtGeneratedVarNameMap & getGeneratedDecls()
bool aliasFromForInit() const
Indicates if the alias declaration came from the init clause of a nested for loop.
const DeclRefExpr * getDeclRef(const Expr *E)
Returns the DeclRefExpr represented by E, or NULL if there isn&#39;t one.
void findExprComponents(const clang::Expr *SourceExpr)
Find the components of an expression and place them in a ComponentVector.
const ComponentVector & getComponents()
Accessor for Components.
Level getLevel() const
Return the internal confidence level.
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.
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)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
The information needed to describe a valid convertible usage of an array index or iterator...
void lowerTo(Confidence::Level Level)
Lower the internal confidence level to Level, but do not raise it.
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...
llvm::DenseMap< const clang::Stmt *, const clang::Stmt * > StmtParentMap
A map used to walk the AST in reverse: maps child Stmt to parent Stmt.
const UsageResult & getUsages() const
Accessor for Usages.
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)
const DeclStmt * getAliasDecl() const
Returns the statement declaring the variable created as an alias for the loop element, if any.