[cfe-commits] r74197 - in /cfe/trunk: include/clang/Frontend/Utils.h lib/Frontend/CMakeLists.txt lib/Frontend/ResolveLocation.cpp

Argyrios Kyrtzidis kyrtzidis at apple.com
Thu Jun 25 16:05:45 PDT 2009


On Jun 25, 2009, at 3:36 PM, Douglas Gregor wrote:

>
> Okay, so the scheme here is: check whether the source location we're
> looking for is within the range of the current node. If so, recurse to
> find which sub-node it is in. I like that, although the CheckRange/
> FoundIt/Finished trio feels more complicated that it needs to be,
> because there's a lot of state encoded in Dcl/Stm/PassedLoc. Why not
> just have your Visit functions return std::pair<Decl*, Stmt*> (or
> something like it?).

I initially had them returning a class with Decl, Stmt, bool  
(PassedLoc), but I eventually moved that state into the LocResolver  
class to avoid constantly passing the (mostly same) structure amongst  
the visitor methods.
I don't have a strong opinion though, let me know if you think  
returning the state from the visitor methods is better.

-Argiris

>
>> +void DeclLocResolver::VisitDeclContext(DeclContext *DC) {
>> +  DeclLocResolver DLR(Ctx, Loc);
>> +  for (DeclContext::decl_iterator
>> +         I = DC->decls_begin(Ctx), E = DC->decls_end(Ctx); I != E; +
>> +I) {
>> +    DLR.Visit(*I);
>> +    if (DLR.Finished()) {
>> +      if (DLR.FoundIt())
>> +        llvm::tie(Dcl, Stm) = DLR.getResult();
>> +      return;
>> +    }
>> +  }
>> +}
>> +
>> +void DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl
>> *TU) {
>> +  VisitDeclContext(TU);
>> +}
>> +
>> +void DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
>> +  CheckRange(D);
>> +  if (!FoundIt())
>> +    return;
>> +  assert(Dcl == D && "Result not updated ?");
>> +
>> +  // 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;
>> +    }
>> +  }
>
> Okay, looks good.
>
>> +  // We didn't found the location in the parameters and we didn't
>> get passed it.
>> +
>> +  // 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);
>> +  DLR.VisitDeclContext(D);
>> +  if (DLR.FoundIt()) {
>> +    llvm::tie(Dcl, Stm) = DLR.getResult();
>> +    return;
>> +  }
>> +
>> +  // We didn't find a declaration that corresponds to the source
>> location.
>> +
>> +  // Finally, search through the body of the function.
>> +  if (D->isThisDeclarationADefinition()) {
>> +    StmtLocResolver SLR(Ctx, Loc);
>> +    SLR.Visit(D->getBody(Ctx));
>> +    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;
>> +    }
>> +  }
>> +}
>> +
>> +void DeclLocResolver::VisitVarDecl(VarDecl *D) {
>> +  CheckRange(D);
>> +  if (!FoundIt())
>> +    return;
>> +  assert(Dcl == D && "Result not updated ?");
>> +
>> +  // Check whether the location points to the init expression.
>> +  if (D->getInit()) {
>> +    StmtLocResolver SLR(Ctx, Loc);
>> +    SLR.Visit(D->getInit());
>> +    Stm = SLR.getStmt();
>> +  }
>> +}
>> +
>> +void DeclLocResolver::VisitDecl(Decl *D) {
>> +  CheckRange(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;
>> +}
>> +
>> +void LocResolverBase::CheckRange(Stmt *Node) {
>> +  SourceRange Range = Node->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
>> +    Stm = Node;
>> +}
>> +
>> +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));
>> +}
>> +
>> +void LocResolverBase::print(Decl *D) {
>> +  llvm::raw_ostream &OS = llvm::outs();
>> +  OS << "#### DECL ####\n";
>> +  D->print(OS, Ctx);
>> +  OS << " <";
>> +  D->getLocStart().print(OS, Ctx.getSourceManager());
>> +  OS << " > - <";
>> +  D->getLocEnd().print(OS, Ctx.getSourceManager());
>> +  OS << ">\n\n";
>> +  OS.flush();
>> +}
>> +
>> +void LocResolverBase::print(Stmt *Node) {
>> +  llvm::raw_ostream &OS = llvm::outs();
>> +  OS << "#### STMT ####\n";
>> +  Node->printPretty(OS, Ctx);
>> +  OS << " <";
>> +  Node->getLocStart().print(OS, Ctx.getSourceManager());
>> +  OS << " > - <";
>> +  Node->getLocEnd().print(OS, Ctx.getSourceManager());
>> +  OS << ">\n\n";
>> +  OS.flush();
>> +}
>> +
>> +
>> +/// \brief Returns the AST node that a source location points to.
>> +///
>> +std::pair<Decl *, Stmt *>
>> +clang::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) {
>> +  if (Loc.isInvalid())
>> +    return std::make_pair((Decl*)0, (Stmt*)0);
>> +
>> +  DeclLocResolver DLR(Ctx, Loc);
>> +  DLR.Visit(Ctx.getTranslationUnitDecl());
>> +  return DLR.getResult();
>> +}
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list