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.getNodeAsclang::Stmt(“CID1”))
(FS2 = Result.Nodes.getNodeAsclang::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.