blob: 56665f9af3daebf267246659378bd499cca244a4 [file] [log] [blame]
Edwin Vanedde168b2013-01-04 18:25:18 +00001//===-- LoopConvert/StmtAncestor.h - AST property visitors ------*- 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/// \file
11/// \brief This file contains the declarations of several RecursiveASTVisitors
12/// used to build and check data structures used in loop migration.
13///
14//===----------------------------------------------------------------------===//
15#ifndef LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_STMT_ANCESTOR_H
16#define LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_STMT_ANCESTOR_H
17
18#include "clang/AST/RecursiveASTVisitor.h"
19
20/// A map used to walk the AST in reverse: maps child Stmt to parent Stmt.
21typedef llvm::DenseMap<const clang::Stmt*, const clang::Stmt*> StmtParentMap;
22
23/// A map used to walk the AST in reverse:
24/// maps VarDecl to the to parent DeclStmt.
25typedef
26llvm::DenseMap<const clang::VarDecl*, const clang::DeclStmt*> DeclParentMap;
27
28/// A map used to track which variables have been removed by a refactoring pass.
29/// It maps the parent ForStmt to the removed index variable's VarDecl.
30typedef
31llvm::DenseMap<const clang::ForStmt*, const clang::VarDecl*> ReplacedVarsMap;
32
33/// A map used to remember the variable names generated in a Stmt
34typedef llvm::DenseMap<const clang::Stmt*, std::string> StmtGeneratedVarNameMap;
35
36/// A vector used to store the AST subtrees of an Expr.
37typedef llvm::SmallVector<const clang::Expr*, 16> ComponentVector;
38
39/// \brief Class used build the reverse AST properties needed to detect
40/// name conflicts and free variables.
41class StmtAncestorASTVisitor :
42 public clang::RecursiveASTVisitor<StmtAncestorASTVisitor> {
43public:
44 StmtAncestorASTVisitor() {
45 StmtStack.push_back(NULL);
46 }
47
48 /// \brief Run the analysis on the TranslationUnitDecl.
49 ///
50 /// In case we're running this analysis multiple times, don't repeat the work.
51 void gatherAncestors(const clang::TranslationUnitDecl *T) {
52 if (StmtAncestors.empty())
53 TraverseDecl(const_cast<clang::TranslationUnitDecl*>(T));
54 }
55
56 /// Accessor for StmtAncestors.
57 const StmtParentMap &getStmtToParentStmtMap() {
58 return StmtAncestors;
59 }
60
61 /// Accessor for DeclParents.
62 const DeclParentMap &getDeclToParentStmtMap() {
63 return DeclParents;
64 }
65
66 friend class clang::RecursiveASTVisitor<StmtAncestorASTVisitor>;
67
68private:
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.
79class ComponentFinderASTVisitor :
80 public clang::RecursiveASTVisitor<ComponentFinderASTVisitor> {
81public:
82 ComponentFinderASTVisitor() { }
83
84 /// Find the components of an expression and place them in a ComponentVector.
85 void findExprComponents(const clang::Expr *SourceExpr) {
86 clang::Expr *E = const_cast<clang::Expr *>(SourceExpr);
87 TraverseStmt(E);
88 }
89
90 /// Accessor for Components.
91 const ComponentVector &getComponents() {
92 return Components;
93 }
94
95 friend class clang::RecursiveASTVisitor<ComponentFinderASTVisitor>;
96
97private:
98 ComponentVector Components;
99
100 bool VisitDeclRefExpr(clang::DeclRefExpr *E);
101 bool VisitMemberExpr(clang::MemberExpr *Member);
102};
103
104/// Class used to determine if an expression is dependent on a variable declared
105/// inside of the loop where it would be used.
106class DependencyFinderASTVisitor :
107 public clang::RecursiveASTVisitor<DependencyFinderASTVisitor> {
108public:
109 DependencyFinderASTVisitor(const StmtParentMap *StmtParents,
110 const DeclParentMap *DeclParents,
111 const ReplacedVarsMap *ReplacedVars,
112 const clang::Stmt *ContainingStmt) :
113 StmtParents(StmtParents), DeclParents(DeclParents),
114 ContainingStmt(ContainingStmt), ReplacedVars(ReplacedVars) { }
115
116 /// \brief Run the analysis on Body, and return true iff the expression
117 /// depends on some variable declared within ContainingStmt.
118 ///
119 /// This is intended to protect against hoisting the container expression
120 /// outside of an inner context if part of that expression is declared in that
121 /// inner context.
122 ///
123 /// For example,
124 /// \code
125 /// const int N = 10, M = 20;
126 /// int arr[N][M];
127 /// int getRow();
128 ///
129 /// for (int i = 0; i < M; ++i) {
130 /// int k = getRow();
131 /// printf("%d:", arr[k][i]);
132 /// }
133 /// \endcode
134 /// At first glance, this loop looks like it could be changed to
135 /// \code
136 /// for (int elem : arr[k]) {
137 /// int k = getIndex();
138 /// printf("%d:", elem);
139 /// }
140 /// \endcode
141 /// But this is malformed, since `k` is used before it is defined!
142 ///
143 /// In order to avoid this, this class looks at the container expression
144 /// `arr[k]` and decides whether or not it contains a sub-expression declared
145 /// within the the loop body.
146 bool dependsOnInsideVariable(const clang::Stmt *Body) {
147 DependsOnInsideVariable = false;
148 TraverseStmt(const_cast<clang::Stmt *>(Body));
149 return DependsOnInsideVariable;
150 }
151
152 friend class clang::RecursiveASTVisitor<DependencyFinderASTVisitor>;
153
154private:
155 const StmtParentMap *StmtParents;
156 const DeclParentMap *DeclParents;
157 const clang::Stmt *ContainingStmt;
158 const ReplacedVarsMap *ReplacedVars;
159 bool DependsOnInsideVariable;
160
161 bool VisitVarDecl(clang::VarDecl *V);
162 bool VisitDeclRefExpr(clang::DeclRefExpr *D);
163};
164
165/// Class used to determine if any declarations used in a Stmt would conflict
166/// with a particular identifier. This search includes the names that don't
167/// actually appear in the AST (i.e. created by a refactoring tool) by including
168/// a map from Stmts to generated names associated with those stmts.
169class DeclFinderASTVisitor :
170 public clang::RecursiveASTVisitor<DeclFinderASTVisitor> {
171public:
172 DeclFinderASTVisitor(const std::string &Name,
173 const StmtGeneratedVarNameMap *GeneratedDecls) :
174 Name(Name), GeneratedDecls(GeneratedDecls), Found(false) { }
175
176 /// Attempts to find any usages of variables name Name in Body, returning
177 /// true when it is used in Body. This includes the generated loop variables
178 /// of ForStmts which have already been transformed.
179 bool findUsages(const clang::Stmt *Body) {
180 Found = false;
181 TraverseStmt(const_cast<clang::Stmt *>(Body));
182 return Found;
183 }
184
Chandler Carruth08116a72013-01-05 02:57:54 +0000185 friend class clang::RecursiveASTVisitor<DeclFinderASTVisitor>;
Edwin Vanedde168b2013-01-04 18:25:18 +0000186
187private:
188 std::string Name;
189 /// GeneratedDecls keeps track of ForStmts which have been tranformed, mapping
190 /// each modified ForStmt to the variable generated in the loop.
191 const StmtGeneratedVarNameMap *GeneratedDecls;
192 bool Found;
193
194 bool VisitForStmt(clang::ForStmt *F);
195 bool VisitNamedDecl(clang::NamedDecl *D);
196 bool VisitDeclRefExpr(clang::DeclRefExpr *D);
197};
198
199#endif // LLVM_TOOLS_CLANG_TOOLS_EXTRA_CPP11_MIGRATE_STMT_ANCESTOR_H