[cfe-commits] r135491 - in /cfe/trunk: include/clang/ARCMigrate/ARCMT.h include/clang/ARCMigrate/ARCMTActions.h include/clang/Driver/CC1Options.td include/clang/Driver/Options.td include/clang/Frontend/FrontendOptions.h lib/ARCMigrate/ARCMT.cpp lib/ARCMigrate/ARCMTActions.cpp lib/ARCMigrate/Internals.h lib/ARCMigrate/PlistReporter.cpp lib/Driver/Tools.cpp lib/Frontend/CompilerInvocation.cpp lib/FrontendTool/ExecuteCompilerInvocation.cpp test/ARCMT/migrate-emit-errors.m test/ARCMT/migrate-plist-output.m

Argyrios Kyrtzidis akyrtzi at gmail.com
Tue Jul 19 10:20:03 PDT 2011


Author: akirtzidis
Date: Tue Jul 19 12:20:03 2011
New Revision: 135491

URL: http://llvm.org/viewvc/llvm-project?rev=135491&view=rev
Log:
[arcmt] Add some additional driver flags to optionally emit or save the pre-migration ARC errors.

-arcmt-migrate-emit-errors : Emits the pre-migration ARC errors but it doesn't affect anything else
-arcmt-migrate-report-output : Writes out the pre-migration ARC errors to the provided plist file

rdar://9791454

Added:
    cfe/trunk/lib/ARCMigrate/PlistReporter.cpp
    cfe/trunk/test/ARCMT/migrate-emit-errors.m
    cfe/trunk/test/ARCMT/migrate-plist-output.m
Modified:
    cfe/trunk/include/clang/ARCMigrate/ARCMT.h
    cfe/trunk/include/clang/ARCMigrate/ARCMTActions.h
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/include/clang/Frontend/FrontendOptions.h
    cfe/trunk/lib/ARCMigrate/ARCMT.cpp
    cfe/trunk/lib/ARCMigrate/ARCMTActions.cpp
    cfe/trunk/lib/ARCMigrate/Internals.h
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp
    cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp

Modified: cfe/trunk/include/clang/ARCMigrate/ARCMT.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ARCMigrate/ARCMT.h?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/include/clang/ARCMigrate/ARCMT.h (original)
+++ cfe/trunk/include/clang/ARCMigrate/ARCMT.h Tue Jul 19 12:20:03 2011
@@ -28,10 +28,19 @@
 /// It then checks the AST and produces errors/warning for ARC migration issues
 /// that the user needs to handle manually.
 ///
+/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
+/// even if the migrator can fix them, but the function will still return false
+/// if all ARC errors can be fixed.
+///
+/// \param plistOut if non-empty, it is the file path to store the plist with
+/// the pre-migration ARC diagnostics.
+///
 /// \returns false if no error is produced, true otherwise.
 bool checkForManualIssues(CompilerInvocation &CI,
                           llvm::StringRef Filename, InputKind Kind,
-                          DiagnosticClient *DiagClient);
+                          DiagnosticClient *DiagClient,
+                          bool emitPremigrationARCErrors = false,
+                          llvm::StringRef plistOut = llvm::StringRef());
 
 /// \brief Works similar to checkForManualIssues but instead of checking, it
 /// applies automatic modifications to source files to conform to ARC.
@@ -44,11 +53,20 @@
 /// \brief Applies automatic modifications and produces temporary files
 /// and metadata into the \arg outputDir path.
 ///
+/// \param emitPremigrationARCErrors if true all ARC errors will get emitted
+/// even if the migrator can fix them, but the function will still return false
+/// if all ARC errors can be fixed.
+///
+/// \param plistOut if non-empty, it is the file path to store the plist with
+/// the pre-migration ARC diagnostics.
+///
 /// \returns false if no error is produced, true otherwise.
 bool migrateWithTemporaryFiles(CompilerInvocation &origCI,
                                llvm::StringRef Filename, InputKind Kind,
                                DiagnosticClient *DiagClient,
-                               llvm::StringRef outputDir);
+                               llvm::StringRef outputDir,
+                               bool emitPremigrationARCErrors,
+                               llvm::StringRef plistOut);
 
 /// \brief Get the set of file remappings from the \arg outputDir path that
 /// migrateWithTemporaryFiles produced.

