[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