18f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===-- arcmt-test.cpp - ARC Migration Tool testbed -----------------------===//
28f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
38f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//                     The LLVM Compiler Infrastructure
48f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
58f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// This file is distributed under the University of Illinois Open Source
68f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// License. See LICENSE.TXT for details.
78f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//
88f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
98f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/ARCMigrate/ARCMT.h"
118f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Frontend/ASTUnit.h"
128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Frontend/TextDiagnosticPrinter.h"
138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Frontend/Utils.h"
14f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "clang/Frontend/VerifyDiagnosticConsumer.h"
158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "clang/Lex/Preprocessor.h"
1669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis#include "llvm/Support/FileSystem.h"
17f59edb96b2d0bfe612b732f19519ab84bb995bd4Chandler Carruth#include "llvm/Support/MemoryBuffer.h"
188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall#include "llvm/Support/Signals.h"
1969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis#include "llvm/Support/system_error.h"
208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
218f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace clang;
228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallusing namespace arcmt;
238f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic llvm::cl::opt<bool>
258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallCheckOnly("check-only",
268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      llvm::cl::desc("Just check for issues that need to be handled manually"));
278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//static llvm::cl::opt<bool>
298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//TestResultForARC("test-result",
308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//llvm::cl::desc("Test the result of transformations by parsing it in ARC mode"));
318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic llvm::cl::opt<bool>
338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallOutputTransformations("output-transformations",
348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall                      llvm::cl::desc("Print the source transformations"));
358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic llvm::cl::opt<bool>
378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallVerifyDiags("verify",llvm::cl::desc("Verify emitted diagnostics and warnings"));
388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic llvm::cl::opt<bool>
408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallVerboseOpt("v", llvm::cl::desc("Enable verbose output"));
418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
4269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidisstatic llvm::cl::opt<bool>
4369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios KyrtzidisVerifyTransformedFiles("verify-transformed-files",
4469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidisllvm::cl::desc("Read pairs of file mappings (typically the output of "
4569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis               "c-arcmt-test) and compare their contents with the filenames "
4669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis               "provided in command-line"));
4769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
4869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidisstatic llvm::cl::opt<std::string>
4969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios KyrtzidisRemappingsFile("remappings-file",
5069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis               llvm::cl::desc("Pairs of file mappings (typically the output of "
5169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis               "c-arcmt-test)"));
5269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
5369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidisstatic llvm::cl::list<std::string>
5469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios KyrtzidisResultFiles(llvm::cl::Positional, llvm::cl::desc("<filename>..."));
5569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic llvm::cl::extrahelp extraHelp(
578f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  "\nusage with compiler args: arcmt-test [options] --args [compiler flags]\n");
588f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
598f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// This function isn't referenced outside its translation unit, but it
608f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// can't use the "static" keyword because its address is used for
618f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// GetMainExecutable (since some platforms don't support taking the
628f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// address of main, and some platforms can't implement GetMainExecutable
638f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// without being given the address of a function in the main executable).
64ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindolastd::string GetExecutablePath(const char *Argv0) {
658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // This just needs to be some symbol in the binary; C++ doesn't
668f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // allow taking the address of ::main however.
678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
68ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindola  return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void printSourceLocation(SourceLocation loc, ASTContext &Ctx,
725f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                raw_ostream &OS);
738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void printSourceRange(CharSourceRange range, ASTContext &Ctx,
745f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                             raw_ostream &OS);
758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallnamespace {
778f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
788f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallclass PrintTransforms : public MigrationProcess::RewriteListener {
798f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  ASTContext *Ctx;
805f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  raw_ostream &OS;
818f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallpublic:
835f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  PrintTransforms(raw_ostream &OS)
848f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    : Ctx(0), OS(OS) { }
858f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  virtual void start(ASTContext &ctx) { Ctx = &ctx; }
878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  virtual void finish() { Ctx = 0; }
888f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
895f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner  virtual void insert(SourceLocation loc, StringRef text) {
908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    assert(Ctx);
918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    OS << "Insert: ";
928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    printSourceLocation(loc, *Ctx, OS);
938f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    OS << " \"" << text << "\"\n";
948f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  virtual void remove(CharSourceRange range) {
978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    assert(Ctx);
988f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    OS << "Remove: ";
998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    printSourceRange(range, *Ctx, OS);
1008f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    OS << '\n';
1018f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1028f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall};
1038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall} // anonymous namespace
1058f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1065f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic bool checkForMigration(StringRef resourcesPath,
1072d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner                              ArrayRef<const char *> Args) {
10802c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
10978ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *DiagClient =
11002c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
111c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
112c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
11302c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor      new DiagnosticsEngine(DiagID, &*DiagOpts, DiagClient));
1148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // Chain in -verify checker, if requested.
115621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie  VerifyDiagnosticConsumer *verifyDiag = 0;
1168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (VerifyDiags) {
117621bc69624599da62abd9bc9e5edd8a63ac99fe6David Blaikie    verifyDiag = new VerifyDiagnosticConsumer(*Diags);
1188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    Diags->setClient(verifyDiag);
1198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
121eaed19e241359fb37da0269a64311e57cd53b83cArgyrios Kyrtzidis  CompilerInvocation CI;
1228fdb6dee2da0dee97d64fe12eda46fb318414de9Dylan Noblesmith  if (!CompilerInvocation::CreateFromArgs(CI, Args.begin(), Args.end(), *Diags))
1238fdb6dee2da0dee97d64fe12eda46fb318414de9Dylan Noblesmith    return true;
1248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
125eaed19e241359fb37da0269a64311e57cd53b83cArgyrios Kyrtzidis  if (CI.getFrontendOpts().Inputs.empty()) {
1268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    llvm::errs() << "error: no input files\n";
1278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
1288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
130d3b74d9ca4f239a7a90ad193378c494306c57352Ted Kremenek  if (!CI.getLangOpts()->ObjC1)
1318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return false;
1328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1331f6b2b5c82b2d2d3935b0db76352a04e9877b73fDouglas Gregor  arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0],
134e665d6929e11796620ff799bc0186ebd747bfc76Argyrios Kyrtzidis                              Diags->getClient());
135e665d6929e11796620ff799bc0186ebd747bfc76Argyrios Kyrtzidis  return Diags->getClient()->getNumErrors() > 0;
1368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic void printResult(FileRemapper &remapper, raw_ostream &OS) {
13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  PreprocessorOptions PPOpts;
14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  remapper.applyMappings(PPOpts);
1418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // The changed files will be in memory buffers, print them.
1428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (unsigned i = 0, e = PPOpts.RemappedFileBuffers.size(); i != e; ++i) {
1438f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    const llvm::MemoryBuffer *mem = PPOpts.RemappedFileBuffers[i].second;
1448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    OS << mem->getBuffer();
1458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
1478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1485f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic bool performTransformations(StringRef resourcesPath,
1492d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner                                   ArrayRef<const char *> Args) {
1508f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // Check first.
1518f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (checkForMigration(resourcesPath, Args))
1528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
1538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
15402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
15578ad0b98848c17a0a11847fa1d456e2dfec8aa2fDavid Blaikie  DiagnosticConsumer *DiagClient =
15602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor    new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
157c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
158c93dc7889644293e318e19d82830ea2acc45b678Dylan Noblesmith  IntrusiveRefCntPtr<DiagnosticsEngine> TopDiags(
15902c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor      new DiagnosticsEngine(DiagID, &*DiagOpts, &*DiagClient));
1608f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
161eaed19e241359fb37da0269a64311e57cd53b83cArgyrios Kyrtzidis  CompilerInvocation origCI;
1628fdb6dee2da0dee97d64fe12eda46fb318414de9Dylan Noblesmith  if (!CompilerInvocation::CreateFromArgs(origCI, Args.begin(), Args.end(),
1638fdb6dee2da0dee97d64fe12eda46fb318414de9Dylan Noblesmith                                     *TopDiags))
1648fdb6dee2da0dee97d64fe12eda46fb318414de9Dylan Noblesmith    return true;
1658f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
166eaed19e241359fb37da0269a64311e57cd53b83cArgyrios Kyrtzidis  if (origCI.getFrontendOpts().Inputs.empty()) {
1678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    llvm::errs() << "error: no input files\n";
1688f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return true;
1698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
171d3b74d9ca4f239a7a90ad193378c494306c57352Ted Kremenek  if (!origCI.getLangOpts()->ObjC1)
1728f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return false;
1738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
174eaed19e241359fb37da0269a64311e57cd53b83cArgyrios Kyrtzidis  MigrationProcess migration(origCI, DiagClient);
1758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
176e0ac7454bae910ab3d67a92f6e2e5046d3bb8c1aArgyrios Kyrtzidis  std::vector<TransformFn>
177bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian    transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(),
178bbdfad581fa300fa0d162d968ec14de3c95fc760Fariborz Jahanian                                 origCI.getMigratorOpts().NoFinalizeRemoval);
1798f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  assert(!transforms.empty());
1808f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1811e4c01b79273b9cd4e9e9ecfd3422df3900b8356Dylan Noblesmith  OwningPtr<PrintTransforms> transformPrinter;
1828f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (OutputTransformations)
1838f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    transformPrinter.reset(new PrintTransforms(llvm::outs()));
1848f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1858f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (unsigned i=0, e = transforms.size(); i != e; ++i) {
1868f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    bool err = migration.applyTransform(transforms[i], transformPrinter.get());
1878f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (err) return true;
1888f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1898f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (VerboseOpt) {
1908f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      if (i == e-1)
1918f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall        llvm::errs() << "\n##### FINAL RESULT #####\n";
1928f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      else
1938f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall        llvm::errs() << "\n##### OUTPUT AFTER "<< i+1 <<". TRANSFORMATION #####\n";
1948f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      printResult(migration.getRemapper(), llvm::errs());
1958f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      llvm::errs() << "\n##########################\n\n";
1968f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    }
1978f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
1988f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
1998f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!OutputTransformations)
2008f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    printResult(migration.getRemapper(), llvm::outs());
2018f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2028f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  // FIXME: TestResultForARC
2038f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2048f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return false;
2058f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
2068f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
2075f9e272e632e951b1efe824cd16acb4d96077930Chris Lattnerstatic bool filesCompareEqual(StringRef fname1, StringRef fname2) {
20869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  using namespace llvm;
20969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
21069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  OwningPtr<MemoryBuffer> file1;
21169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  MemoryBuffer::getFile(fname1, file1);
21269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (!file1)
21369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return false;
21469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
21569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  OwningPtr<MemoryBuffer> file2;
21669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  MemoryBuffer::getFile(fname2, file2);
21769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (!file2)
21869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return false;
21969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
22069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  return file1->getBuffer() == file2->getBuffer();
22169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis}
22269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
2232d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattnerstatic bool verifyTransformedFiles(ArrayRef<std::string> resultFiles) {
22469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  using namespace llvm;
22569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
22669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  assert(!resultFiles.empty());
22769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
22869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  std::map<StringRef, StringRef> resultMap;
22969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
23069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  for (ArrayRef<std::string>::iterator
23169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis         I = resultFiles.begin(), E = resultFiles.end(); I != E; ++I) {
23269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    StringRef fname(*I);
23369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (!fname.endswith(".result")) {
23469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: filename '" << fname
23569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis                   << "' does not have '.result' extension\n";
23669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return true;
23769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
23869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    resultMap[sys::path::stem(fname)] = fname;
23969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
24069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
24169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  OwningPtr<MemoryBuffer> inputBuf;
24269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (RemappingsFile.empty())
24369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    MemoryBuffer::getSTDIN(inputBuf);
24469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  else
24569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    MemoryBuffer::getFile(RemappingsFile, inputBuf);
24669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (!inputBuf) {
24769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    errs() << "error: could not read remappings input\n";
24869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return true;
24969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
25069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
25169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  SmallVector<StringRef, 8> strs;
25269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  inputBuf->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
25369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
25469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (strs.empty()) {
25569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    errs() << "error: no files to verify from stdin\n";
25669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return true;
25769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
25869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (strs.size() % 2 != 0) {
25969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    errs() << "error: files to verify are not original/result pairs\n";
26069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return true;
26169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
26269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
26369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  for (unsigned i = 0, e = strs.size(); i != e; i += 2) {
26469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    StringRef inputOrigFname = strs[i];
26569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    StringRef inputResultFname = strs[i+1];
26669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
26769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    std::map<StringRef, StringRef>::iterator It;
26869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    It = resultMap.find(sys::path::filename(inputOrigFname));
26969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (It == resultMap.end()) {
27069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: '" << inputOrigFname << "' is not in the list of "
27169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis             << "transformed files to verify\n";
27269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return true;
27369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
27469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
27569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    bool exists = false;
27669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    sys::fs::exists(It->second, exists);
27769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (!exists) {
27869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: '" << It->second << "' does not exist\n";
27969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return true;
28069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
28169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    sys::fs::exists(inputResultFname, exists);
28269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (!exists) {
28369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: '" << inputResultFname << "' does not exist\n";
28469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return true;
28569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
28669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
28769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (!filesCompareEqual(It->second, inputResultFname)) {
28869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: '" << It->second << "' is different than "
28969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis             << "'" << inputResultFname << "'\n";
29069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return true;
29169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
29269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
29369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    resultMap.erase(It);
29469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
29569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
29669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (!resultMap.empty()) {
29769325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    for (std::map<StringRef, StringRef>::iterator
29869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis           I = resultMap.begin(), E = resultMap.end(); I != E; ++I)
29969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      errs() << "error: '" << I->second << "' was not verified!\n";
30069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return true;
30169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
30269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
30369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  return false;
30469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis}
30569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
3068f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
3078f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// Misc. functions.
3088f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
3098f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3108f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void printSourceLocation(SourceLocation loc, ASTContext &Ctx,
3115f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                                raw_ostream &OS) {
3128f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  SourceManager &SM = Ctx.getSourceManager();
3138f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  PresumedLoc PL = SM.getPresumedLoc(loc);
3148f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3158f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << llvm::sys::path::filename(PL.getFilename());
3168f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << ":" << PL.getLine() << ":"
3178f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall            << PL.getColumn();
3188f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
3198f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3208f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallstatic void printSourceRange(CharSourceRange range, ASTContext &Ctx,
3215f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner                             raw_ostream &OS) {
3228f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  SourceManager &SM = Ctx.getSourceManager();
3234e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  const LangOptions &langOpts = Ctx.getLangOpts();
3248f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3258f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  PresumedLoc PL = SM.getPresumedLoc(range.getBegin());
3268f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3278f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << llvm::sys::path::filename(PL.getFilename());
3288f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << " [" << PL.getLine() << ":"
3298f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall             << PL.getColumn();
3308f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << " - ";
3318f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3328f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  SourceLocation end = range.getEnd();
3338f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  PL = SM.getPresumedLoc(end);
3348f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3358f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  unsigned endCol = PL.getColumn() - 1;
3368f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (!range.isTokenRange())
3378f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    endCol += Lexer::MeasureTokenLength(end, SM, langOpts);
3388f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  OS << PL.getLine() << ":" << endCol << "]";
3398f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
3408f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3418f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
3428f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall// Command line processing.
3438f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall//===----------------------------------------------------------------------===//
3448f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3458f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCallint main(int argc, const char **argv) {
3468f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
3478f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  llvm::sys::PrintStackTraceOnErrorSignal();
3488f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3498f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  std::string
3508f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    resourcesPath = CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
3518f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3528f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  int optargc = 0;
3538f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  for (; optargc != argc; ++optargc) {
3548f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    if (StringRef(argv[optargc]) == "--args")
3558f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall      break;
3568f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
3576bd17d2f2e6e498b0ff01e2e755f044de046d138David Blaikie  llvm::cl::ParseCommandLineOptions(optargc, argv, "arcmt-test");
35869325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
35969325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  if (VerifyTransformedFiles) {
36069325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    if (ResultFiles.empty()) {
36169325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      llvm::cl::PrintHelpMessage();
36269325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis      return 1;
36369325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    }
36469325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis    return verifyTransformedFiles(ResultFiles);
36569325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis  }
36669325d5b7cfecf1b3128745efc33612aedf1b8b4Argyrios Kyrtzidis
3678f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (optargc == argc) {
3688f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    llvm::cl::PrintHelpMessage();
3698f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return 1;
3708f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  }
3718f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3722d3ba4f5a923a90c3fc290ddfba5e36c2d0a9b46Chris Lattner  ArrayRef<const char*> Args(argv+optargc+1, argc-optargc-1);
3738f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3748f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  if (CheckOnly)
3758f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall    return checkForMigration(resourcesPath, Args);
3768f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall
3778f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall  return performTransformations(resourcesPath, Args);
3788f0e8d22960d56f8390f4971e2c0f2f0a0884602John McCall}
379