Modified: cfe/trunk/include/clang/ARCMigrate/ARCMTActions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/ARCMigrate/ARCMTActions.h?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/include/clang/ARCMigrate/ARCMTActions.h (original)
+++ cfe/trunk/include/clang/ARCMigrate/ARCMTActions.h Tue Jul 19 12:20:03 2011
@@ -34,11 +34,15 @@
 
 class MigrateAction : public WrapperFrontendAction {
   std::string MigrateDir;
+  std::string PlistOut;
+  bool EmitPremigrationARCErros;
 protected:
   virtual bool BeginInvocation(CompilerInstance &CI);
 
 public:
-  MigrateAction(FrontendAction *WrappedAction, llvm::StringRef migrateDir);
+  MigrateAction(FrontendAction *WrappedAction, llvm::StringRef migrateDir,
+                llvm::StringRef plistOut,
+                bool emitPremigrationARCErrors);
 };
 
 }

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Tue Jul 19 12:20:03 2011
@@ -394,6 +394,10 @@
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
 def arcmt_migrate_directory : Separate<"-arcmt-migrate-directory">,
   HelpText<"Directory for temporary files produced during ARC migration">;
+def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
+  HelpText<"Output path for the plist report">;
+def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
+  HelpText<"Emit ARC errors even if the migrator can fix them">;
 
 def import_module : Separate<"-import-module">,
   HelpText<"Import a module definition file">;

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Tue Jul 19 12:20:03 2011
@@ -122,6 +122,10 @@
   HelpText<"Apply modifications and produces temporary files that conform to ARC">;
 def ccc_arcmt_migrate_EQ : Joined<"-ccc-arcmt-migrate=">, CCCDriverOpt,
   Alias<ccc_arcmt_migrate>;
+def arcmt_migrate_report_output : Separate<"-arcmt-migrate-report-output">,
+  HelpText<"Output path for the plist report">;
+def arcmt_migrate_emit_arc_errors : Flag<"-arcmt-migrate-emit-errors">,
+  HelpText<"Emit ARC errors even if the migrator can fix them">;
 
 // Make sure all other -ccc- options are rejected.
 def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;

Modified: cfe/trunk/include/clang/Frontend/FrontendOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/FrontendOptions.h?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/include/clang/Frontend/FrontendOptions.h (original)
+++ cfe/trunk/include/clang/Frontend/FrontendOptions.h Tue Jul 19 12:20:03 2011
@@ -75,6 +75,8 @@
   unsigned ShowVersion : 1;                ///< Show the -version text.
   unsigned FixWhatYouCan : 1;              ///< Apply fixes even if there are
                                            /// unfixable errors.
+  unsigned ARCMTMigrateEmitARCErrors : 1;  /// Emit ARC errors even if the
+                                           /// migrator can fix them
 
   enum {
     ARCMT_None,
@@ -84,6 +86,7 @@
   } ARCMTAction;
 
   std::string ARCMTMigrateDir;
+  std::string ARCMTMigrateReportOut;
 
   /// The input files and their types.
   std::vector<std::pair<InputKind, std::string> > Inputs;
@@ -140,6 +143,7 @@
     ShowTimers = 0;
     ShowVersion = 0;
     ARCMTAction = ARCMT_None;
+    ARCMTMigrateEmitARCErrors = 0;
   }
 
   /// getInputKindForExtension - Return the appropriate input kind for a file

Modified: cfe/trunk/lib/ARCMigrate/ARCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ARCMT.cpp?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ARCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ARCMT.cpp Tue Jul 19 12:20:03 2011
@@ -10,6 +10,7 @@
 #include "Internals.h"
 #include "clang/Frontend/ASTUnit.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
 #include "clang/Frontend/Utils.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/Rewrite/Rewriter.h"
@@ -194,13 +195,29 @@
   return CInvok.take();
 }
 
+void emitPremigrationErrors(const CapturedDiagList &arcDiags,
+                            const DiagnosticOptions &diagOpts,
+                            Preprocessor &PP) {
+  TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
+  llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
+                   new Diagnostic(DiagID, &printer, /*ShouldOwnClient=*/false));
+  Diags->setSourceManager(&PP.getSourceManager());
+  
+  printer.BeginSourceFile(PP.getLangOptions(), &PP);
+  arcDiags.reportDiagnostics(*Diags);
+  printer.EndSourceFile();
+}
+
 //===----------------------------------------------------------------------===//
 // checkForManualIssues.
 //===----------------------------------------------------------------------===//
 
 bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
                                  llvm::StringRef Filename, InputKind Kind,
