//===-- LoopConvert/StmtAncestor.cpp - AST property visitors ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// /// \file /// \brief This file contains the definitions of several RecursiveASTVisitors /// used to build and check data structures used in loop migration. /// //===----------------------------------------------------------------------===// #include "StmtAncestor.h" using namespace clang; /// \brief Tracks a stack of parent statements during traversal. /// /// All this really does is inject push_back() before running /// RecursiveASTVisitor::TraverseStmt() and pop_back() afterwards. The Stmt atop /// the stack is the parent of the current statement (NULL for the topmost /// statement). bool StmtAncestorASTVisitor::TraverseStmt(Stmt *Statement) { StmtAncestors.insert(std::make_pair(Statement, StmtStack.back())); StmtStack.push_back(Statement); RecursiveASTVisitor::TraverseStmt(Statement); StmtStack.pop_back(); return true; } /// \brief Keep track of the DeclStmt associated with each VarDecl. /// /// Combined with StmtAncestors, this provides roughly the same information as /// Scope, as we can map a VarDecl to its DeclStmt, then walk up the parent tree /// using StmtAncestors. bool StmtAncestorASTVisitor::VisitDeclStmt(DeclStmt *Decls) { for (DeclStmt::const_decl_iterator I = Decls->decl_begin(), E = Decls->decl_end(); I != E; ++I) if (const VarDecl *V = dyn_cast(*I)) DeclParents.insert(std::make_pair(V, Decls)); return true; } /// \brief record the DeclRefExpr as part of the parent expression. bool ComponentFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *E) { Components.push_back(E); return true; } /// \brief record the MemberExpr as part of the parent expression. bool ComponentFinderASTVisitor::VisitMemberExpr(MemberExpr *Member) { Components.push_back(Member); return true; } /// \brief Forward any DeclRefExprs to a check on the referenced variable /// declaration. bool DependencyFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) { if (VarDecl *V = dyn_cast_or_null(DeclRef->getDecl())) return VisitVarDecl(V); return true; } /// \brief Determine if any this variable is declared inside the ContainingStmt. bool DependencyFinderASTVisitor::VisitVarDecl(VarDecl *V) { const Stmt *Curr = DeclParents->lookup(V); // First, see if the variable was declared within an inner scope of the loop. while (Curr != NULL) { if (Curr == ContainingStmt) { DependsOnInsideVariable = true; return false; } Curr = StmtParents->lookup(Curr); } // Next, check if the variable was removed from existence by an earlier // iteration. for (ReplacedVarsMap::const_iterator I = ReplacedVars->begin(), E = ReplacedVars->end(); I != E; ++I) if ((*I).second == V) { DependsOnInsideVariable = true; return false; } return true; } /// \brief If we already created a variable for TheLoop, check to make sure /// that the name was not already taken. bool DeclFinderASTVisitor::VisitForStmt(ForStmt *TheLoop) { StmtGeneratedVarNameMap::const_iterator I = GeneratedDecls->find(TheLoop); if (I != GeneratedDecls->end() && I->second == Name) { Found = true; return false; } return true; } /// \brief If any named declaration within the AST subtree has the same name, /// then consider Name already taken. bool DeclFinderASTVisitor::VisitNamedDecl(NamedDecl *D) { const IdentifierInfo *Ident = D->getIdentifier(); if (Ident && Ident->getName() == Name) { Found = true; return false; } return true; } /// \brief Forward any declaration references to the actual check on the /// referenced declaration. bool DeclFinderASTVisitor::VisitDeclRefExpr(DeclRefExpr *DeclRef) { if (NamedDecl *D = dyn_cast(DeclRef->getDecl())) return VisitNamedDecl(D); return true; }