[LLVMbugs] [Bug 12487] New: Stmt::getLocEnd() behaviour

bugzilla-daemon at llvm.org bugzilla-daemon at llvm.org
Fri Apr 6 16:22:10 PDT 2012


http://llvm.org/bugs/show_bug.cgi?id=12487

             Bug #: 12487
           Summary: Stmt::getLocEnd() behaviour
           Product: clang
           Version: trunk
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: C++
        AssignedTo: unassignedclangbugs at nondot.org
        ReportedBy: rrankene at gmail.com
                CC: dgregor at apple.com, llvmbugs at cs.uiuc.edu
    Classification: Unclassified


I've been playing with Clang to see what it can do, and thinking of
writing a Rewriter tutorial.  I was thinking of rewriting statements
of the form:
  if (expr)
    stmt;
to:
  if (expr)
  {
     stmt;
  }
as a way to enforce some coding standards I've seen.  I coupled a
RecursiveASTVisitor with a rewriter, and when visiting an IfStmt or WhileStmt,
I
expected getLocEnd() to point at the end of the if statement.  What I
get instead is somewhere inside the stmt.  Is that expected behaviour?
 For example with the following input file test1.c:
int i = 4;
int j = 0;

int main()
{
 if (i < 4)
    j++;

 while (i < 6)
    i++;

 return 0;
}

I get the output:
int i = 4;
int j = 0;

int main()
{
 <Start If>if (i < 4)
    j<End If>++;

 <Start While>while (i < 6)
    i<End While>++;

 return 0;
}

so that the getLocEnd points to before the ++ operator.
The code I used was:
#include <iostream>

#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

#include "clang/Frontend/CompilerInstance.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Parse/ParseAST.h"
#include "clang/Rewrite/Rewriters.h"
#include "clang/Rewrite/Rewriter.h"

clang::Rewriter Rewrite;

// RecursiveASTVisitor is is the big-kahuna visitor that traverses
// everything in the AST.
class MyRecursiveASTVisitor
   : public clang::RecursiveASTVisitor<MyRecursiveASTVisitor>
{
 public:
 bool VisitStmt(clang::Stmt *s);
};


// Override Statements which includes expressions and more
bool MyRecursiveASTVisitor::VisitStmt(clang::Stmt *s)
{
 if (clang::isa<clang::IfStmt>(s))
 {
   Rewrite.InsertText(s->getLocStart(), "<Start If>", true, true);
   Rewrite.InsertText(s->getLocEnd(), "<End If>", true, true);
 }
 else
 if (clang::isa<clang::WhileStmt>(s))
 {
   Rewrite.InsertText(s->getLocStart(), "<Start While>", true, true);
   Rewrite.InsertText(s->getLocEnd(), "<End While>", true, true);
 }

 return true; // returning false aborts the traversal
}

class MyASTConsumer : public clang::ASTConsumer
{
 public:
   virtual bool HandleTopLevelDecl(clang::DeclGroupRef d);
};


bool MyASTConsumer::HandleTopLevelDecl(clang::DeclGroupRef d)
{
 MyRecursiveASTVisitor rv;
 typedef clang::DeclGroupRef::iterator iter;

 for (iter b = d.begin(), e = d.end(); b != e; ++b) {
   rv.TraverseDecl(*b);
 }

 return true; // keep going
}


int main()
{
 using clang::CompilerInstance;
 using clang::TargetOptions;
 using clang::TargetInfo;
 using clang::FileEntry;

 CompilerInstance ci;
 ci.createDiagnostics(0,NULL);

 TargetOptions to;
 to.Triple = llvm::sys::getDefaultTargetTriple();
 TargetInfo *pti = TargetInfo::CreateTargetInfo(ci.getDiagnostics(), to);
 ci.setTarget(pti);

 ci.createFileManager();
 ci.createSourceManager(ci.getFileManager());
 ci.createPreprocessor();
 ci.getPreprocessorOpts().UsePredefines = false;
 MyASTConsumer *astConsumer = new MyASTConsumer();
 ci.setASTConsumer(astConsumer);

 ci.createASTContext();

 // Initialize rewriter
 Rewrite.setSourceMgr(ci.getSourceManager(), ci.getLangOpts());

 const FileEntry *pFile = ci.getFileManager().getFile("test1.c");
 ci.getSourceManager().createMainFileID(pFile);
 ci.getDiagnosticClient().BeginSourceFile(ci.getLangOpts(),
                                          &ci.getPreprocessor());
 clang::ParseAST(ci.getPreprocessor(), astConsumer, ci.getASTContext());
 ci.getDiagnosticClient().EndSourceFile();

 // Now output rewritten source code
 const clang::RewriteBuffer *RewriteBuf =
          Rewrite.getRewriteBufferFor(ci.getSourceManager().getMainFileID());
 llvm::errs() << std::string(RewriteBuf->begin(), RewriteBuf->end());

 return 0;
}

As a side-note, if I move the statement:
CompilerInstance ci;
outside of main (i.e. under clang::Rewriter Rewrite;), on exit I get the
following error:
pure virtual method called
terminate called without an active exception
Segmentation fault

Robert Ankeney

-- 
Configure bugmail: http://llvm.org/bugs/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



More information about the llvm-bugs mailing list