diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-09 20:00:58 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2011-07-09 20:00:58 +0000 |
commit | 69325d5b7cfecf1b3128745efc33612aedf1b8b4 (patch) | |
tree | ddd1627268276e97d9a2394625f3aff4b904f5ec /tools | |
parent | 8dd5cdfc462026648b480adaf774e24bc620f7c3 (diff) | |
download | clang-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.txt | 1 | ||||
-rw-r--r-- | tools/Makefile | 2 | ||||
-rw-r--r-- | tools/arcmt-test/arcmt-test.cpp | 125 | ||||
-rw-r--r-- | tools/c-arcmt-test/CMakeLists.txt | 14 | ||||
-rw-r--r-- | tools/c-arcmt-test/Makefile | 24 | ||||
-rw-r--r-- | tools/c-arcmt-test/c-arcmt-test.c | 82 | ||||
-rw-r--r-- | tools/libclang/ARCMigrate.cpp | 96 | ||||
-rw-r--r-- | tools/libclang/CMakeLists.txt | 3 | ||||
-rw-r--r-- | tools/libclang/Makefile | 4 | ||||
-rw-r--r-- | tools/libclang/libclang.darwin.exports | 5 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 5 |
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 |