diff options
| author | Nick Lewycky <nicholas@mxc.ca> | 2010-04-24 01:30:46 +0000 | 
|---|---|---|
| committer | Nick Lewycky <nicholas@mxc.ca> | 2010-04-24 01:30:46 +0000 | 
| commit | 784fad7a4134c9504f7c3efa292e8a7b43155a2c (patch) | |
| tree | 9403fc2b930f161d3f736e2c8b06ecf50d851836 /clang/lib | |
| parent | 48ff3cf63bfa8019aca9b5df5f9fa496033c60cb (diff) | |
| download | bcm5719-llvm-784fad7a4134c9504f7c3efa292e8a7b43155a2c.tar.gz bcm5719-llvm-784fad7a4134c9504f7c3efa292e8a7b43155a2c.zip  | |
Teach clang -fixit to modify files in-place, or -fixit=suffix to create new
files with the additional suffix in the middle.
llvm-svn: 102230
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/Frontend/FixItRewriter.cpp | 64 | ||||
| -rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 90 | 
3 files changed, 40 insertions, 137 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 3386eff5bac..db937bc4c7a 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -361,12 +361,6 @@ static void FrontendOptsToArgs(const FrontendOptions &Opts,      Res.push_back("-cxx-inheritance-view");      Res.push_back(Opts.ViewClassInheritance);    } -  for (unsigned i = 0, e = Opts.FixItLocations.size(); i != e; ++i) { -    Res.push_back("-fixit-at"); -    Res.push_back(Opts.FixItLocations[i].FileName + ":" + -                  llvm::utostr(Opts.FixItLocations[i].Line) + ":" + -                  llvm::utostr(Opts.FixItLocations[i].Column)); -  }    if (!Opts.CodeCompletionAt.FileName.empty()) {      Res.push_back("-code-completion-at");      Res.push_back(Opts.CodeCompletionAt.FileName + ":" + @@ -910,6 +904,9 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) {        Opts.ProgramAction = frontend::EmitLLVMOnly; break;      case OPT_emit_obj:        Opts.ProgramAction = frontend::EmitObj; break; +    case OPT_fixit_EQ: +      Opts.FixItSuffix = A->getValue(Args); +      // fall-through!      case OPT_fixit:        Opts.ProgramAction = frontend::FixIt; break;      case OPT_emit_pch: @@ -956,20 +953,6 @@ ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Diagnostic &Diags) {      !Args.hasArg(OPT_no_code_completion_debug_printer);    Opts.DisableFree = Args.hasArg(OPT_disable_free); -  Opts.FixItLocations.clear(); -  for (arg_iterator it = Args.filtered_begin(OPT_fixit_at), -         ie = Args.filtered_end(); it != ie; ++it) { -    const char *Loc = it->getValue(Args); -    ParsedSourceLocation PSL = ParsedSourceLocation::FromString(Loc); - -    if (PSL.FileName.empty()) { -      Diags.Report(diag::err_drv_invalid_value) << it->getAsString(Args) << Loc; -      continue; -    } - -    Opts.FixItLocations.push_back(PSL); -  } -    Opts.OutputFile = getLastArgValue(Args, OPT_o);    Opts.Plugins = getAllArgValues(Args, OPT_load);    Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch); diff --git a/clang/lib/Frontend/FixItRewriter.cpp b/clang/lib/Frontend/FixItRewriter.cpp index 7aff92340ea..cb2b44a0272 100644 --- a/clang/lib/Frontend/FixItRewriter.cpp +++ b/clang/lib/Frontend/FixItRewriter.cpp @@ -26,8 +26,12 @@  using namespace clang;  FixItRewriter::FixItRewriter(Diagnostic &Diags, SourceManager &SourceMgr, -                             const LangOptions &LangOpts) -  : Diags(Diags), Rewrite(SourceMgr, LangOpts), NumFailures(0) { +                             const LangOptions &LangOpts, +                             FixItPathRewriter *PathRewriter) +  : Diags(Diags), +    Rewrite(SourceMgr, LangOpts), +    PathRewriter(PathRewriter), +    NumFailures(0) {    Client = Diags.getClient();    Diags.setClient(this);  } @@ -52,15 +56,15 @@ bool FixItRewriter::WriteFixedFiles() {    for (iterator I = buffer_begin(), E = buffer_end(); I != E; ++I) {      const FileEntry *Entry = Rewrite.getSourceMgr().getFileEntryForID(I->first); -    llvm::sys::Path Path(Entry->getName()); -    std::string Suffix = Path.getSuffix(); -    Path.eraseSuffix(); -    Path.appendSuffix("fixit." + Suffix); +    std::string Filename = Entry->getName(); +    if (PathRewriter) +      Filename = PathRewriter->RewriteFilename(Filename);      std::string Err; -    llvm::raw_fd_ostream OS(Path.c_str(), Err, llvm::raw_fd_ostream::F_Binary); +    llvm::raw_fd_ostream OS(Filename.c_str(), Err, +                            llvm::raw_fd_ostream::F_Binary);      if (!Err.empty()) {        Diags.Report(clang::diag::err_fe_unable_to_open_output) -          << Path.c_str() << Err; +          << Filename << Err;        continue;      }      RewriteBuffer &RewriteBuf = I->second; @@ -79,48 +83,10 @@ void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,                                       const DiagnosticInfo &Info) {    Client->HandleDiagnostic(DiagLevel, Info); -  // Skip over any diagnostics that are ignored. -  if (DiagLevel == Diagnostic::Ignored) +  // Skip over any diagnostics that are ignored or notes. +  if (DiagLevel <= Diagnostic::Note)      return; -  const SourceManager &SM = Rewrite.getSourceMgr(); -  if (!FixItLocations.empty()) { -    // The user has specified the locations where we should perform -    // the various fix-it modifications. - -    // If this diagnostic does not have any code modifications, -    // completely ignore it, even if it's an error: fix-it locations -    // are meant to perform specific fix-ups even in the presence of -    // other errors. -    if (Info.getNumFixItHints() == 0) -      return; - -    // See if the location of the error is one that matches what the -    // user requested. -    bool AcceptableLocation = false; -    const FileEntry *File = SM.getFileEntryForID( -                                                Info.getLocation().getFileID()); -    unsigned Line = Info.getLocation().getSpellingLineNumber(); -    unsigned Column = Info.getLocation().getSpellingColumnNumber(); -    for (llvm::SmallVector<RequestedSourceLocation, 4>::iterator -           Loc = FixItLocations.begin(), LocEnd = FixItLocations.end(); -         Loc != LocEnd; ++Loc) { -      if (Loc->File == File && -          ((Loc->Line == 0 && Loc->Column == 0 && -            DiagLevel > Diagnostic::Note) || -           (Loc->Line == Line && Loc->Column == Column))) { -        AcceptableLocation = true; -        break; -      } -    } - -    if (!AcceptableLocation) -      return; -  } else if (DiagLevel == Diagnostic::Note) { -    // Don't apply fix-it modifications in notes. -    return; -  } -    // Make sure that we can perform all of the modifications we    // in this diagnostic.    bool CanRewrite = Info.getNumFixItHints() > 0; @@ -197,3 +163,5 @@ void FixItRewriter::Diag(FullSourceLoc Loc, unsigned DiagID) {    Diags.Report(Loc, DiagID);    Diags.setClient(this);  } + +FixItPathRewriter::~FixItPathRewriter() {} diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index e2b2fd7deb3..6cd960be20d 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -19,6 +19,7 @@  #include "clang/Frontend/FixItRewriter.h"  #include "clang/Frontend/FrontendDiagnostic.h"  #include "clang/Frontend/Utils.h" +#include "llvm/ADT/OwningPtr.h"  #include "llvm/Support/raw_ostream.h"  using namespace clang; @@ -113,85 +114,36 @@ ASTConsumer *FixItAction::CreateASTConsumer(CompilerInstance &CI,    return new ASTConsumer();  } -/// AddFixItLocations - Add any individual user specified "fix-it" locations, -/// and return true on success. -static bool AddFixItLocations(CompilerInstance &CI, -                              FixItRewriter &FixItRewrite) { -  const std::vector<ParsedSourceLocation> &Locs = -    CI.getFrontendOpts().FixItLocations; -  for (unsigned i = 0, e = Locs.size(); i != e; ++i) { -    const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName); -    if (!File) { -      CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file) -        << Locs[i].FileName; -      return false; -    } - -    RequestedSourceLocation Requested; -    Requested.File = File; -    Requested.Line = Locs[i].Line; -    Requested.Column = Locs[i].Column; -    FixItRewrite.addFixItLocation(Requested); -  } +class FixItActionSuffixInserter : public FixItPathRewriter { +  std::string NewSuffix; -  const std::string &OutputFile = CI.getFrontendOpts().OutputFile; -  if (Locs.empty() && !OutputFile.empty()) { -    // FIXME: we will issue "FIX-IT applied suggested code changes" for every -    // input, but only the main file will actually be rewritten. -    const std::vector<std::pair<FrontendOptions::InputKind, std::string> > &Inputs = -      CI.getFrontendOpts().Inputs; -    for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { -      const FileEntry *File = CI.getFileManager().getFile(Inputs[i].second); -      assert(File && "Input file not found in FileManager"); -      RequestedSourceLocation Requested; -      Requested.File = File; -      Requested.Line = 0; -      Requested.Column = 0; -      FixItRewrite.addFixItLocation(Requested); -    } -  } +public: +  explicit FixItActionSuffixInserter(std::string NewSuffix) +    : NewSuffix(NewSuffix) {} -  return true; -} +  std::string RewriteFilename(const std::string &Filename) { +    llvm::sys::Path Path(Filename); +    std::string Suffix = Path.getSuffix(); +    Path.eraseSuffix(); +    Path.appendSuffix(NewSuffix + "." + Suffix); +    return Path.c_str(); +  } +};  bool FixItAction::BeginSourceFileAction(CompilerInstance &CI,                                          llvm::StringRef Filename) { +  const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); +  if (!FEOpts.FixItSuffix.empty()) { +    PathRewriter.reset(new FixItActionSuffixInserter(FEOpts.FixItSuffix)); +  } else { +    PathRewriter.reset(); +  }    Rewriter.reset(new FixItRewriter(CI.getDiagnostics(), CI.getSourceManager(), -                                   CI.getLangOpts())); -  if (!AddFixItLocations(CI, *Rewriter)) -    return false; - +                                   CI.getLangOpts(), PathRewriter.get()));    return true;  }  void FixItAction::EndSourceFileAction() { -  const FrontendOptions &FEOpts = getCompilerInstance().getFrontendOpts(); -  if (!FEOpts.OutputFile.empty()) { -    // When called with 'clang -fixit -o filename' output only the main file. - -    const SourceManager &SM = getCompilerInstance().getSourceManager(); -    FileID MainFileID = SM.getMainFileID(); -    if (!Rewriter->IsModified(MainFileID)) { -      getCompilerInstance().getDiagnostics().Report( -          diag::note_fixit_main_file_unchanged); -      return; -    } - -    llvm::OwningPtr<llvm::raw_ostream> OwnedStream; -    llvm::raw_ostream *OutFile; -    if (FEOpts.OutputFile == "-") { -      OutFile = &llvm::outs(); -    } else { -      std::string Err; -      OutFile = new llvm::raw_fd_ostream(FEOpts.OutputFile.c_str(), Err, -                                         llvm::raw_fd_ostream::F_Binary); -      OwnedStream.reset(OutFile); -    } - -    Rewriter->WriteFixedFile(MainFileID, *OutFile); -    return; -  } -    // Otherwise rewrite all files.    Rewriter->WriteFixedFiles();  }  | 

