[cfe-commits] r68268 - in /cfe/trunk: include/clang/Frontend/FixItRewriter.h lib/Frontend/FixItRewriter.cpp lib/Parse/ParseInit.cpp lib/Sema/SemaDeclCXX.cpp test/Sema/fixit-c90.c test/Sema/fixit-errors.c test/Sema/fixit.c test/SemaCXX/fixit.cpp tools/clang-cc/clang-cc.cpp

Chris Lattner clattner at apple.com
Wed Apr 1 21:58:13 PDT 2009


On Apr 1, 2009, at 6:08 PM, Douglas Gregor wrote:
> Author: dgregor
> Date: Wed Apr  1 20:08:08 2009
> New Revision: 68268
>
> URL: http://llvm.org/viewvc/llvm-project?rev=68268&view=rev
> Log:
> Introduce a "-fixit" mode to clang-cc that applies code-modification  
> hints.

I was just going to say "we really need some way to test these fixit  
hints".  This is a great answer to that predictable request :)

> +++ cfe/trunk/lib/Frontend/FixItRewriter.cpp Wed Apr  1 20:08:08 2009
> @@ -0,0 +1,140 @@
> +//===--- FixItRewriter.cpp - Fix-It Rewriter Diagnostic Client --*-  
> C++ -*-===//
> +//
> +//                     The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open  
> Source
> +// License. See LICENSE.TXT for details.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +//
> +// This is a diagnostic client adaptor that performs rewrites as
> +// suggested by code modification hints attached to diagnostics. It
> +// then forwards any diagnostics to the adapted diagnostic client.
> +//
> +// 
> = 
> = 
> = 
> ----------------------------------------------------------------------= 
> ==//
> +#include "clang/Basic/SourceManager.h"
> +#include "clang/Frontend/FixItRewriter.h"

Please include FixItRewriter.h first, since this is the .cpp file that  
corresponds to it.  Also, a space between the header comment and first  
#include would be nice :)

> +bool FixItRewriter::WriteFixedFile(const std::string &InFileName,
> +                                   const std::string &OutFileName) {
> +
> +  llvm::OwningPtr<llvm::raw_ostream> OwnedStream;
> +  llvm::raw_ostream *OutFile;
> +  if (OutFileName == "-") {
> +    OutFile = &llvm::outs();
> +  } else if (!OutFileName.empty()) {
> +    std::string Err;
> +    OutFile = new llvm::raw_fd_ostream(OutFileName.c_str(),
> +                                       // set binary mode (critical  
> for Windoze)
> +                                       true,
> +                                       Err);

This ctor for raw_fd_ostream directly supports "-", so you can drop  
the first if.

> +  FileID MainFileID = Rewrite->getSourceMgr().getMainFileID();
> +  if (const RewriteBuffer *RewriteBuf =
> +        Rewrite->getRewriteBufferFor(MainFileID)) {
> +    *OutFile << std::string(RewriteBuf->begin(), RewriteBuf->end());
> +  } else {
> +    std::fprintf(stderr, "Main file is unchanged\n");

If the main file is unchanged, shouldn't this be unreached?

>
> +  }
> +  OutFile->flush();

Should OutFile be flushed or deleted here?  If OwnedStream will  
destroy it, then it doesn't need to be flushed.

> +void FixItRewriter::HandleDiagnostic(Diagnostic::Level DiagLevel,
> +                                     const DiagnosticInfo &Info) {
> +  if (Client)
> +    Client->HandleDiagnostic(DiagLevel, Info);
> +
> +  // Make sure that we can perform all of the modifications we
> +  // in this diagnostic.
> +  bool CanRewrite = true;
> +  for (unsigned Idx = 0; Idx < Info.getNumCodeModificationHints(); + 
> +Idx) {

Please don't call Info.getNumCodeModificationHints() each time through  
the loop :)

> +    const CodeModificationHint &Hint =  
> Info.getCodeModificationHint(Idx);
> +    if (Hint.RemoveRange.isValid() &&
> +        (!Rewrite->isRewritable(Hint.RemoveRange.getBegin()) ||
> +         !Rewrite->isRewritable(Hint.RemoveRange.getEnd()) ||
> +         Rewrite->getRangeSize(Hint.RemoveRange) == -1)) {

getRangeSize returns -1 if either of the start/end are not rewritable,  
so you can drop those checks.
> +    if (Hint.InsertionLoc.isValid() &&
> +        !Rewrite->isRewritable(Hint.InsertionLoc)) {
> +      CanRewrite = false;
> +      break;
> +    }
> +  }

What if an error diagnostic has no rewrite info?  Shouldn't that cause  
the fixit rewriter to refuse to apply any rewrites?

> +
> +  if (!CanRewrite) // FIXME: warn the user that this rewrite  
> couldn't be done
> +    return;
> +
> +  bool Failed = false;
> +  for (unsigned Idx = 0; Idx < Info.getNumCodeModificationHints(); + 
> +Idx) {

No need to call Info.getNumCodeModificationHints() each time through  
the loop.

> +    const CodeModificationHint &Hint =  
> Info.getCodeModificationHint(Idx);
> +    if (Hint.RemoveRange.isValid()) {

Please handle the !valid case first, allowing you to turn the rest  
into elseif chains and reduce indentation.

This is cool stuff Doug, very nice!

-Chris




More information about the cfe-commits mailing list