summaryrefslogtreecommitdiffstats
path: root/examples
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2011-04-27 16:39:14 +0000
committerManuel Klimek <klimek@google.com>2011-04-27 16:39:14 +0000
commit9a05fa97df4d5e64f740848a7759ecae5e1ed162 (patch)
tree70f5f56fcbe1bd6d3ff66ee1af96fa793fc01923 /examples
parent4d8d803b06804defe25346871c7beb6096540c4a (diff)
This is the next step in building the standalone tools infrastructure:
This patch simplifies writing of standalone Clang tools. As an example, we add clang-check, a tool that runs a syntax only frontend action over a .cc file. When you integrate this into your favorite editor, you get much faster feedback on your compilation errors, thus reducing your feedback cycle especially when writing new code. The tool depends on integration of an outstanding patch to CMake to work which allows you to always have a current compile command database in your cmake output directory when you set CMAKE_EXPORT_COMPILE_COMMANDS. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130306 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'examples')
-rw-r--r--examples/CMakeLists.txt2
-rw-r--r--examples/Tooling/CMakeLists.txt6
-rw-r--r--examples/Tooling/ClangCheck.cpp108
3 files changed, 115 insertions, 1 deletions
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 9a32ee4065..8e16ef1c6c 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,3 +1,3 @@
add_subdirectory(clang-interpreter)
add_subdirectory(PrintFunctionNames)
-
+add_subdirectory(Tooling)
diff --git a/examples/Tooling/CMakeLists.txt b/examples/Tooling/CMakeLists.txt
new file mode 100644
index 0000000000..257d3ea8ea
--- /dev/null
+++ b/examples/Tooling/CMakeLists.txt
@@ -0,0 +1,6 @@
+set(LLVM_USED_LIBS clangTooling clangBasic)
+
+add_clang_executable(clang-check
+ ClangCheck.cpp
+ )
+
diff --git a/examples/Tooling/ClangCheck.cpp b/examples/Tooling/ClangCheck.cpp
new file mode 100644
index 0000000000..9f0b1dde70
--- /dev/null
+++ b/examples/Tooling/ClangCheck.cpp
@@ -0,0 +1,108 @@
+//===- examples/Tooling/ClangCheck.cpp - Clang check tool -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a clang-check tool that runs the
+// clang::SyntaxOnlyAction over a number of translation units.
+//
+// Usage:
+// clang-check <cmake-output-dir> <file1> <file2> ...
+//
+// Where <cmake-output-dir> is a CMake build directory in which a file named
+// compile_commands.json exists (enable -DCMAKE_EXPORT_COMPILE_COMMANDS in
+// CMake to get this output).
+//
+// <file1> ... specify the paths of files in the CMake source tree. This path
+// is looked up in the compile command database. If the path of a file is
+// absolute, it needs to point into CMake's source tree. If the path is
+// relative, the current working directory needs to be in the CMake source
+// tree and the file must be in a subdirectory of the current working
+// directory. "./" prefixes in the relative files will be automatically
+// removed, but the rest of a relative path must be a suffix of a path in
+// the compile command line database.
+//
+// For example, to use clang-check on all files in a subtree of the source
+// tree, use:
+// /path/to/cmake/sources $ find . -name '*.cpp' \
+// |xargs clang-check /path/to/cmake/build
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/OwningPtr.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/system_error.h"
+
+/// \brief Returns the absolute path of 'File', by prepending it with
+/// 'BaseDirectory' if 'File' is not absolute. Otherwise returns 'File'.
+/// If 'File' starts with "./", the returned path will not contain the "./".
+/// Otherwise, the returned path will contain the literal path-concatenation of
+/// 'BaseDirectory' and 'File'.
+///
+/// \param File Either an absolute or relative path.
+/// \param BaseDirectory An absolute path.
+///
+/// FIXME: Put this somewhere where it is more generally available.
+static std::string GetAbsolutePath(
+ llvm::StringRef File, llvm::StringRef BaseDirectory) {
+ assert(llvm::sys::path::is_absolute(BaseDirectory));
+ if (llvm::sys::path::is_absolute(File)) {
+ return File;
+ }
+ llvm::StringRef RelativePath(File);
+ if (RelativePath.startswith("./")) {
+ RelativePath = RelativePath.substr(strlen("./"));
+ }
+ llvm::SmallString<1024> AbsolutePath(BaseDirectory);
+ llvm::sys::path::append(AbsolutePath, RelativePath);
+ return AbsolutePath.str();
+}
+
+int main(int argc, char **argv) {
+ if (argc < 3) {
+ llvm::outs() << "Usage: " << argv[0] << " <cmake-output-dir> "
+ << "<file1> <file2> ...\n";
+ return 1;
+ }
+ // FIXME: We should pull how to find the database into the Tooling package.
+ llvm::OwningPtr<llvm::MemoryBuffer> JsonDatabase;
+ llvm::SmallString<1024> JsonDatabasePath(argv[1]);
+ llvm::sys::path::append(JsonDatabasePath, "compile_commands.json");
+ llvm::error_code Result =
+ llvm::MemoryBuffer::getFile(JsonDatabasePath, JsonDatabase);
+ if (Result != 0) {
+ llvm::outs() << "Error while opening JSON database: " << Result.message()
+ << "\n";
+ return 1;
+ }
+ llvm::StringRef BaseDirectory(::getenv("PWD"));
+ for (int I = 2; I < argc; ++I) {
+ llvm::SmallString<1024> File(GetAbsolutePath(argv[I], BaseDirectory));
+ llvm::outs() << "Processing " << File << ".\n";
+ std::string ErrorMessage;
+ clang::tooling::CompileCommand LookupResult =
+ clang::tooling::FindCompileArgsInJsonDatabase(
+ File.str(), JsonDatabase->getBuffer(), ErrorMessage);
+ if (!LookupResult.CommandLine.empty()) {
+ if (!clang::tooling::RunToolWithFlags(
+ new clang::SyntaxOnlyAction,
+ LookupResult.CommandLine.size(),
+ clang::tooling::CommandLineToArgv(
+ &LookupResult.CommandLine).data())) {
+ llvm::outs() << "Error while processing " << File << ".\n";
+ }
+ } else {
+ llvm::outs() << "Skipping " << File << ". Command line not found.\n";
+ }
+ }
+ return 0;
+}