From bd2ab6e8f6ec16ca29e2479c8bc2a48a4eae7f07 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 7 Jul 2009 00:53:31 +0000 Subject: [PATCH] Refactor DeclLocResolver/StmtLocResolver into a more functional style by removing the search state and by having their Visit* methods return the ASTLocation directly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@74887 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Index/ResolveLocation.cpp | 304 +++++++++++++--------------------- 1 file changed, 117 insertions(+), 187 deletions(-) diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp index b9df702904..e27e9bce4f 100644 --- a/lib/Index/ResolveLocation.cpp +++ b/lib/Index/ResolveLocation.cpp @@ -29,270 +29,202 @@ class VISIBILITY_HIDDEN LocResolverBase { protected: ASTContext &Ctx; SourceLocation Loc; - - Decl *Dcl; - Stmt *Stm; - bool PassedLoc; - - /// \brief Checks whether Loc is in the source range of 'D'. - /// - /// If it is, updates Dcl. If Loc is passed the source range, it sets - /// PassedLoc, otherwise it does nothing. - void CheckRange(Decl *D); - - /// \brief Checks whether Loc is in the source range of 'Node'. - /// - /// If it is, updates Stm. If Loc is passed the source range, it sets - /// PassedLoc, otherwise it does nothing. - void CheckRange(Stmt *Node); - - /// \brief Updates the end source range to cover the full length of the token - /// positioned at the end of the source range. - /// - /// e.g., - /// @code - /// int foo - /// ^ ^ - /// @endcode - /// will be updated to - /// @code - /// int foo - /// ^ ^ - /// @endcode - void FixRange(SourceRange &Range); + + enum RangePos { + BeforeLoc, + ContainsLoc, + AfterLoc + }; + + RangePos CheckRange(SourceRange Range); + RangePos CheckRange(Decl *D) { return CheckRange(D->getSourceRange()); } + RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); } public: LocResolverBase(ASTContext &ctx, SourceLocation loc) - : Ctx(ctx), Loc(loc), Dcl(0), Stm(0), PassedLoc(0) {} - - /// \brief We found a AST node that corresponds to the source location. - bool FoundIt() const { return Dcl != 0 || Stm != 0; } + : Ctx(ctx), Loc(loc) {} - /// \brief We either found a AST node or we passed the source location while - /// searching. - bool Finished() const { return FoundIt() || PassedLoc; } - - Decl *getDecl() const { return Dcl; } - Stmt *getStmt() const { return Stm; } - - std::pair getResult() const { - return std::make_pair(getDecl(), getStmt()); - } - /// \brief Debugging output. void print(Decl *D); /// \brief Debugging output. void print(Stmt *Node); }; -/// \brief Searches a statement for the AST node that corresponds to a source +/// \brief Searches a statement for the ASTLocation that corresponds to a source /// location. class VISIBILITY_HIDDEN StmtLocResolver : public LocResolverBase, - public StmtVisitor { + public StmtVisitor { + Decl *Parent; + public: - StmtLocResolver(ASTContext &ctx, SourceLocation loc) - : LocResolverBase(ctx, loc) {} + StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent) + : LocResolverBase(ctx, loc), Parent(parent) {} - void VisitDeclStmt(DeclStmt *Node); - void VisitStmt(Stmt *Node); + ASTLocation VisitDeclStmt(DeclStmt *Node); + ASTLocation VisitStmt(Stmt *Node); }; -/// \brief Searches a declaration for the AST node that corresponds to a source -/// location. +/// \brief Searches a declaration for the ASTLocation that corresponds to a +/// source location. class VISIBILITY_HIDDEN DeclLocResolver : public LocResolverBase, - public DeclVisitor { + public DeclVisitor { public: DeclLocResolver(ASTContext &ctx, SourceLocation loc) : LocResolverBase(ctx, loc) {} - void VisitDeclContext(DeclContext *DC); - void VisitTranslationUnitDecl(TranslationUnitDecl *TU); - void VisitVarDecl(VarDecl *D); - void VisitFunctionDecl(FunctionDecl *D); - void VisitDecl(Decl *D); + ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU); + ASTLocation VisitVarDecl(VarDecl *D); + ASTLocation VisitFunctionDecl(FunctionDecl *D); + ASTLocation VisitDecl(Decl *D); }; } // anonymous namespace -void StmtLocResolver::VisitDeclStmt(DeclStmt *Node) { - CheckRange(Node); - if (!FoundIt()) - return; - assert(Stm == Node && "Result not updated ?"); +ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) { + assert(CheckRange(Node) == ContainsLoc + && "Should visit only after verifying that loc is in range"); - // Search all declarations of this DeclStmt. If we found the one corresponding - // to the source location, update this StmtLocResolver's result. - DeclLocResolver DLR(Ctx, Loc); + // Search all declarations of this DeclStmt. for (DeclStmt::decl_iterator I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) { - DLR.Visit(*I); - if (DLR.Finished()) { - if (DLR.FoundIt()) - llvm::tie(Dcl, Stm) = DLR.getResult(); - return; - } + RangePos RP = CheckRange(*I); + if (RP == AfterLoc) + break; + if (RP == ContainsLoc) + return DeclLocResolver(Ctx, Loc).Visit(*I); } + + return ASTLocation(Parent, Node); } -void StmtLocResolver::VisitStmt(Stmt *Node) { - CheckRange(Node); - if (!FoundIt()) - return; - assert(Stm == Node && "Result not updated ?"); - +ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) { + assert(CheckRange(Node) == ContainsLoc + && "Should visit only after verifying that loc is in range"); + // Search the child statements. - StmtLocResolver SLR(Ctx, Loc); for (Stmt::child_iterator I = Node->child_begin(), E = Node->child_end(); I != E; ++I) { - SLR.Visit(*I); - if (!SLR.Finished()) - continue; - - // We either found it or we passed the source location. - - if (SLR.FoundIt()) { - // Only update Dcl if we found another more immediate 'parent' Decl for - // the statement. - if (SLR.getDecl()) - Dcl = SLR.getDecl(); - Stm = SLR.getStmt(); - } - - return; + RangePos RP = CheckRange(*I); + if (RP == AfterLoc) + break; + if (RP == ContainsLoc) + return Visit(*I); } + + return ASTLocation(Parent, Node); } -void DeclLocResolver::VisitDeclContext(DeclContext *DC) { - DeclLocResolver DLR(Ctx, Loc); +ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { + DeclContext *DC = TU; + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { - DLR.Visit(*I); - if (DLR.Finished()) { - if (DLR.FoundIt()) - llvm::tie(Dcl, Stm) = DLR.getResult(); - return; - } + RangePos RP = CheckRange(*I); + if (RP == AfterLoc) + break; + if (RP == ContainsLoc) + return Visit(*I); } -} -void DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { - VisitDeclContext(TU); + return ASTLocation(); } -void DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) { - CheckRange(D); - if (!FoundIt()) - return; - assert(Dcl == D && "Result not updated ?"); +ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) { + assert(CheckRange(D) == ContainsLoc + && "Should visit only after verifying that loc is in range"); // First, search through the parameters of the function. - DeclLocResolver ParmRes(Ctx, Loc); for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); I != E; ++I) { - ParmRes.Visit(*I); - if (ParmRes.Finished()) { - if (ParmRes.FoundIt()) - llvm::tie(Dcl, Stm) = ParmRes.getResult(); - return; - } + RangePos RP = CheckRange(*I); + if (RP == AfterLoc) + return ASTLocation(D); + if (RP == ContainsLoc) + return Visit(*I); } - // We didn't found the location in the parameters and we didn't get passed it. + // We didn't find the location in the parameters and we didn't get passed it. if (!D->isThisDeclarationADefinition()) - return; + return ASTLocation(D); // Second, search through the declarations that are part of the function. // If we find he location there, we won't have to search through its body. - DeclLocResolver DLR(Ctx, Loc); for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end(); I != E; ++I) { if (isa(*I)) continue; // We already searched through the parameters. - DLR.Visit(*I); - if (DLR.FoundIt()) { - llvm::tie(Dcl, Stm) = DLR.getResult(); - return; - } + RangePos RP = CheckRange(*I); + if (RP == AfterLoc) + break; + if (RP == ContainsLoc) + return Visit(*I); } // We didn't find a declaration that corresponds to the source location. // Finally, search through the body of the function. - assert(D->getBody() && "Expected definition"); - StmtLocResolver SLR(Ctx, Loc); - SLR.Visit(D->getBody()); - if (SLR.FoundIt()) { - llvm::tie(Dcl, Stm) = SLR.getResult(); - // If we didn't find a more immediate 'parent' declaration for the - // statement, set the function as the parent. - if (Dcl == 0) - Dcl = D; - } + Stmt *Body = D->getBody(); + assert(Body && "Expected definition"); + assert(CheckRange(Body) != BeforeLoc + && "This function is supposed to contain the loc"); + if (CheckRange(Body) == AfterLoc) + return ASTLocation(D); + + // The body contains the location. + assert(CheckRange(Body) == ContainsLoc); + return StmtLocResolver(Ctx, Loc, D).Visit(Body); } -void DeclLocResolver::VisitVarDecl(VarDecl *D) { - CheckRange(D); - if (!FoundIt()) - return; - assert(Dcl == D && "Result not updated ?"); - +ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) { + assert(CheckRange(D) == ContainsLoc + && "Should visit only after verifying that loc is in range"); + // Check whether the location points to the init expression. - if (D->getInit()) { - StmtLocResolver SLR(Ctx, Loc); - SLR.Visit(D->getInit()); - Stm = SLR.getStmt(); - } -} + Expr *Init = D->getInit(); + if (Init && CheckRange(Init) == ContainsLoc) + return StmtLocResolver(Ctx, Loc, D).Visit(Init); -void DeclLocResolver::VisitDecl(Decl *D) { - CheckRange(D); + return ASTLocation(D); } -void LocResolverBase::CheckRange(Decl *D) { - SourceRange Range = D->getSourceRange(); - if (!Range.isValid()) - return; - - FixRange(Range); - - SourceManager &SourceMgr = Ctx.getSourceManager(); - if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc)) - return; - - if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin())) - PassedLoc = true; - else - Dcl = D; +ASTLocation DeclLocResolver::VisitDecl(Decl *D) { + assert(CheckRange(D) == ContainsLoc + && "Should visit only after verifying that loc is in range"); + return ASTLocation(D); } -void LocResolverBase::CheckRange(Stmt *Node) { - SourceRange Range = Node->getSourceRange(); +LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) { if (!Range.isValid()) - return; - - FixRange(Range); + return BeforeLoc; // Keep looking. + + // Update the end source range to cover the full length of the token + // positioned at the end of the source range. + // + // e.g., + // int foo + // ^ ^ + // + // will be updated to + // int foo + // ^ ^ + unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(), + Ctx.getSourceManager(), + Ctx.getLangOptions()); + Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1)); SourceManager &SourceMgr = Ctx.getSourceManager(); if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc)) - return; + return BeforeLoc; if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin())) - PassedLoc = true; - else - Stm = Node; -} + return AfterLoc; -void LocResolverBase::FixRange(SourceRange &Range) { - if (!Range.isValid()) - return; - - unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(), - Ctx.getSourceManager(), - Ctx.getLangOptions()); - Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1)); + return ContainsLoc; } void LocResolverBase::print(Decl *D) { @@ -326,7 +258,5 @@ ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) { if (Loc.isInvalid()) return ASTLocation(); - DeclLocResolver DLR(Ctx, Loc); - DLR.Visit(Ctx.getTranslationUnitDecl()); - return ASTLocation(DLR.getDecl(), DLR.getStmt()); + return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl()); } -- 2.40.0