-                                 DiagnosticClient *DiagClient) {
+                                 DiagnosticClient *DiagClient,
+                                 bool emitPremigrationARCErrors,
+                                 llvm::StringRef plistOut) {
   if (!origCI.getLangOpts().ObjC1)
     return false;
 
@@ -241,6 +258,18 @@
     return true;
   }
 
+  if (emitPremigrationARCErrors)
+    emitPremigrationErrors(capturedDiags, origCI.getDiagnosticOpts(),
+                           Unit->getPreprocessor());
+  if (!plistOut.empty()) {
+    llvm::SmallVector<StoredDiagnostic, 8> arcDiags;
+    for (CapturedDiagList::iterator
+           I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
+      arcDiags.push_back(*I);
+    writeARCDiagsToPlist(plistOut, arcDiags,
+                         Ctx.getSourceManager(), Ctx.getLangOptions());
+  }
+
   // After parsing of source files ended, we want to reuse the
   // diagnostics objects to emit further diagnostics.
   // We call BeginSourceFile because DiagnosticClient requires that 
@@ -276,13 +305,16 @@
 static bool applyTransforms(CompilerInvocation &origCI,
                             llvm::StringRef Filename, InputKind Kind,
                             DiagnosticClient *DiagClient,
-                            llvm::StringRef outputDir) {
+                            llvm::StringRef outputDir,
+                            bool emitPremigrationARCErrors,
+                            llvm::StringRef plistOut) {
   if (!origCI.getLangOpts().ObjC1)
     return false;
 
   // Make sure checking is successful first.
   CompilerInvocation CInvokForCheck(origCI);
-  if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient))
+  if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient,
+                                  emitPremigrationARCErrors, plistOut))
     return true;
 
   CompilerInvocation CInvok(origCI);
@@ -317,15 +349,19 @@
 bool arcmt::applyTransformations(CompilerInvocation &origCI,
                                  llvm::StringRef Filename, InputKind Kind,
                                  DiagnosticClient *DiagClient) {
-  return applyTransforms(origCI, Filename, Kind, DiagClient, llvm::StringRef());
+  return applyTransforms(origCI, Filename, Kind, DiagClient,
+                         llvm::StringRef(), false, llvm::StringRef());
 }
 
 bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
                                       llvm::StringRef Filename, InputKind Kind,
                                       DiagnosticClient *DiagClient,
-                                      llvm::StringRef outputDir) {
+                                      llvm::StringRef outputDir,
+                                      bool emitPremigrationARCErrors,
+                                      llvm::StringRef plistOut) {
   assert(!outputDir.empty() && "Expected output directory path");
-  return applyTransforms(origCI, Filename, Kind, DiagClient, outputDir);
+  return applyTransforms(origCI, Filename, Kind, DiagClient,
+                         outputDir, emitPremigrationARCErrors, plistOut);
 }
 
 bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &

Modified: cfe/trunk/lib/ARCMigrate/ARCMTActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ARCMTActions.cpp?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ARCMTActions.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ARCMTActions.cpp Tue Jul 19 12:20:03 2011
@@ -38,16 +38,26 @@
   : WrapperFrontendAction(WrappedAction) {}
 
 bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
-  return !arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
+  if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
                                            getCurrentFile(),
                                            getCurrentFileKind(),
                                            CI.getDiagnostics().getClient(),
-                                           MigrateDir);
+                                           MigrateDir,
+                                           EmitPremigrationARCErros,
+                                           PlistOut))
+    return false; // errors, stop the action.
+
+  // We only want to see diagnostics emitted by migrateWithTemporaryFiles.
+  CI.getDiagnostics().setIgnoreAllWarnings(true);
+  return true;
 }
 
 MigrateAction::MigrateAction(FrontendAction *WrappedAction,
-                             llvm::StringRef migrateDir)
-  : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir) {
+                             llvm::StringRef migrateDir,
+                             llvm::StringRef plistOut,
+                             bool emitPremigrationARCErrors)
+  : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
+    PlistOut(plistOut), EmitPremigrationARCErros(emitPremigrationARCErrors) {
   if (MigrateDir.empty())
     MigrateDir = "."; // user current directory if none is given.
 }

