[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