]> granicus.if.org Git - clang/commitdiff
Refactor DeclLocResolver/StmtLocResolver into a more functional style by removing...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 7 Jul 2009 00:53:31 +0000 (00:53 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Tue, 7 Jul 2009 00:53:31 +0000 (00:53 +0000)
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

index b9df7029048e2e7bb2967cf141bcdf535bc23186..e27e9bce4fb98ceae607d10d5f0b3d89df75e8a1 100644 (file)
@@ -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<Decl *, Stmt *> 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<StmtLocResolver> {
+                                          public StmtVisitor<StmtLocResolver,
+                                                             ASTLocation     > {
+  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<DeclLocResolver> {
+                                          public DeclVisitor<DeclLocResolver,
+                                                             ASTLocation     > {
 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<ParmVarDecl>(*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());
 }