Modified: cfe/trunk/lib/ARCMigrate/Internals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/Internals.h?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/Internals.h (original)
+++ cfe/trunk/lib/ARCMigrate/Internals.h Tue Jul 19 12:20:03 2011
@@ -32,8 +32,16 @@
   void reportDiagnostics(Diagnostic &diags) const;
 
   bool hasErrors() const;
+
+  typedef ListTy::const_iterator iterator;
+  iterator begin() const { return List.begin(); }
+  iterator end()   const { return List.end();   }
 };
 
+void writeARCDiagsToPlist(const std::string &outPath,
+                          llvm::ArrayRef<StoredDiagnostic> diags,
+                          SourceManager &SM, const LangOptions &LangOpts);
+
 class TransformActions {
   Diagnostic &Diags;
   CapturedDiagList &CapturedDiags;

Added: cfe/trunk/lib/ARCMigrate/PlistReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/PlistReporter.cpp?rev=135491&view=auto
==============================================================================
--- cfe/trunk/lib/ARCMigrate/PlistReporter.cpp (added)
+++ cfe/trunk/lib/ARCMigrate/PlistReporter.cpp Tue Jul 19 12:20:03 2011
@@ -0,0 +1,197 @@
+//===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Internals.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+
+using namespace clang;
+using namespace arcmt;
+using llvm::StringRef;
+
+// FIXME: This duplicates significant functionality from PlistDiagnostics.cpp,
+// it would be jolly good if there was a reusable PlistWriter or something.
+
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+static void AddFID(FIDMap &FIDs, llvm::SmallVectorImpl<FileID> &V,
+                   const SourceManager &SM, SourceLocation L) {
+
+  FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
+  FIDMap::iterator I = FIDs.find(FID);
+  if (I != FIDs.end()) return;
+  FIDs[FID] = V.size();
+  V.push_back(FID);
+}
+
+static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
+                       SourceLocation L) {
+  FileID FID = SM.getFileID(SM.getInstantiationLoc(L));
+  FIDMap::const_iterator I = FIDs.find(FID);
+  assert(I != FIDs.end());
+  return I->second;
+}
+
+static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
+  for (unsigned i = 0; i < indent; ++i) o << ' ';
+  return o;
+}
+
+static void EmitLocation(llvm::raw_ostream& o, const SourceManager &SM,
+                         const LangOptions &LangOpts,
+                         SourceLocation L, const FIDMap &FM,
+                         unsigned indent, bool extend = false) {
+
+  FullSourceLoc Loc(SM.getInstantiationLoc(L), const_cast<SourceManager&>(SM));
+
+  // Add in the length of the token, so that we cover multi-char tokens.
+  unsigned offset =
+    extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
+
+  Indent(o, indent) << "<dict>\n";
+  Indent(o, indent) << " <key>line</key><integer>"
+                    << Loc.getInstantiationLineNumber() << "</integer>\n";
+  Indent(o, indent) << " <key>col</key><integer>"
+                    << Loc.getInstantiationColumnNumber() + offset << "</integer>\n";
+  Indent(o, indent) << " <key>file</key><integer>"
+                    << GetFID(FM, SM, Loc) << "</integer>\n";
+  Indent(o, indent) << "</dict>\n";
+}
+
+static void EmitRange(llvm::raw_ostream& o, const SourceManager &SM,
+                      const LangOptions &LangOpts,
+                      CharSourceRange R, const FIDMap &FM,
+                      unsigned indent) {
+  Indent(o, indent) << "<array>\n";
+  EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
+  EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, R.isTokenRange());
+  Indent(o, indent) << "</array>\n";
+}
+
+static llvm::raw_ostream& EmitString(llvm::raw_ostream& o,
+                                     StringRef s) {
+  o << "<string>";
+  for (StringRef::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
+    char c = *I;
+    switch (c) {
+    default:   o << c; break;
+    case '&':  o << "&"; break;
+    case '<':  o << "<"; break;
+    case '>':  o << ">"; break;
+    case '\'': o << "'"; break;
+    case '\"': o << """; break;
+    }
+  }
+  o << "</string>";
+  return o;
+}
+
+void arcmt::writeARCDiagsToPlist(const std::string &outPath,
+                                 llvm::ArrayRef<StoredDiagnostic> diags,
+                                 SourceManager &SM,
+                                 const LangOptions &LangOpts) {
+  DiagnosticIDs DiagIDs;
+
+  // Build up a set of FIDs that we use by scanning the locations and
+  // ranges of the diagnostics.
+  FIDMap FM;
+  llvm::SmallVector<FileID, 10> Fids;
+
+  for (llvm::ArrayRef<StoredDiagnostic>::iterator
+         I = diags.begin(), E = diags.end(); I != E; ++I) {
+    const StoredDiagnostic &D = *I;
+
+    AddFID(FM, Fids, SM, D.getLocation());
+
+    for (StoredDiagnostic::range_iterator
+           RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) {
+      AddFID(FM, Fids, SM, RI->getBegin());
+      AddFID(FM, Fids, SM, RI->getEnd());
+    }
+  }
+
+  std::string errMsg;
+  llvm::raw_fd_ostream o(outPath.c_str(), errMsg);
+  if (!errMsg.empty()) {
+    llvm::errs() << "error: could not create file: " << outPath << '\n';
+    return;
+  }
+
+  // Write the plist header.
+  o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+  "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+  "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+  "<plist version=\"1.0\">\n";
+
+  // Write the root object: a <dict> containing...
+  //  - "files", an <array> mapping from FIDs to file names
+  //  - "diagnostics", an <array> containing the diagnostics
+  o << "<dict>\n"
+       " <key>files</key>\n"
+       " <array>\n";
+
+  for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
+       I!=E; ++I) {
+    o << "  ";
+    EmitString(o, SM.getFileEntryForID(*I)->getName()) << '\n';
+  }
+
+  o << " </array>\n"
+       " <key>diagnostics</key>\n"
+       " <array>\n";
+
+  for (llvm::ArrayRef<StoredDiagnostic>::iterator
+         DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {
+    
+    const StoredDiagnostic &D = *DI;
+
+    if (D.getLevel() == Diagnostic::Ignored)
+      continue;
+
+    o << "  <dict>\n";
+
+    // Output the diagnostic.
+    o << "   <key>description</key>";
+    EmitString(o, D.getMessage()) << '\n';
+    o << "   <key>category</key>";
+    EmitString(o, DiagIDs.getCategoryNameFromID(
+                          DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n';
+    o << "   <key>type</key>";
+    if (D.getLevel() >= Diagnostic::Error)
+      EmitString(o, "error") << '\n';
+    else if (D.getLevel() == Diagnostic::Warning)
+      EmitString(o, "warning") << '\n';
+    else
+      EmitString(o, "note") << '\n';
+
+    // Output the location of the bug.
+    o << "  <key>location</key>\n";
+    EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2);
+
+    // Output the ranges (if any).
+    StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end();
+
+    if (RI != RE) {
+      o << "   <key>ranges</key>\n";
+      o << "   <array>\n";
+      for (; RI != RE; ++RI)
+        EmitRange(o, SM, LangOpts, *RI, FM, 4);
+      o << "   </array>\n";
+    }
+
+    // Close up the entry.
+    o << "  </dict>\n";
+  }
+
+  o << " </array>\n";
+
+  // Finish.
+  o << "</dict>\n</plist>";
+}

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Tue Jul 19 12:20:03 2011
@@ -1444,6 +1444,9 @@
         CmdArgs.push_back("-arcmt-migrate");
         CmdArgs.push_back("-arcmt-migrate-directory");
         CmdArgs.push_back(A->getValue(Args));
+
+        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output);
+        Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_emit_arc_errors);
         break;
       }
     }

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Tue Jul 19 12:20:03 2011
@@ -439,6 +439,12 @@
     Res.push_back("-arcmt-migrate-directory");
     Res.push_back(Opts.ARCMTMigrateDir);
   }
+  if (!Opts.ARCMTMigrateReportOut.empty()) {
+    Res.push_back("-arcmt-migrate-report-output");
+    Res.push_back(Opts.ARCMTMigrateReportOut);
+  }
+  if (Opts.ARCMTMigrateEmitARCErrors)
+    Res.push_back("-arcmt-migrate-emit-errors");
 
   bool NeedLang = false;
   for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
@@ -1278,6 +1284,10 @@
     }
   }
   Opts.ARCMTMigrateDir = Args.getLastArgValue(OPT_arcmt_migrate_directory);
+  Opts.ARCMTMigrateReportOut
+    = Args.getLastArgValue(OPT_arcmt_migrate_report_output);
+  Opts.ARCMTMigrateEmitARCErrors
+    = Args.hasArg(OPT_arcmt_migrate_emit_arc_errors);
 
   InputKind DashX = IK_None;
   if (const Arg *A = Args.getLastArg(OPT_x)) {

Modified: cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp?rev=135491&r1=135490&r2=135491&view=diff
==============================================================================
--- cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp (original)
+++ cfe/trunk/lib/FrontendTool/ExecuteCompilerInvocation.cpp Tue Jul 19 12:20:03 2011
@@ -100,7 +100,10 @@
     Act = new arcmt::ModifyAction(Act);
     break;
   case FrontendOptions::ARCMT_Migrate:
-    Act = new arcmt::MigrateAction(Act, CI.getFrontendOpts().ARCMTMigrateDir);
+    Act = new arcmt::MigrateAction(Act,
+                                   CI.getFrontendOpts().ARCMTMigrateDir,
+                                   CI.getFrontendOpts().ARCMTMigrateReportOut,
+                                CI.getFrontendOpts().ARCMTMigrateEmitARCErrors);
     break;
   }
 

Added: cfe/trunk/test/ARCMT/migrate-emit-errors.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/migrate-emit-errors.m?rev=135491&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/migrate-emit-errors.m (added)
+++ cfe/trunk/test/ARCMT/migrate-emit-errors.m Tue Jul 19 12:20:03 2011
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -arcmt-migrate -arcmt-migrate-directory %t -arcmt-migrate-emit-errors %s -fobjc-nonfragile-abi 2>&1 | FileCheck %s
+// RUN: rm -rf %t
+
+ at protocol NSObject
+- (oneway void)release;
+ at end
+
+void test(id p) {
+  [p release];
+}
+
+// CHECK: error: ARC forbids explicit message send of 'release'
\ No newline at end of file

Added: cfe/trunk/test/ARCMT/migrate-plist-output.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ARCMT/migrate-plist-output.m?rev=135491&view=auto
==============================================================================
--- cfe/trunk/test/ARCMT/migrate-plist-output.m (added)
+++ cfe/trunk/test/ARCMT/migrate-plist-output.m Tue Jul 19 12:20:03 2011
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -arcmt-migrate -arcmt-migrate-directory %t.dir -arcmt-migrate-report-output %t.plist %s -fobjc-nonfragile-abi
+// RUN: FileCheck %s -input-file=%t.plist
+// RUN: rm -rf %t.dir
+
+ at protocol NSObject
+- (oneway void)release;
+ at end
+
+void test(id p) {
+  [p release];
+}
+
+// CHECK: <?xml version="1.0" encoding="UTF-8"?>
+// CHECK: <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+// CHECK: <plist version="1.0">
+// CHECK: <dict>
+// CHECK:  <key>files</key>
+// CHECK:  <array>
+// CHECK:  </array>
+// CHECK:  <key>diagnostics</key>
+// CHECK:  <array>
+// CHECK:   <dict>
+// CHECK:    <key>description</key><string>ARC forbids explicit message send of 'release'</string>
+// CHECK:    <key>category</key><string>Automatic Reference Counting Issue</string>
+// CHECK:    <key>type</key><string>error</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>10</integer>
+// CHECK:    <key>col</key><integer>4</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:    <key>ranges</key>
+// CHECK:    <array>
+// CHECK:     <array>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>10</integer>
+// CHECK:       <key>col</key><integer>6</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>10</integer>
+// CHECK:       <key>col</key><integer>12</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:     </array>
+// CHECK:    </array>
+// CHECK:   </dict>
+// CHECK:  </array>
+// CHECK: </dict>
+// CHECK: </plist>





More information about the cfe-commits mailing list