For Loop Conversion
[lldb.git] / clang-tools-extra / loop-convert / StmtAncestor.cpp
1 #include "StmtAncestor.h"
2
3 namespace clang {
4 namespace loop_migrate {
5
6 /// \brief Tracks a stack of parent statements during traversal.
7 ///
8 /// All this really does is inject push_back() before running
9 /// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop
10 /// the stack is the parent of the current statement (NULL for the topmost
11 /// statement).
12 bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) {
13   StmtAncestors.insert(std::make_pair(Statement, StmtStack.back()));
14   StmtStack.push_back(Statement);
15   RecursiveASTVisitor<StmtAncestorASTVisitor>::TraverseStmt(Statement);
16   StmtStack.pop_back();
17   return true;
18 }
19
20 /// \brief Keep track of the DeclStmt associated with each VarDecl.
21 ///
22 /// Combined with StmtAncestors, this provides roughly the same information as
23 /// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree
24 /// using StmtAncestors.
25 bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) {
26   for (DeclStmt::const_decl_iterator I = Decls->decl_begin(),
27                                      E = Decls->decl_end(); I != E; ++I)
28     if (const VarDecl *VD = dyn_cast<VarDecl>(*I))
29       DeclParents.insert(std::make_pair(VD, Decls));
30   return true;
31 }
32
33 /// \brief record the DeclRefExpr as part of the parent expression.
34 bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) {
35   Components.push_back(E);
36   return true;
37 }
38
39 /// \brief record the MemberExpr as part of the parent expression.
40 bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) {
41   Components.push_back(Member);
42   return true;
43 }
44
45 /// \brief Forward any DeclRefExprs to a check on the referenced variable
46 /// declaration.
47 bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
48   if (VarDecl *VD = dyn_cast_or_null<VarDecl>(DRE->getDecl()))
49     return VisitVarDecl(VD);
50   return true;
51 }
52
53 /// \brief Determine if any this variable is declared inside the ContainingStmt.
54 bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *VD) {
55   const Stmt *Curr = DeclParents->lookup(VD);
56   // First, see if the variable was declared within an inner scope of the loop.
57   while (Curr != NULL) {
58     if (Curr == ContainingStmt) {
59       DependsOnOutsideVariable = true;
60       return false;
61     }
62     Curr = StmtParents->lookup(Curr);
63   }
64
65   // Next, check if the variable was removed from existence by an earlier
66   // iteration.
67   for (ReplacedVarsMap::const_iterator I = ReplacedVars->begin(),
68                                        E = ReplacedVars->end(); I != E; ++I)
69     if ((*I).second == VD) {
70       DependsOnOutsideVariable = true;
71       return false;
72     }
73   return true;
74 }
75
76 /// \brief If we already created a variable for TheLoop, check to make sure
77 /// that the name was not already taken.
78 bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) {
79   StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop);
80   if (I != GeneratedDecls->end() && I->second == Name) {
81     Found = true;
82     return false;
83   }
84   return true;
85 }
86
87 /// \brief If any named declaration within the AST subtree has the same name,
88 /// then consider Name already taken.
89 bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *ND) {
90   const IdentifierInfo *Ident = ND->getIdentifier();
91   if (Ident && Ident->getName() == Name) {
92     Found = true;
93     return false;
94   }
95   return true;
96 }
97
98 /// \brief Forward any declaration references to the actual check on the
99 /// referenced declaration.
100 bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DRE) {
101   if (NamedDecl *ND = dyn_cast<NamedDecl>(DRE->getDecl()))
102     return VisitNamedDecl(ND);
103   return true;
104 }
105
106 } // namespace clang
107 } // namespace for_migrate