[cfe-dev] Segmentation fault while trying to replace text
Daniel QuiƱones Lopez
kaos09 at hotmail.com
Thu Oct 31 06:14:05 PDT 2013
Hello, trying to replace a text (spfically ":" at the beginning of an initialization list) when I run my program it causes a segmentation fault due to the marked line. The function "findSymbolAfterLocation" returns the right SourceLocation of the ":", but then it crashs. What surprises me is that it works fine in all the other cases, it finds the character I want to clear and does it. This is the source code:
class ConstructorInitializerDelete : public MatchFinder::MatchCallback {
public :
/// This function adapted from clang/lib/ARCMigrate/Transforms.cpp
/// If no symbol is found or the location is inside a macro, the returned
/// source location will be invalid.
SourceLocation findSymbolAfterLocation(SourceLocation loc, ASTContext* Ctx, char c) {
SourceManager &SM = Ctx->getSourceManager();
if (loc.isMacroID())
if (!Lexer::isAtEndOfMacroExpansion(loc, SM,Ctx->getLangOpts(), &loc))
return SourceLocation();
loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx->getLangOpts());
// Break down the source location.
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
// Try to load the file buffer.
bool invalidTemp = false;
StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp)
return SourceLocation();
const char *tokenBegin = file.data() + locInfo.second;
// Lex from the start of the given location.
Lexer lexer(SM.getLocForStartOfFile(locInfo.first),
Ctx->getLangOpts(),
file.begin(), tokenBegin, file.end());
Token tok;
lexer.LexFromRawLexer(tok);
switch (c){
case ',': if (tok.isNot(tok::comma))
return findSymbolAfterLocation(tok.getLocation(), Ctx, c);
break;
case ':': if (tok.isNot(tok::colon))
return findSymbolAfterLocation(tok.getLocation(), Ctx, c);
break;
case ';': if (tok.isNot(tok::semi))
return findSymbolAfterLocation(tok.getLocation(), Ctx, c);
break;
}
return tok.getLocation();
}
virtual void run(const MatchFinder::MatchResult &Result) {
ASTContext *Context = Result.Context;
const Stmt *FS1;
const CXXConstructorDecl *FS2;
if ((FS1 = Result.Nodes.getNodeAs<clang::Stmt>("CID1"))
|| (FS2 = Result.Nodes.getNodeAs<clang::CXXConstructorDecl>("CID2"))){
FullSourceLoc FullLocation;
if (FS1) {
FullLocation = Context->getFullLoc(FS1->getLocStart());
}
else if (FS2){
FullLocation = Context->getFullLoc(FS2->getLocStart());
}
if (FullLocation.isValid() && !Context->getSourceManager().isInSystemHeader(FullLocation)
&& !Context->getSourceManager().isInExternCSystemHeader(FullLocation)){
if (FS1){
FS1->dump();
}
else if (FS2){
FS2->dump();
}
llvm::outs() << "\nFound declaration at "
<< FullLocation.getSpellingLineNumber() << ":"
<< FullLocation.getSpellingColumnNumber() << "\n";
SourceRange r;
SourceLocation source;
if (FS1) {
r = FS1->getSourceRange();
char label[50];
sprintf(label, "//Deleted assignment operation");
Rewriter Rewrite;
Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
Rewrite.ReplaceText(r,label);
source = findSymbolAfterLocation(FS1->getLocStart(), Context, ';');
if((source.isValid()) && (source != FS1->getLocStart())){
Rewrite.ReplaceText(source,1,"");
}
const RewriteBuffer *RewriteBuf = Rewrite.getRewriteBufferFor(FullLocation.getFileID());
llvm::outs() << std::string(RewriteBuf->begin(), RewriteBuf->end());
}
else if (FS2){
for(CXXConstructorDecl::init_const_iterator i = FS2->init_begin(); i != FS2->init_end(); i++){
if (((*i)->isWritten()) && ((*i)->isMemberInitializer()) && (!(*i)->getMember()->getType().isConstQualified())){
char label[50];
r = (*i)->getSourceRange();
Rewriter Rewrite2;
// If there is a single initializer, clears ":"
if ((i == FS2->init_begin()) && (i+1 == FS2->init_end())){
unsigned nparam = FS2->getNumParams();
const ParmVarDecl* parm = FS2->getParamDecl(nparam-1);
----------------------------------------------------------------------------------------------
source = findSymbolAfterLocation(parm->getLocation(), Context, ':'); <- This line
----------------------------------------------------------------------------------------------
llvm::outs() << "\nsource: " << source.printToString(Context->getSourceManager()) << "\n";
if((source.isValid()) && (source != parm->getLocation()))
Rewrite2.ReplaceText(source,1,"");
}
sprintf(label,"//Deleted initializer");
Rewrite2.setSourceMgr(Context->getSourceManager(), Context->getLangOpts());
Rewrite2.ReplaceText(r,label);
// If it isn't the last initializer, clears the comma that follows
if (i+1 < FS2->init_end()){
source = findSymbolAfterLocation((*i)->getSourceLocation(), Context, ',');
if((source.isValid()) && (source != (*i)->getSourceLocation()))
Rewrite2.ReplaceText(source,1,"");
}
// If it is the last initializer and not the only, clears the comma that precedes
if ((i+1 == FS2->init_end()) && ((*i)->getSourceOrder() > 1)){
source = findSymbolAfterLocation((*(i-1))->getSourceLocation(), Context, ',');
if((source.isValid()) && (source != (*(i-1))->getSourceLocation()))
Rewrite2.ReplaceText(source,1,"");
}
const RewriteBuffer *RewriteBuf2 = Rewrite2.getRewriteBufferFor(FullLocation.getFileID());
llvm::outs() << std::string(RewriteBuf2->begin(), RewriteBuf2->end());
}
}
}
}
}
}
};
Can someone help me? Thanks.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20131031/b6c9792b/attachment.html>
More information about the cfe-dev
mailing list