summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-09 20:00:58 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2011-07-09 20:00:58 +0000
commit69325d5b7cfecf1b3128745efc33612aedf1b8b4 (patch)
treeddd1627268276e97d9a2394625f3aff4b904f5ec /tools
parent8dd5cdfc462026648b480adaf774e24bc620f7c3 (diff)
downloadclang-69325d5b7cfecf1b3128745efc33612aedf1b8b4.tar.gz
clang-69325d5b7cfecf1b3128745efc33612aedf1b8b4.tar.bz2
clang-69325d5b7cfecf1b3128745efc33612aedf1b8b4.tar.xz
[arcmt] Introduce new '-ccc-arcmt-migrate <path>' ARC migration driver option.
This is a new mode of migration, where we avoid modifying the original files but we emit temporary files instead. <path> will be used to keep migration process metadata. Currently the temporary files that are produced are put in the system's temp directory but we can put them in the <path> if is necessary. Also introduce new ARC migration functions in libclang whose only purpose, currently, is to accept <path> and provide pairs of original file/transformed file to map from the originals to the files after transformations are applied. Finally introduce the c-arcmt-test utility that exercises the new libclang functions, update arcmt-test, and add tests for the whole process. rdar://9735086. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134844 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/CMakeLists.txt1
-rw-r--r--tools/Makefile2
-rw-r--r--tools/arcmt-test/arcmt-test.cpp125
-rw-r--r--tools/c-arcmt-test/CMakeLists.txt14
-rw-r--r--tools/c-arcmt-test/Makefile24
-rw-r--r--tools/c-arcmt-test/c-arcmt-test.c82
-rw-r--r--tools/libclang/ARCMigrate.cpp96
-rw-r--r--tools/libclang/CMakeLists.txt3
-rw-r--r--tools/libclang/Makefile4
-rw-r--r--tools/libclang/libclang.darwin.exports5
-rw-r--r--tools/libclang/libclang.exports5
11 files changed, 357 insertions, 4 deletions
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 8f8aa097ce..aff437fd46 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(libclang)
add_subdirectory(c-index-test)
add_subdirectory(arcmt-test)
+add_subdirectory(c-arcmt-test)
add_subdirectory(driver)
diff --git a/tools/Makefile b/tools/Makefile
index e0afc6a04a..bfd2a641ec 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ..
-DIRS := driver libclang c-index-test arcmt-test
+DIRS := driver libclang c-index-test arcmt-test c-arcmt-test
include $(CLANG_LEVEL)/../../Makefile.config
diff --git a/tools/arcmt-test/arcmt-test.cpp b/tools/arcmt-test/arcmt-test.cpp
index 702e13a414..eb0f56943f 100644
--- a/tools/arcmt-test/arcmt-test.cpp
+++ b/tools/arcmt-test/arcmt-test.cpp
@@ -14,7 +14,9 @@
#include "clang/Frontend/Utils.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Signals.h"
+#include "llvm/Support/system_error.h"
using namespace clang;
using namespace arcmt;
@@ -37,6 +39,20 @@ VerifyDiags("verify",llvm::cl::desc("Verify emitted diagnostics and warnings"));
static llvm::cl::opt<bool>
VerboseOpt("v", llvm::cl::desc("Enable verbose output"));
+static llvm::cl::opt<bool>
+VerifyTransformedFiles("verify-transformed-files",
+llvm::cl::desc("Read pairs of file mappings (typically the output of "
+ "c-arcmt-test) and compare their contents with the filenames "
+ "provided in command-line"));
+
+static llvm::cl::opt<std::string>
+RemappingsFile("remappings-file",
+ llvm::cl::desc("Pairs of file mappings (typically the output of "
+ "c-arcmt-test)"));
+
+static llvm::cl::list<std::string>
+ResultFiles(llvm::cl::Positional, llvm::cl::desc("<filename>..."));
+
static llvm::cl::extrahelp extraHelp(
"\nusage with compiler args: arcmt-test [options] --args [compiler flags]\n");
@@ -183,6 +199,105 @@ static bool performTransformations(llvm::StringRef resourcesPath,
return false;
}
+static bool filesCompareEqual(llvm::StringRef fname1, llvm::StringRef fname2) {
+ using namespace llvm;
+
+ OwningPtr<MemoryBuffer> file1;
+ MemoryBuffer::getFile(fname1, file1);
+ if (!file1)
+ return false;
+
+ OwningPtr<MemoryBuffer> file2;
+ MemoryBuffer::getFile(fname2, file2);
+ if (!file2)
+ return false;
+
+ return file1->getBuffer() == file2->getBuffer();
+}
+
+static bool verifyTransformedFiles(llvm::ArrayRef<std::string> resultFiles) {
+ using namespace llvm;
+
+ assert(!resultFiles.empty());
+
+ std::map<StringRef, StringRef> resultMap;
+
+ for (ArrayRef<std::string>::iterator
+ I = resultFiles.begin(), E = resultFiles.end(); I != E; ++I) {
+ StringRef fname(*I);
+ if (!fname.endswith(".result")) {
+ errs() << "error: filename '" << fname
+ << "' does not have '.result' extension\n";
+ return true;
+ }
+ resultMap[sys::path::stem(fname)] = fname;
+ }
+
+ OwningPtr<MemoryBuffer> inputBuf;
+ if (RemappingsFile.empty())
+ MemoryBuffer::getSTDIN(inputBuf);
+ else
+ MemoryBuffer::getFile(RemappingsFile, inputBuf);
+ if (!inputBuf) {
+ errs() << "error: could not read remappings input\n";
+ return true;
+ }
+
+ SmallVector<StringRef, 8> strs;
+ inputBuf->getBuffer().split(strs, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
+
+ if (strs.empty()) {
+ errs() << "error: no files to verify from stdin\n";
+ return true;
+ }
+ if (strs.size() % 2 != 0) {
+ errs() << "error: files to verify are not original/result pairs\n";
+ return true;
+ }
+
+ for (unsigned i = 0, e = strs.size(); i != e; i += 2) {
+ StringRef inputOrigFname = strs[i];
+ StringRef inputResultFname = strs[i+1];
+
+ std::map<StringRef, StringRef>::iterator It;
+ It = resultMap.find(sys::path::filename(inputOrigFname));
+ if (It == resultMap.end()) {
+ errs() << "error: '" << inputOrigFname << "' is not in the list of "
+ << "transformed files to verify\n";
+ return true;
+ }
+
+ bool exists = false;
+ sys::fs::exists(It->second, exists);
+ if (!exists) {
+ errs() << "error: '" << It->second << "' does not exist\n";
+ return true;
+ }
+ sys::fs::exists(inputResultFname, exists);
+ if (!exists) {
+ errs() << "error: '" << inputResultFname << "' does not exist\n";
+ return true;
+ }
+
+ if (!filesCompareEqual(It->second, inputResultFname)) {
+ errs() << "error: '" << It->second << "' is different than "
+ << "'" << inputResultFname << "'\n";
+ return true;
+ }
+
+ resultMap.erase(It);
+ }
+
+ if (!resultMap.empty()) {
+ for (std::map<StringRef, StringRef>::iterator
+ I = resultMap.begin(), E = resultMap.end(); I != E; ++I)
+ errs() << "error: '" << I->second << "' was not verified!\n";
+ return true;
+ }
+
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// Misc. functions.
//===----------------------------------------------------------------------===//
@@ -236,7 +351,15 @@ int main(int argc, const char **argv) {
break;
}
llvm::cl::ParseCommandLineOptions(optargc, const_cast<char **>(argv), "arcmt-test");
-
+
+ if (VerifyTransformedFiles) {
+ if (ResultFiles.empty()) {
+ llvm::cl::PrintHelpMessage();
+ return 1;
+ }
+ return verifyTransformedFiles(ResultFiles);
+ }
+
if (optargc == argc) {
llvm::cl::PrintHelpMessage();
return 1;
diff --git a/tools/c-arcmt-test/CMakeLists.txt b/tools/c-arcmt-test/CMakeLists.txt
new file mode 100644
index 0000000000..bcb963dec3
--- /dev/null
+++ b/tools/c-arcmt-test/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(LLVM_USED_LIBS libclang)
+
+set( LLVM_LINK_COMPONENTS
+ support
+ mc
+ )
+
+add_clang_executable(c-arcmt-test
+ c-arcmt-test.cpp
+ )
+
+set_target_properties(c-arcmt-test
+ PROPERTIES
+ LINKER_LANGUAGE CXX)
diff --git a/tools/c-arcmt-test/Makefile b/tools/c-arcmt-test/Makefile
new file mode 100644
index 0000000000..6737a531ba
--- /dev/null
+++ b/tools/c-arcmt-test/Makefile
@@ -0,0 +1,24 @@
+##===- tools/c-arcmt-test/Makefile -------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+CLANG_LEVEL := ../..
+
+TOOLNAME = c-arcmt-test
+
+# No plugins, optimize startup time.
+TOOL_NO_EXPORTS = 1
+
+# Don't install this. It is used for tests.
+NO_INSTALL = 1
+
+LINK_COMPONENTS := support mc
+USEDLIBS = clang.a clangIndex.a clangFrontend.a clangDriver.a \
+ clangSerialization.a clangParse.a clangSema.a \
+ clangRewrite.a clangAnalysis.a clangAST.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
diff --git a/tools/c-arcmt-test/c-arcmt-test.c b/tools/c-arcmt-test/c-arcmt-test.c
new file mode 100644
index 0000000000..86992da76b
--- /dev/null
+++ b/tools/c-arcmt-test/c-arcmt-test.c
@@ -0,0 +1,82 @@
+/* c-arcmt-test.c */
+
+#include "clang-c/ARCMigrate.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+static int print_remappings(const char *path) {
+ CMTRemap remap;
+ unsigned i, N;
+ CXString origFname;
+ CXString transFname;
+
+ remap = arcmt_getRemappings(path);
+ if (!remap)
+ return 1;
+
+ N = arcmt_remap_getNumFiles(remap);
+ for (i = 0; i != N; ++i) {
+ origFname = arcmt_remap_getOriginalFile(remap, i);
+ transFname = arcmt_remap_getTransformedFile(remap, i);
+
+ fprintf(stdout, "%s\n", clang_getCString(origFname));
+ fprintf(stdout, "%s\n", clang_getCString(transFname));
+
+ clang_disposeString(origFname);
+ clang_disposeString(transFname);
+ }
+
+ arcmt_remap_dispose(remap);
+ return 0;
+}
+
+/******************************************************************************/
+/* Command line processing. */
+/******************************************************************************/
+
+static void print_usage(void) {
+ fprintf(stderr,
+ "usage: c-arcmt-test -arcmt-migrate-directory <path>\n\n\n");
+}
+
+/***/
+
+int carcmttest_main(int argc, const char **argv) {
+ clang_enableStackTraces();
+ if (argc == 3 && strncmp(argv[1], "-arcmt-migrate-directory", 24) == 0)
+ return print_remappings(argv[2]);
+
+ print_usage();
+ return 1;
+}
+
+/***/
+
+/* We intentionally run in a separate thread to ensure we at least minimal
+ * testing of a multithreaded environment (for example, having a reduced stack
+ * size). */
+
+typedef struct thread_info {
+ int argc;
+ const char **argv;
+ int result;
+} thread_info;
+void thread_runner(void *client_data_v) {
+ thread_info *client_data = client_data_v;
+ client_data->result = carcmttest_main(client_data->argc, client_data->argv);
+}
+
+int main(int argc, const char **argv) {
+ thread_info client_data;
+
+ setenv("LIBCLANG_LOGGING", "1", /*overwrite=*/0);
+
+ if (getenv("CINDEXTEST_NOTHREADS"))
+ return carcmttest_main(argc, argv);
+
+ client_data.argc = argc;
+ client_data.argv = argv;
+ clang_executeOnThread(thread_runner, &client_data, 0);
+ return client_data.result;
+}
diff --git a/tools/libclang/ARCMigrate.cpp b/tools/libclang/ARCMigrate.cpp
new file mode 100644
index 0000000000..cd0d8bb64a
--- /dev/null
+++ b/tools/libclang/ARCMigrate.cpp
@@ -0,0 +1,96 @@
+//===- ARCMigrate.cpp - Clang-C ARC Migration Library ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main API hooks in the Clang-C ARC Migration library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-c/ARCMigrate.h"
+
+#include "CXString.h"
+#include "clang/ARCMigrate/ARCMT.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "llvm/Support/FileSystem.h"
+
+using namespace clang;
+using namespace arcmt;
+
+namespace {
+
+struct Remap {
+ std::vector<std::pair<std::string, std::string> > Vec;
+};
+
+} // anonymous namespace.
+
+//===----------------------------------------------------------------------===//
+// libClang public APIs.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+CMTRemap arcmt_getRemappings(const char *migrate_dir_path) {
+ bool Logging = ::getenv("LIBCLANG_LOGGING");
+
+ if (!migrate_dir_path) {
+ if (Logging)
+ llvm::errs() << "arcmt_getRemappings was called with NULL parameter\n";
+ return 0;
+ }
+
+ bool exists = false;
+ llvm::sys::fs::exists(migrate_dir_path, exists);
+ if (!exists) {
+ if (Logging) {
+ llvm::errs() << "Error by arcmt_getRemappings(\"" << migrate_dir_path
+ << "\")\n";
+ llvm::errs() << "\"" << migrate_dir_path << "\" does not exist\n";
+ }
+ return 0;
+ }
+
+ TextDiagnosticBuffer diagBuffer;
+ llvm::OwningPtr<Remap> remap(new Remap());
+
+ bool err = arcmt::getFileRemappings(remap->Vec, migrate_dir_path,&diagBuffer);
+
+ if (err) {
+ if (Logging) {
+ llvm::errs() << "Error by arcmt_getRemappings(\"" << migrate_dir_path
+ << "\")\n";
+ for (TextDiagnosticBuffer::const_iterator
+ I = diagBuffer.err_begin(), E = diagBuffer.err_end(); I != E; ++I)
+ llvm::errs() << I->second << '\n';
+ }
+ return 0;
+ }
+
+ return remap.take();
+}
+
+unsigned arcmt_remap_getNumFiles(CMTRemap map) {
+ return static_cast<Remap *>(map)->Vec.size();
+
+}
+
+CXString arcmt_remap_getOriginalFile(CMTRemap map, unsigned index) {
+ return cxstring::createCXString(static_cast<Remap *>(map)->Vec[index].first,
+ /*DupString =*/ true);
+}
+
+CXString arcmt_remap_getTransformedFile(CMTRemap map, unsigned index) {
+ return cxstring::createCXString(static_cast<Remap *>(map)->Vec[index].second,
+ /*DupString =*/ true);
+}
+
+void arcmt_remap_dispose(CMTRemap map) {
+ delete static_cast<Remap *>(map);
+}
+
+} // end: extern "C"
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index 7a6270d176..9fd731d001 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -1,4 +1,5 @@
set(LLVM_USED_LIBS
+ clangARCMigrate
clangFrontend
clangDriver
clangSerialization
@@ -14,6 +15,7 @@ set( LLVM_LINK_COMPONENTS
)
set(SOURCES
+ ARCMigrate.cpp
CIndex.cpp
CIndexCXX.cpp
CIndexCodeCompletion.cpp
@@ -25,6 +27,7 @@ set(SOURCES
CXString.cpp
CXType.cpp
../../include/clang-c/Index.h
+ ../../include/clang-c/ARCMigrate.h
)
if( LLVM_ENABLE_PIC )
diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile
index e684652aa4..af93088410 100644
--- a/tools/libclang/Makefile
+++ b/tools/libclang/Makefile
@@ -16,8 +16,8 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := support mc
-USEDLIBS = clangFrontend.a clangDriver.a clangSerialization.a clangParse.a \
- clangSema.a clangAnalysis.a clangAST.a clangLex.a clangBasic.a
+USEDLIBS = clangARCMigrate.a clangFrontend.a clangDriver.a clangSerialization.a \
+ clangParse.a clangSema.a clangAnalysis.a clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index df7cda2e7d..a8b466eff5 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -137,3 +137,8 @@ _clang_toggleCrashRecovery
_clang_tokenize
_clang_visitChildren
_clang_visitChildrenWithBlock
+_arcmt_getRemappings
+_arcmt_remap_getNumFiles
+_arcmt_remap_getOriginalFile
+_arcmt_remap_getTransformedFile
+_arcmt_remap_dispose
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index f5e0a304e6..ac6fc3494f 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -137,3 +137,8 @@ clang_toggleCrashRecovery
clang_tokenize
clang_visitChildren
clang_visitChildrenWithBlock
+arcmt_getRemappings
+arcmt_remap_getNumFiles
+arcmt_remap_getOriginalFile
+arcmt_remap_getTransformedFile
+arcmt_remap_dispose